Skip to content

Commit 5cae07b

Browse files
committed
Version 2.13.0-211.13.beta
* Cherry-pick aaa66ed to beta * Cherry-pick ea50eeb to beta * Cherry-pick 825b59a to beta * Cherry-pick 8800dec to beta * Cherry-pick 8e2539d to beta * Cherry-pick d41f9a7 to beta * Cherry-pick 8156646 to beta
2 parents 94162a2 + b99f016 commit 5cae07b

File tree

21 files changed

+690
-88
lines changed

21 files changed

+690
-88
lines changed

pkg/dev_compiler/lib/src/kernel/compiler.dart

+31-5
Original file line numberDiff line numberDiff line change
@@ -3585,8 +3585,30 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
35853585
js_ast.Statement _visitStatement(Statement s) {
35863586
if (s == null) return null;
35873587
var result = s.accept(this);
3588+
3589+
// In most cases, a Dart expression statement with a child expression
3590+
// compile to a JS expression statement with a child expression.
3591+
//
3592+
// ExpressionStatement js_ast.ExpressionStatement
3593+
// | --> compiles to --> |
3594+
// Expression js_ast.Expression
3595+
//
3596+
// Both the expression statement and child expression nodes contain their
3597+
// own source location information.
3598+
//
3599+
// In the case of a debugger() call, the code compiles to a single node.
3600+
//
3601+
// ExpressionStatement js_ast.DebuggerStatement
3602+
// | --> compiles to -->
3603+
// Expression
3604+
//
3605+
// The js_ast.DebuggerStatement already has the correct source information
3606+
// attached so we avoid overwriting with the incorrect source location from
3607+
// [s].
35883608
// TODO(jmesserly): is the `is! Block` still necessary?
3589-
if (s is! Block) result.sourceInformation = _nodeStart(s);
3609+
if (!(s is Block || result is js_ast.DebuggerStatement)) {
3610+
result.sourceInformation = _nodeStart(s);
3611+
}
35903612

35913613
// The statement might be the target of a break or continue with a label.
35923614
var name = _labelNames[s];
@@ -5087,6 +5109,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
50875109
// If we know that the left type uses identity for equality, we can
50885110
// sometimes emit better code, either `===` or `==`.
50895111
var isEnum = leftType is InterfaceType && leftType.classNode.isEnum;
5112+
50905113
var usesIdentity = _typeRep.isPrimitive(leftType) ||
50915114
isEnum ||
50925115
_isNull(left) ||
@@ -5290,12 +5313,14 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
52905313
js_ast.Node _emitDebuggerCall(StaticInvocation node) {
52915314
var args = node.arguments.named;
52925315
var isStatement = node.parent is ExpressionStatement;
5316+
var debuggerStatement =
5317+
js_ast.DebuggerStatement().withSourceInformation(_nodeStart(node));
52935318
if (args.isEmpty) {
52945319
// Inline `debugger()` with no arguments, as a statement if possible,
52955320
// otherwise as an immediately invoked function.
52965321
return isStatement
5297-
? js.statement('debugger;')
5298-
: js.call('(() => { debugger; return true})()');
5322+
? debuggerStatement
5323+
: js.call('(() => { #; return true})()', [debuggerStatement]);
52995324
}
53005325

53015326
// The signature of `debugger()` is:
@@ -5320,8 +5345,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
53205345
// order, then extract the `when` argument.
53215346
: js.call('#.when', js_ast.ObjectInitializer(jsArgs));
53225347
return isStatement
5323-
? js.statement('if (#) debugger;', when)
5324-
: js.call('# && (() => { debugger; return true })()', when);
5348+
? js.statement('if (#) #;', [when, debuggerStatement])
5349+
: js.call(
5350+
'# && (() => { #; return true })()', [when, debuggerStatement]);
53255351
}
53265352

53275353
/// Emits the target of a [StaticInvocation], [StaticGet], or [StaticSet].

pkg/dev_compiler/lib/src/kernel/native_types.dart

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class NativeTypeSet {
4949
_addExtensionType(coreTypes.doubleClass, true);
5050
_addExtensionType(coreTypes.boolClass, true);
5151
_addExtensionType(coreTypes.stringClass, true);
52+
// Allow `Function.==` to be recognized as a symbolized member.
53+
_addExtensionType(coreTypes.functionClass, false);
5254

5355
var sdk = coreTypes.index;
5456
_addExtensionTypes(sdk.getLibrary('dart:_interceptors'));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
// @dart = 2.9
6+
7+
import 'dart:developer';
8+
9+
// Regression test: https://github.com/dart-lang/sdk/issues/45544
10+
11+
var b = true;
12+
void main() {
13+
// Ensure multiple debugger calls of different varieties map to different
14+
// unique locations.
15+
print('1');
16+
/*s:1*/ debugger();
17+
print('2');
18+
/*s:2*/ debugger(when: b);
19+
print('3');
20+
foo(/*s:3*/ debugger());
21+
print('4');
22+
/*s:4*/ debugger(when: b);
23+
print('5');
24+
foo(/*s:5*/ debugger(when: b));
25+
print('6');
26+
/*s:6*/ debugger();
27+
print('7');
28+
foo(/*s:7*/ debugger(when: b));
29+
print('8');
30+
foo(/*s:8*/ debugger());
31+
}
32+
33+
void foo(bool _) => null;

pkg/vm/lib/transformations/type_flow/signature_shaking.dart

+6
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,12 @@ class _Transform extends RecursiveVisitor {
498498
super.visitProcedure(node);
499499
}
500500

501+
@override
502+
void visitField(Field node) {
503+
typeContext = StaticTypeContext(node, shaker.typeFlowAnalysis.environment);
504+
super.visitField(node);
505+
}
506+
501507
static void forEachArgumentRev(Arguments args, _ProcedureInfo info,
502508
void Function(Expression, _ParameterInfo) fun) {
503509
for (int i = args.named.length - 1; i >= 0; i--) {

runtime/vm/compiler/compiler_sources.gni

+1
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ compiler_sources_tests = [
175175
"backend/typed_data_aot_test.cc",
176176
"backend/yield_position_test.cc",
177177
"cha_test.cc",
178+
"relocation_test.cc",
178179
"ffi/native_type_vm_test.cc",
179180
"frontend/kernel_binary_flowgraph_test.cc",
180181
"write_barrier_elimination_test.cc",

runtime/vm/compiler/relocation.cc

+56-49
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,47 @@ DEFINE_FLAG(bool,
2020
false,
2121
"Generate always trampolines (for testing purposes).");
2222

23+
DEFINE_FLAG(int,
24+
lower_tail_pc_relative_call_distance,
25+
-1,
26+
"Lower tail call distance.");
27+
DEFINE_FLAG(int,
28+
upper_tail_pc_relative_call_distance,
29+
-1,
30+
"Upper tail call distance.");
31+
DEFINE_FLAG(int, lower_pc_relative_call_distance, -1, "Lower call distance.");
32+
DEFINE_FLAG(int, upper_pc_relative_call_distance, -1, "Upper call distance.");
33+
34+
struct TailCallDistanceLimits {
35+
static intptr_t Lower() {
36+
if (FLAG_lower_tail_pc_relative_call_distance != -1) {
37+
return FLAG_lower_tail_pc_relative_call_distance;
38+
}
39+
return PcRelativeTailCallPattern::kLowerCallingRange;
40+
}
41+
static intptr_t Upper() {
42+
if (FLAG_upper_tail_pc_relative_call_distance != -1) {
43+
return FLAG_upper_tail_pc_relative_call_distance;
44+
}
45+
return PcRelativeTailCallPattern::kUpperCallingRange;
46+
}
47+
};
48+
49+
struct CallDistanceLimits {
50+
static intptr_t Lower() {
51+
if (FLAG_lower_pc_relative_call_distance != -1) {
52+
return FLAG_lower_pc_relative_call_distance;
53+
}
54+
return PcRelativeCallPattern::kLowerCallingRange;
55+
}
56+
static intptr_t Upper() {
57+
if (FLAG_upper_pc_relative_call_distance != -1) {
58+
return FLAG_upper_pc_relative_call_distance;
59+
}
60+
return PcRelativeCallPattern::kUpperCallingRange;
61+
}
62+
};
63+
2364
const intptr_t kTrampolineSize =
2465
Utils::RoundUp(PcRelativeTrampolineJumpPattern::kLengthInBytes,
2566
compiler::target::Instructions::kBarePayloadAlignment);
@@ -46,7 +87,7 @@ void CodeRelocator::Relocate(bool is_vm_isolate) {
4687
// * the maximum number of calls
4788
// * the maximum offset into a target instruction
4889
//
49-
FindInstructionAndCallLimits();
90+
FindLargestInstruction();
5091

5192
// Emit all instructions and do relocations on the way.
5293
for (intptr_t i = 0; i < code_objects_->length(); ++i) {
@@ -65,7 +106,8 @@ void CodeRelocator::Relocate(bool is_vm_isolate) {
65106

66107
// If we have forward/backwards calls which are almost out-of-range, we'll
67108
// create trampolines now.
68-
BuildTrampolinesForAlmostOutOfRangeCalls();
109+
BuildTrampolinesForAlmostOutOfRangeCalls(
110+
/*force=*/(i == (code_objects_->length() - 1)));
69111
}
70112

71113
// We're guaranteed to have all calls resolved, since
@@ -101,7 +143,7 @@ void CodeRelocator::Relocate(bool is_vm_isolate) {
101143
// however we might need it to write information into V8 snapshot profile.
102144
}
103145

104-
void CodeRelocator::FindInstructionAndCallLimits() {
146+
void CodeRelocator::FindLargestInstruction() {
105147
auto zone = thread_->zone();
106148
auto& current_caller = Code::Handle(zone);
107149
auto& call_targets = Array::Handle(zone);
@@ -122,48 +164,10 @@ void CodeRelocator::FindInstructionAndCallLimits() {
122164
kind_type_and_offset_ = call.Get<Code::kSCallTableKindAndOffset>();
123165
const auto kind =
124166
Code::KindField::decode(kind_type_and_offset_.Value());
125-
const auto return_pc_offset =
126-
Code::OffsetField::decode(kind_type_and_offset_.Value());
127-
const auto call_entry_point =
128-
Code::EntryPointField::decode(kind_type_and_offset_.Value());
129-
130167
if (kind == Code::kCallViaCode) {
131168
continue;
132169
}
133-
134-
destination_ = GetTarget(call);
135170
num_calls++;
136-
137-
// A call site can decide to jump not to the beginning of a function but
138-
// rather jump into it at a certain (positive) offset.
139-
int32_t offset_into_target = 0;
140-
if (kind == Code::kPcRelativeCall || kind == Code::kPcRelativeTTSCall) {
141-
const intptr_t call_instruction_offset =
142-
return_pc_offset - PcRelativeCallPattern::kLengthInBytes;
143-
PcRelativeCallPattern call(current_caller.PayloadStart() +
144-
call_instruction_offset);
145-
ASSERT(call.IsValid());
146-
offset_into_target = call.distance();
147-
} else {
148-
ASSERT(kind == Code::kPcRelativeTailCall);
149-
const intptr_t call_instruction_offset =
150-
return_pc_offset - PcRelativeTailCallPattern::kLengthInBytes;
151-
PcRelativeTailCallPattern call(current_caller.PayloadStart() +
152-
call_instruction_offset);
153-
ASSERT(call.IsValid());
154-
offset_into_target = call.distance();
155-
}
156-
157-
const uword destination_payload = destination_.PayloadStart();
158-
const uword entry_point = call_entry_point == Code::kUncheckedEntry
159-
? destination_.UncheckedEntryPoint()
160-
: destination_.EntryPoint();
161-
162-
offset_into_target += (entry_point - destination_payload);
163-
164-
if (offset_into_target > max_offset_into_target_) {
165-
max_offset_into_target_ = offset_into_target;
166-
}
167171
}
168172

169173
if (num_calls > max_calls_) {
@@ -323,8 +327,11 @@ bool CodeRelocator::TryResolveBackwardsCall(UnresolvedCall* unresolved_call) {
323327
auto map_entry = text_offsets_.Lookup(callee);
324328
if (map_entry == nullptr) return false;
325329

326-
ResolveCall(unresolved_call);
327-
return true;
330+
if (IsTargetInRangeFor(unresolved_call, map_entry->value)) {
331+
ResolveCall(unresolved_call);
332+
return true;
333+
}
334+
return false;
328335
}
329336

330337
void CodeRelocator::ResolveUnresolvedCallsTargeting(
@@ -411,11 +418,11 @@ bool CodeRelocator::IsTargetInRangeFor(UnresolvedCall* unresolved_call,
411418
const auto forward_distance =
412419
target_text_offset - unresolved_call->text_offset;
413420
if (unresolved_call->is_tail_call) {
414-
return PcRelativeTailCallPattern::kLowerCallingRange < forward_distance &&
415-
forward_distance < PcRelativeTailCallPattern::kUpperCallingRange;
421+
return TailCallDistanceLimits::Lower() < forward_distance &&
422+
forward_distance < TailCallDistanceLimits::Upper();
416423
} else {
417-
return PcRelativeCallPattern::kLowerCallingRange < forward_distance &&
418-
forward_distance < PcRelativeCallPattern::kUpperCallingRange;
424+
return CallDistanceLimits::Lower() < forward_distance &&
425+
forward_distance < CallDistanceLimits::Upper();
419426
}
420427
}
421428

@@ -471,7 +478,7 @@ CodePtr CodeRelocator::GetTarget(const StaticCallsTableEntry& call) {
471478
return destination_.ptr();
472479
}
473480

474-
void CodeRelocator::BuildTrampolinesForAlmostOutOfRangeCalls() {
481+
void CodeRelocator::BuildTrampolinesForAlmostOutOfRangeCalls(bool force) {
475482
while (!all_unresolved_calls_.IsEmpty()) {
476483
UnresolvedCall* unresolved_call = all_unresolved_calls_.First();
477484

@@ -484,7 +491,7 @@ void CodeRelocator::BuildTrampolinesForAlmostOutOfRangeCalls() {
484491
kTrampolineSize *
485492
(unresolved_calls_by_destination_.Length() + max_calls_);
486493
if (IsTargetInRangeFor(unresolved_call, future_boundary) &&
487-
!FLAG_always_generate_trampolines_for_testing) {
494+
!FLAG_always_generate_trampolines_for_testing && !force) {
488495
break;
489496
}
490497

runtime/vm/compiler/relocation.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class CodeRelocator : public StackResource {
161161

162162
void Relocate(bool is_vm_isolate);
163163

164-
void FindInstructionAndCallLimits();
164+
void FindLargestInstruction();
165165

166166
bool AddInstructionsToText(CodePtr code);
167167
void ScanCallTargets(const Code& code,
@@ -183,7 +183,7 @@ class CodeRelocator : public StackResource {
183183
intptr_t destination_text);
184184
void ResolveTrampoline(UnresolvedTrampoline* unresolved_trampoline);
185185

186-
void BuildTrampolinesForAlmostOutOfRangeCalls();
186+
void BuildTrampolinesForAlmostOutOfRangeCalls(bool force);
187187

188188
intptr_t FindDestinationInText(const InstructionsPtr destination,
189189
intptr_t offset_into_target);
@@ -207,7 +207,6 @@ class CodeRelocator : public StackResource {
207207
intptr_t max_instructions_size_ = 0;
208208
// The maximum number of pc-relative calls in an instructions object.
209209
intptr_t max_calls_ = 0;
210-
intptr_t max_offset_into_target_ = 0;
211210

212211
// Data structures used for relocation.
213212
intptr_t next_text_offset_ = 0;

0 commit comments

Comments
 (0)