@@ -20,6 +20,47 @@ DEFINE_FLAG(bool,
20
20
false ,
21
21
" Generate always trampolines (for testing purposes)." );
22
22
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
+
23
64
const intptr_t kTrampolineSize =
24
65
Utils::RoundUp (PcRelativeTrampolineJumpPattern::kLengthInBytes ,
25
66
compiler::target::Instructions::kBarePayloadAlignment );
@@ -46,7 +87,7 @@ void CodeRelocator::Relocate(bool is_vm_isolate) {
46
87
// * the maximum number of calls
47
88
// * the maximum offset into a target instruction
48
89
//
49
- FindInstructionAndCallLimits ();
90
+ FindLargestInstruction ();
50
91
51
92
// Emit all instructions and do relocations on the way.
52
93
for (intptr_t i = 0 ; i < code_objects_->length (); ++i) {
@@ -65,7 +106,8 @@ void CodeRelocator::Relocate(bool is_vm_isolate) {
65
106
66
107
// If we have forward/backwards calls which are almost out-of-range, we'll
67
108
// create trampolines now.
68
- BuildTrampolinesForAlmostOutOfRangeCalls ();
109
+ BuildTrampolinesForAlmostOutOfRangeCalls (
110
+ /* force=*/ (i == (code_objects_->length () - 1 )));
69
111
}
70
112
71
113
// We're guaranteed to have all calls resolved, since
@@ -101,7 +143,7 @@ void CodeRelocator::Relocate(bool is_vm_isolate) {
101
143
// however we might need it to write information into V8 snapshot profile.
102
144
}
103
145
104
- void CodeRelocator::FindInstructionAndCallLimits () {
146
+ void CodeRelocator::FindLargestInstruction () {
105
147
auto zone = thread_->zone ();
106
148
auto & current_caller = Code::Handle (zone);
107
149
auto & call_targets = Array::Handle (zone);
@@ -122,48 +164,10 @@ void CodeRelocator::FindInstructionAndCallLimits() {
122
164
kind_type_and_offset_ = call.Get <Code::kSCallTableKindAndOffset >();
123
165
const auto kind =
124
166
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
-
130
167
if (kind == Code::kCallViaCode ) {
131
168
continue ;
132
169
}
133
-
134
- destination_ = GetTarget (call);
135
170
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
- }
167
171
}
168
172
169
173
if (num_calls > max_calls_) {
@@ -323,8 +327,11 @@ bool CodeRelocator::TryResolveBackwardsCall(UnresolvedCall* unresolved_call) {
323
327
auto map_entry = text_offsets_.Lookup (callee);
324
328
if (map_entry == nullptr ) return false ;
325
329
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 ;
328
335
}
329
336
330
337
void CodeRelocator::ResolveUnresolvedCallsTargeting (
@@ -411,11 +418,11 @@ bool CodeRelocator::IsTargetInRangeFor(UnresolvedCall* unresolved_call,
411
418
const auto forward_distance =
412
419
target_text_offset - unresolved_call->text_offset ;
413
420
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 () ;
416
423
} else {
417
- return PcRelativeCallPattern:: kLowerCallingRange < forward_distance &&
418
- forward_distance < PcRelativeCallPattern:: kUpperCallingRange ;
424
+ return CallDistanceLimits::Lower () < forward_distance &&
425
+ forward_distance < CallDistanceLimits::Upper () ;
419
426
}
420
427
}
421
428
@@ -471,7 +478,7 @@ CodePtr CodeRelocator::GetTarget(const StaticCallsTableEntry& call) {
471
478
return destination_.ptr ();
472
479
}
473
480
474
- void CodeRelocator::BuildTrampolinesForAlmostOutOfRangeCalls () {
481
+ void CodeRelocator::BuildTrampolinesForAlmostOutOfRangeCalls (bool force ) {
475
482
while (!all_unresolved_calls_.IsEmpty ()) {
476
483
UnresolvedCall* unresolved_call = all_unresolved_calls_.First ();
477
484
@@ -484,7 +491,7 @@ void CodeRelocator::BuildTrampolinesForAlmostOutOfRangeCalls() {
484
491
kTrampolineSize *
485
492
(unresolved_calls_by_destination_.Length () + max_calls_);
486
493
if (IsTargetInRangeFor (unresolved_call, future_boundary) &&
487
- !FLAG_always_generate_trampolines_for_testing) {
494
+ !FLAG_always_generate_trampolines_for_testing && !force ) {
488
495
break ;
489
496
}
490
497
0 commit comments