Skip to content

Commit fdce7a8

Browse files
committed
Version 2.13.2
* Cherry-pick 6d0f90e to stable * Cherry-pick a3767f7 to stable * Cherry-pick ed82bb6 to stable * Cherry-pick 8eba520 to stable
2 parents 375a2d7 + 41caafa commit fdce7a8

File tree

8 files changed

+135
-84
lines changed

8 files changed

+135
-84
lines changed

CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## 2.13.2 - 2021-06-09
2+
3+
This is a patch release that fixes:
4+
5+
* a Dart compiler crash (issue [flutter/flutter#83094][]).
6+
* an analysis server deadlock causing it to stop responding to IDE requests
7+
(issue [#45996][]).
8+
* an analyzer crash when analyzing against `package:meta` `v1.4.0` (issue
9+
[#46183][]).
10+
11+
[flutter/flutter#83094]: https://github.com/flutter/flutter/issues/83094
12+
[#45996]: https://github.com/dart-lang/sdk/issues/45996
13+
[#46183]: https://github.com/dart-lang/sdk/issues/46183
14+
115
## 2.13.1 - 2021-05-25
216

317
This is a patch release that fixes:

pkg/analyzer/lib/src/error/best_practices_verifier.dart

+19-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ import 'package:meta/meta_meta.dart';
4141
class BestPracticesVerifier extends RecursiveAstVisitor<void> {
4242
static const String _TO_INT_METHOD_NAME = "toInt";
4343

44+
static final Map<String, TargetKind> _targetKindsByName = {
45+
for (final kind in TargetKind.values) kind.toString(): kind,
46+
};
47+
4448
/// The class containing the AST nodes being visited, or `null` if we are not
4549
/// in the scope of a class.
4650
ClassElementImpl? _enclosingClass;
@@ -1596,9 +1600,23 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
15961600
if (annotation.isTarget) {
15971601
var value = annotation.computeConstantValue()!;
15981602
var kinds = <TargetKind>{};
1603+
15991604
for (var kindObject in value.getField('kinds')!.toSetValue()!) {
1605+
// We can't directly translate the index from the analyzed TargetKind
1606+
// constant to TargetKinds.values because the analyzer from the SDK
1607+
// may have been compiled with a different version of pkg:meta.
16001608
var index = kindObject.getField('index')!.toIntValue()!;
1601-
kinds.add(TargetKind.values[index]);
1609+
var targetKindClass =
1610+
(kindObject.type as InterfaceType).element as EnumElementImpl;
1611+
// Instead, map constants to their TargetKind by comparing getter
1612+
// names.
1613+
var getter = targetKindClass.constants[index];
1614+
var name = 'TargetKind.${getter.name}';
1615+
1616+
var foundTargetKind = _targetKindsByName[name];
1617+
if (foundTargetKind != null) {
1618+
kinds.add(foundTargetKind);
1619+
}
16021620
}
16031621
return kinds;
16041622
}

runtime/bin/file_system_watcher_macos.cc

+13-60
Original file line numberDiff line numberDiff line change
@@ -82,89 +82,44 @@ class FSEventsWatcher {
8282
void set_ref(FSEventStreamRef ref) { ref_ = ref; }
8383

8484
void Start() {
85-
// Schedule StartCallback to be executed in the RunLoop.
86-
CFRunLoopTimerContext context;
87-
memset(&context, 0, sizeof(context));
88-
context.info = this;
89-
CFRunLoopTimerRef timer =
90-
CFRunLoopTimerCreate(NULL, 0, 0, 0, 0, Node::StartCallback, &context);
91-
CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes);
92-
CFRelease(timer);
93-
watcher_->monitor_.Enter();
94-
while (!ready_) {
95-
watcher_->monitor_.Wait(Monitor::kNoTimeout);
96-
}
97-
watcher_->monitor_.Exit();
98-
}
99-
100-
static void StartCallback(CFRunLoopTimerRef timer, void* info) {
101-
Node* node = reinterpret_cast<Node*>(info);
102-
ASSERT(Thread::Compare(node->watcher_->threadId_,
103-
Thread::GetCurrentThreadId()));
10485
FSEventStreamContext context;
10586
memset(&context, 0, sizeof(context));
106-
context.info = reinterpret_cast<void*>(node);
87+
context.info = reinterpret_cast<void*>(this);
10788
CFArrayRef array = CFArrayCreate(
108-
NULL, reinterpret_cast<const void**>(&node->path_ref_), 1, NULL);
89+
NULL, reinterpret_cast<const void**>(&path_ref_), 1, NULL);
10990
FSEventStreamRef ref = FSEventStreamCreate(
11091
NULL, Callback, &context, array, kFSEventStreamEventIdSinceNow, 0.10,
11192
kFSEventStreamCreateFlagFileEvents);
11293
CFRelease(array);
11394

114-
node->set_ref(ref);
95+
set_ref(ref);
96+
ready_.store(true, std::memory_order_release);
11597

116-
FSEventStreamScheduleWithRunLoop(node->ref_, node->watcher_->run_loop_,
98+
FSEventStreamScheduleWithRunLoop(ref_, watcher_->run_loop_,
11799
kCFRunLoopDefaultMode);
118100

119-
FSEventStreamStart(node->ref_);
120-
FSEventStreamFlushSync(node->ref_);
121-
122-
node->watcher_->monitor_.Enter();
123-
node->ready_ = true;
124-
node->watcher_->monitor_.Notify();
125-
node->watcher_->monitor_.Exit();
101+
FSEventStreamStart(ref_);
102+
FSEventStreamFlushSync(ref_);
126103
}
127104

128105
void Stop() {
129-
// Schedule StopCallback to be executed in the RunLoop.
130106
ASSERT(ready_);
131-
CFRunLoopTimerContext context;
132-
memset(&context, 0, sizeof(context));
133-
context.info = this;
134-
CFRunLoopTimerRef timer =
135-
CFRunLoopTimerCreate(NULL, 0, 0, 0, 0, StopCallback, &context);
136-
CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes);
137-
CFRelease(timer);
138-
watcher_->monitor_.Enter();
139-
while (ready_) {
140-
watcher_->monitor_.Wait(Monitor::kNoTimeout);
141-
}
142-
watcher_->monitor_.Exit();
143-
}
144-
145-
static void StopCallback(CFRunLoopTimerRef timer, void* info) {
146-
Node* node = reinterpret_cast<Node*>(info);
147-
ASSERT(Thread::Compare(node->watcher_->threadId_,
148-
Thread::GetCurrentThreadId()));
149-
FSEventStreamStop(node->ref_);
150-
FSEventStreamInvalidate(node->ref_);
151-
FSEventStreamRelease(node->ref_);
152-
node->watcher_->monitor_.Enter();
153-
node->ready_ = false;
154-
node->watcher_->monitor_.Notify();
155-
node->watcher_->monitor_.Exit();
107+
FSEventStreamStop(ref_);
108+
FSEventStreamInvalidate(ref_);
109+
FSEventStreamRelease(ref_);
110+
ready_.store(false, std::memory_order_release);
156111
}
157112

158113
FSEventsWatcher* watcher() const { return watcher_; }
159-
bool ready() const { return ready_; }
114+
bool ready() const { return ready_.load(std::memory_order_acquire); }
160115
intptr_t base_path_length() const { return base_path_length_; }
161116
int read_fd() const { return read_fd_; }
162117
int write_fd() const { return write_fd_; }
163118
bool recursive() const { return recursive_; }
164119

165120
private:
166121
FSEventsWatcher* watcher_;
167-
bool ready_;
122+
std::atomic<bool> ready_;
168123
intptr_t base_path_length_;
169124
CFStringRef path_ref_;
170125
int read_fd_;
@@ -266,8 +221,6 @@ class FSEventsWatcher {
266221
Node* node = reinterpret_cast<Node*>(client);
267222
ASSERT(Thread::Compare(node->watcher()->threadId_,
268223
Thread::GetCurrentThreadId()));
269-
// `ready` is set on same thread as this callback is invoked, so we don't
270-
// need to lock here.
271224
if (!node->ready()) {
272225
return;
273226
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// Verifies that compiler doesn't crash due to incompatible types
6+
// when unboxing input of a Phi.
7+
// Regression test for https://github.com/flutter/flutter/issues/83094.
8+
9+
import 'package:expect/expect.dart';
10+
11+
class A {
12+
@pragma('vm:never-inline')
13+
double getMaxIntrinsicWidth() => 1.toDouble();
14+
}
15+
16+
A _leading = A();
17+
18+
@pragma('vm:never-inline')
19+
double computeMaxIntrinsicWidth(double height, double horizontalPadding) {
20+
final leadingWidth =
21+
_leading == null ? 0 : _leading.getMaxIntrinsicWidth() as int;
22+
return horizontalPadding + leadingWidth;
23+
}
24+
25+
main() {
26+
Expect.throws(() => computeMaxIntrinsicWidth(1, 2));
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// Verifies that compiler doesn't crash due to incompatible types
6+
// when unboxing input of a Phi.
7+
// Regression test for https://github.com/flutter/flutter/issues/83094.
8+
9+
import 'package:expect/expect.dart';
10+
11+
class A {
12+
@pragma('vm:never-inline')
13+
double getMaxIntrinsicWidth() => 1.toDouble();
14+
}
15+
16+
A _leading = A();
17+
18+
@pragma('vm:never-inline')
19+
double computeMaxIntrinsicWidth(double height, double horizontalPadding) {
20+
final leadingWidth =
21+
_leading == null ? 0 : _leading.getMaxIntrinsicWidth() as int;
22+
return horizontalPadding + leadingWidth;
23+
}
24+
25+
main() {
26+
Expect.throws(() => computeMaxIntrinsicWidth(1, 2));
27+
}

runtime/vm/compiler/backend/flow_graph.cc

+25-20
Original file line numberDiff line numberDiff line change
@@ -1809,22 +1809,26 @@ void FlowGraph::InsertConversion(Representation from,
18091809
Value* use,
18101810
bool is_environment_use) {
18111811
Instruction* insert_before;
1812-
Instruction* deopt_target;
18131812
PhiInstr* phi = use->instruction()->AsPhi();
18141813
if (phi != NULL) {
18151814
ASSERT(phi->is_alive());
18161815
// For phis conversions have to be inserted in the predecessor.
18171816
auto predecessor = phi->block()->PredecessorAt(use->use_index());
18181817
insert_before = predecessor->last_instruction();
18191818
ASSERT(insert_before->GetBlock() == predecessor);
1820-
deopt_target = NULL;
18211819
} else {
1822-
deopt_target = insert_before = use->instruction();
1820+
insert_before = use->instruction();
1821+
}
1822+
const Instruction::SpeculativeMode speculative_mode =
1823+
use->instruction()->SpeculativeModeOfInput(use->use_index());
1824+
Instruction* deopt_target = nullptr;
1825+
if (speculative_mode == Instruction::kGuardInputs || to == kUnboxedInt32) {
1826+
deopt_target = insert_before;
18231827
}
18241828

18251829
Definition* converted = NULL;
18261830
if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) {
1827-
const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL)
1831+
const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != nullptr)
18281832
? deopt_target->DeoptimizationTarget()
18291833
: DeoptId::kNone;
18301834
converted =
@@ -1833,49 +1837,50 @@ void FlowGraph::InsertConversion(Representation from,
18331837
converted = new Int32ToDoubleInstr(use->CopyWithType());
18341838
} else if ((from == kUnboxedInt64) && (to == kUnboxedDouble) &&
18351839
CanConvertInt64ToDouble()) {
1836-
const intptr_t deopt_id = (deopt_target != NULL)
1840+
const intptr_t deopt_id = (deopt_target != nullptr)
18371841
? deopt_target->DeoptimizationTarget()
18381842
: DeoptId::kNone;
18391843
ASSERT(CanUnboxDouble());
18401844
converted = new Int64ToDoubleInstr(use->CopyWithType(), deopt_id);
18411845
} else if ((from == kTagged) && Boxing::Supports(to)) {
1842-
const intptr_t deopt_id = (deopt_target != NULL)
1846+
const intptr_t deopt_id = (deopt_target != nullptr)
18431847
? deopt_target->DeoptimizationTarget()
18441848
: DeoptId::kNone;
1845-
converted = UnboxInstr::Create(
1846-
to, use->CopyWithType(), deopt_id,
1847-
use->instruction()->SpeculativeModeOfInput(use->use_index()));
1849+
converted =
1850+
UnboxInstr::Create(to, use->CopyWithType(), deopt_id, speculative_mode);
18481851
} else if ((to == kTagged) && Boxing::Supports(from)) {
18491852
converted = BoxInstr::Create(from, use->CopyWithType());
18501853
} else {
18511854
// We have failed to find a suitable conversion instruction.
18521855
// Insert two "dummy" conversion instructions with the correct
18531856
// "from" and "to" representation. The inserted instructions will
18541857
// trigger a deoptimization if executed. See #12417 for a discussion.
1855-
const intptr_t deopt_id = (deopt_target != NULL)
1858+
// If the use is not speculative, then this code should be unreachable.
1859+
// Insert Stop for a graceful error and aid unreachable code elimination.
1860+
if (speculative_mode == Instruction::kNotSpeculative) {
1861+
StopInstr* stop = new (Z) StopInstr("Incompatible conversion.");
1862+
InsertBefore(insert_before, stop, nullptr, FlowGraph::kEffect);
1863+
}
1864+
const intptr_t deopt_id = (deopt_target != nullptr)
18561865
? deopt_target->DeoptimizationTarget()
18571866
: DeoptId::kNone;
18581867
ASSERT(Boxing::Supports(from));
18591868
ASSERT(Boxing::Supports(to));
18601869
Definition* boxed = BoxInstr::Create(from, use->CopyWithType());
18611870
use->BindTo(boxed);
1862-
InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue);
1863-
converted = UnboxInstr::Create(to, new (Z) Value(boxed), deopt_id);
1871+
InsertBefore(insert_before, boxed, nullptr, FlowGraph::kValue);
1872+
converted = UnboxInstr::Create(to, new (Z) Value(boxed), deopt_id,
1873+
speculative_mode);
18641874
}
1865-
ASSERT(converted != NULL);
1866-
InsertBefore(insert_before, converted, use->instruction()->env(),
1875+
ASSERT(converted != nullptr);
1876+
InsertBefore(insert_before, converted,
1877+
(deopt_target != nullptr) ? deopt_target->env() : nullptr,
18671878
FlowGraph::kValue);
18681879
if (is_environment_use) {
18691880
use->BindToEnvironment(converted);
18701881
} else {
18711882
use->BindTo(converted);
18721883
}
1873-
1874-
if ((to == kUnboxedInt32) && (phi != NULL)) {
1875-
// Int32 phis are unboxed optimistically. Ensure that unboxing
1876-
// has deoptimization target attached from the goto instruction.
1877-
CopyDeoptTarget(converted, insert_before);
1878-
}
18791884
}
18801885

18811886
void FlowGraph::InsertConversionsFor(Definition* def) {

runtime/vm/compiler/backend/il.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -2481,9 +2481,12 @@ class PhiInstr : public Definition {
24812481

24822482
virtual void set_representation(Representation r) { representation_ = r; }
24832483

2484-
// In AOT mode Phi instructions do not check types of inputs when unboxing.
2484+
// Only Int32 phis in JIT mode are unboxed optimistically.
24852485
virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
2486-
return CompilerState::Current().is_aot() ? kNotSpeculative : kGuardInputs;
2486+
return (CompilerState::Current().is_aot() ||
2487+
(representation_ != kUnboxedInt32))
2488+
? kNotSpeculative
2489+
: kGuardInputs;
24872490
}
24882491

24892492
virtual intptr_t Hashcode() const {
@@ -3140,6 +3143,9 @@ class GotoInstr : public TemplateInstruction<0, NoThrow> {
31403143
return true;
31413144
}
31423145

3146+
// May require a deoptimization target for int32 Phi input conversions.
3147+
virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
3148+
31433149
virtual bool ComputeCanDeoptimize() const { return false; }
31443150

31453151
virtual bool HasUnknownSideEffects() const { return false; }
@@ -4104,6 +4110,7 @@ class InstanceCallBaseInstr : public TemplateDartCall<0> {
41044110
}
41054111
idx--;
41064112
}
4113+
if (interface_target_.IsNull()) return kGuardInputs;
41074114
return interface_target_.is_unboxed_parameter_at(idx) ? kNotSpeculative
41084115
: kGuardInputs;
41094116
}

tools/VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@
2626
CHANNEL stable
2727
MAJOR 2
2828
MINOR 13
29-
PATCH 1
29+
PATCH 2
3030
PRERELEASE 0
3131
PRERELEASE_PATCH 0

0 commit comments

Comments
 (0)