Skip to content

Commit 4de495f

Browse files
rmacnak-googlecommit-bot@chromium.org
authored andcommitted
[vm, compiler] Remove dead stub ICCallThroughFunction.
This was needed in the past when AOT code was executed in the compiler to implement loading and evaluate constants. Change-Id: I66633acfc61676bce10b0a0abb7955e4e45be54c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104100 Reviewed-by: Aart Bik <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent 8a1dcda commit 4de495f

12 files changed

+52
-205
lines changed

runtime/vm/compiler/aot/precompiler.cc

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ void Precompiler::DoCompileAll() {
337337
DropLibraries();
338338

339339
BindStaticCalls();
340-
SwitchICCalls();
340+
DedupUnlinkedCalls();
341341
Obfuscate();
342342

343343
ProgramVisitor::Dedup();
@@ -612,16 +612,15 @@ void Precompiler::AddCalleesOf(const Function& function, intptr_t gop_offset) {
612612
void Precompiler::AddCalleesOfHelper(const Object& entry,
613613
String* temp_selector,
614614
Class* temp_cls) {
615-
if (entry.IsICData()) {
616-
const auto& call_site = ICData::Cast(entry);
615+
if (entry.IsUnlinkedCall()) {
616+
const auto& call_site = UnlinkedCall::Cast(entry);
617617
// A dynamic call.
618-
ASSERT(!call_site.is_static_call());
619618
*temp_selector = call_site.target_name();
620619
AddSelector(*temp_selector);
621620
if (temp_selector->raw() == Symbols::Call().raw()) {
622621
// Potential closure call.
623622
const Array& arguments_descriptor =
624-
Array::Handle(Z, call_site.arguments_descriptor());
623+
Array::Handle(Z, call_site.args_descriptor());
625624
AddClosureCall(arguments_descriptor);
626625
}
627626
} else if (entry.IsMegamorphicCache()) {
@@ -1986,49 +1985,27 @@ void Precompiler::BindStaticCalls() {
19861985
}
19871986
}
19881987

1989-
void Precompiler::SwitchICCalls() {
1988+
void Precompiler::DedupUnlinkedCalls() {
19901989
ASSERT(!I->compilation_allowed());
19911990
#if !defined(TARGET_ARCH_DBC)
1992-
// Now that all functions have been compiled, we can switch to an instance
1993-
// call sequence that loads the Code object and entry point directly from
1994-
// the ic data array instead indirectly through a Function in the ic data
1995-
// array. Iterate all the object pools and rewrite the ic data from
1996-
// (cid, target function, count) to (cid, target code, entry point), and
1997-
// replace the ICCallThroughFunction stub with ICCallThroughCode.
1998-
class ICCallSwitcher {
1991+
class UnlinkedCallDeduper {
19991992
public:
2000-
explicit ICCallSwitcher(Zone* zone)
1993+
explicit UnlinkedCallDeduper(Zone* zone)
20011994
: zone_(zone),
20021995
entry_(Object::Handle(zone)),
2003-
ic_(ICData::Handle(zone)),
2004-
target_name_(String::Handle(zone)),
2005-
args_descriptor_(Array::Handle(zone)),
20061996
unlinked_(UnlinkedCall::Handle(zone)),
2007-
target_code_(Code::Handle(zone)),
20081997
canonical_unlinked_calls_() {}
20091998

2010-
void SwitchPool(const ObjectPool& pool) {
1999+
void DedupPool(const ObjectPool& pool) {
20112000
for (intptr_t i = 0; i < pool.Length(); i++) {
20122001
if (pool.TypeAt(i) != ObjectPool::EntryType::kTaggedObject) {
20132002
continue;
20142003
}
20152004
entry_ = pool.ObjectAt(i);
2016-
if (entry_.IsICData()) {
2017-
// The only IC calls generated by precompilation are for switchable
2018-
// calls.
2019-
ic_ ^= entry_.raw();
2020-
ic_.ResetSwitchable(zone_);
2021-
2022-
unlinked_ = UnlinkedCall::New();
2023-
target_name_ = ic_.target_name();
2024-
unlinked_.set_target_name(target_name_);
2025-
args_descriptor_ = ic_.arguments_descriptor();
2026-
unlinked_.set_args_descriptor(args_descriptor_);
2005+
if (entry_.IsUnlinkedCall()) {
2006+
unlinked_ ^= entry_.raw();
20272007
unlinked_ = DedupUnlinkedCall(unlinked_);
20282008
pool.SetObjectAt(i, unlinked_);
2029-
} else if (entry_.raw() == StubCode::ICCallThroughFunction().raw()) {
2030-
target_code_ = StubCode::UnlinkedCall().raw();
2031-
pool.SetObjectAt(i, target_code_);
20322009
}
20332010
}
20342011
}
@@ -2048,18 +2025,14 @@ void Precompiler::SwitchICCalls() {
20482025
private:
20492026
Zone* zone_;
20502027
Object& entry_;
2051-
ICData& ic_;
2052-
String& target_name_;
2053-
Array& args_descriptor_;
20542028
UnlinkedCall& unlinked_;
2055-
Code& target_code_;
20562029
UnlinkedCallSet canonical_unlinked_calls_;
20572030
};
20582031

2059-
class SwitchICCallsVisitor : public FunctionVisitor {
2032+
class DedupUnlinkedCallsVisitor : public FunctionVisitor {
20602033
public:
2061-
SwitchICCallsVisitor(ICCallSwitcher* ic_call_switcher, Zone* zone)
2062-
: ic_call_switcher_(*ic_call_switcher),
2034+
DedupUnlinkedCallsVisitor(UnlinkedCallDeduper* deduper, Zone* zone)
2035+
: deduper_(*deduper),
20632036
code_(Code::Handle(zone)),
20642037
pool_(ObjectPool::Handle(zone)) {}
20652038

@@ -2069,22 +2042,22 @@ void Precompiler::SwitchICCalls() {
20692042
}
20702043
code_ = function.CurrentCode();
20712044
pool_ = code_.object_pool();
2072-
ic_call_switcher_.SwitchPool(pool_);
2045+
deduper_.DedupPool(pool_);
20732046
}
20742047

20752048
private:
2076-
ICCallSwitcher& ic_call_switcher_;
2049+
UnlinkedCallDeduper& deduper_;
20772050
Code& code_;
20782051
ObjectPool& pool_;
20792052
};
20802053

2081-
ICCallSwitcher switcher(Z);
2054+
UnlinkedCallDeduper deduper(Z);
20822055
auto& gop = ObjectPool::Handle(I->object_store()->global_object_pool());
20832056
ASSERT(gop.IsNull() != FLAG_use_bare_instructions);
20842057
if (FLAG_use_bare_instructions) {
2085-
switcher.SwitchPool(gop);
2058+
deduper.DedupPool(gop);
20862059
} else {
2087-
SwitchICCallsVisitor visitor(&switcher, Z);
2060+
DedupUnlinkedCallsVisitor visitor(&deduper, Z);
20882061

20892062
// We need both iterations to ensure we visit all the functions that might
20902063
// end up in the snapshot. The ProgramVisitor will miss closures from

runtime/vm/compiler/aot/precompiler.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,13 @@ class Precompiler : public ValueObject {
279279
void DropClasses();
280280
void DropLibraries();
281281

282+
// Remove the indirection of the CallStaticFunction stub from all static call
283+
// sites now that Code is available for all call targets. Allows for dropping
284+
// the static call table from each Code object.
282285
void BindStaticCalls();
283-
void SwitchICCalls();
286+
// Deduplicate the UnlinkedCall objects in all ObjectPools to reduce snapshot
287+
// size.
288+
void DedupUnlinkedCalls();
284289

285290
void Obfuscate();
286291

runtime/vm/compiler/backend/flow_graph_compiler_arm.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,7 +1147,9 @@ void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
11471147
ASSERT(entry_kind == Code::EntryKind::kNormal ||
11481148
entry_kind == Code::EntryKind::kUnchecked);
11491149
ASSERT(ic_data.NumArgsTested() == 1);
1150-
const Code& initial_stub = StubCode::ICCallThroughFunction();
1150+
const Code& initial_stub = StubCode::UnlinkedCall();
1151+
const UnlinkedCall& data =
1152+
UnlinkedCall::ZoneHandle(zone(), ic_data.AsUnlinkedCall());
11511153

11521154
__ Comment("InstanceCallAOT");
11531155
__ LoadFromOffset(
@@ -1167,7 +1169,7 @@ void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
11671169
Code::EntryKind::kMonomorphicUnchecked);
11681170
__ ldr(LR, FieldAddress(CODE_REG, entry_point_offset));
11691171
}
1170-
__ LoadUniqueObject(R9, ic_data);
1172+
__ LoadUniqueObject(R9, data);
11711173
__ blx(LR);
11721174

11731175
EmitCallsiteMetadata(token_pos, DeoptId::kNone, RawPcDescriptors::kOther,

runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,27 +1113,29 @@ void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
11131113
Code::EntryKind entry_kind) {
11141114
// TODO(34162): Support multiple entry-points on ARM64.
11151115
ASSERT(ic_data.NumArgsTested() == 1);
1116-
const Code& initial_stub = StubCode::ICCallThroughFunction();
1116+
const Code& initial_stub = StubCode::UnlinkedCall();
1117+
const UnlinkedCall& data =
1118+
UnlinkedCall::ZoneHandle(zone(), ic_data.AsUnlinkedCall());
11171119

11181120
ObjectPoolBuilder& op = __ object_pool_builder();
11191121

11201122
__ Comment("InstanceCallAOT");
11211123
__ LoadFromOffset(R0, SP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize);
11221124

1123-
const intptr_t ic_data_index =
1124-
op.AddObject(ic_data, ObjectPool::Patchability::kPatchable);
1125+
const intptr_t data_index =
1126+
op.AddObject(data, ObjectPool::Patchability::kPatchable);
11251127
const intptr_t initial_stub_index =
11261128
op.AddObject(initial_stub, ObjectPool::Patchability::kPatchable);
1127-
ASSERT((ic_data_index + 1) == initial_stub_index);
1129+
ASSERT((data_index + 1) == initial_stub_index);
11281130

11291131
if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
11301132
// The AOT runtime will replace the slot in the object pool with the
11311133
// entrypoint address - see clustered_snapshot.cc.
11321134
__ LoadDoubleWordFromPoolOffset(R5, LR,
1133-
ObjectPool::element_offset(ic_data_index));
1135+
ObjectPool::element_offset(data_index));
11341136
} else {
11351137
__ LoadDoubleWordFromPoolOffset(R5, CODE_REG,
1136-
ObjectPool::element_offset(ic_data_index));
1138+
ObjectPool::element_offset(data_index));
11371139
__ ldr(LR, FieldAddress(CODE_REG, Code::entry_point_offset(
11381140
Code::EntryKind::kMonomorphic)));
11391141
}

runtime/vm/compiler/backend/flow_graph_compiler_x64.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,9 @@ void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
11231123
ASSERT(entry_kind == Code::EntryKind::kNormal ||
11241124
entry_kind == Code::EntryKind::kUnchecked);
11251125
ASSERT(ic_data.NumArgsTested() == 1);
1126-
const Code& initial_stub = StubCode::ICCallThroughFunction();
1126+
const Code& initial_stub = StubCode::UnlinkedCall();
1127+
const UnlinkedCall& data =
1128+
UnlinkedCall::ZoneHandle(zone(), ic_data.AsUnlinkedCall());
11271129

11281130
__ Comment("InstanceCallAOT");
11291131
__ movq(RDX, Address(RSP, (ic_data.CountWithoutTypeArgs() - 1) * kWordSize));
@@ -1139,7 +1141,7 @@ void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
11391141
__ LoadUniqueObject(CODE_REG, initial_stub);
11401142
__ movq(RCX, FieldAddress(CODE_REG, entry_point_offset));
11411143
}
1142-
__ LoadUniqueObject(RBX, ic_data);
1144+
__ LoadUniqueObject(RBX, data);
11431145
__ call(RCX);
11441146

11451147
EmitCallsiteMetadata(token_pos, deopt_id, RawPcDescriptors::kOther, locs);

runtime/vm/compiler/stub_code_compiler_arm.cc

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3149,48 +3149,6 @@ void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
31493149
__ b(&loop);
31503150
}
31513151

3152-
// Called from switchable IC calls.
3153-
// R0: receiver
3154-
// R9: ICData (preserved)
3155-
// Passed to target:
3156-
// CODE_REG: target Code object
3157-
// R4: arguments descriptor
3158-
void StubCodeCompiler::GenerateICCallThroughFunctionStub(Assembler* assembler) {
3159-
Label loop, found, miss;
3160-
__ ldr(ARGS_DESC_REG,
3161-
FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
3162-
__ ldr(R8, FieldAddress(R9, target::ICData::entries_offset()));
3163-
__ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
3164-
// R8: first IC entry
3165-
__ LoadTaggedClassIdMayBeSmi(R1, R0);
3166-
// R1: receiver cid as Smi
3167-
3168-
__ Bind(&loop);
3169-
__ ldr(R2, Address(R8, 0));
3170-
__ cmp(R1, Operand(R2));
3171-
__ b(&found, EQ);
3172-
__ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));
3173-
__ b(&miss, EQ);
3174-
3175-
const intptr_t entry_length =
3176-
target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
3177-
target::kWordSize;
3178-
__ AddImmediate(R8, entry_length); // Next entry.
3179-
__ b(&loop);
3180-
3181-
__ Bind(&found);
3182-
const intptr_t target_offset =
3183-
target::ICData::TargetIndexFor(1) * target::kWordSize;
3184-
__ LoadFromOffset(kWord, R0, R8, target_offset);
3185-
__ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
3186-
__ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
3187-
3188-
__ Bind(&miss);
3189-
__ LoadIsolate(R2);
3190-
__ ldr(CODE_REG, Address(R2, target::Isolate::ic_miss_code_offset()));
3191-
__ Branch(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
3192-
}
3193-
31943152
void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
31953153
Label loop, found, miss;
31963154
__ ldr(R8, FieldAddress(R9, target::ICData::entries_offset()));

runtime/vm/compiler/stub_code_compiler_arm64.cc

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3229,50 +3229,6 @@ void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
32293229
__ b(&cid_loaded);
32303230
}
32313231

3232-
// Called from switchable IC calls.
3233-
// R0: receiver
3234-
// R5: ICData (preserved)
3235-
// Passed to target:
3236-
// CODE_REG: target Code object
3237-
// R4: arguments descriptor
3238-
void StubCodeCompiler::GenerateICCallThroughFunctionStub(Assembler* assembler) {
3239-
Label loop, found, miss;
3240-
__ ldr(ARGS_DESC_REG,
3241-
FieldAddress(R5, target::ICData::arguments_descriptor_offset()));
3242-
__ ldr(R8, FieldAddress(R5, target::ICData::entries_offset()));
3243-
__ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
3244-
// R8: first IC entry
3245-
__ LoadTaggedClassIdMayBeSmi(R1, R0);
3246-
// R1: receiver cid as Smi
3247-
3248-
__ Bind(&loop);
3249-
__ ldr(R2, Address(R8, 0));
3250-
__ cmp(R1, Operand(R2));
3251-
__ b(&found, EQ);
3252-
__ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));
3253-
__ b(&miss, EQ);
3254-
3255-
const intptr_t entry_length =
3256-
target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
3257-
target::kWordSize;
3258-
__ AddImmediate(R8, entry_length); // Next entry.
3259-
__ b(&loop);
3260-
3261-
__ Bind(&found);
3262-
const intptr_t target_offset =
3263-
target::ICData::TargetIndexFor(1) * target::kWordSize;
3264-
__ ldr(R0, Address(R8, target_offset));
3265-
__ ldr(R1, FieldAddress(R0, target::Function::entry_point_offset()));
3266-
__ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
3267-
__ br(R1);
3268-
3269-
__ Bind(&miss);
3270-
__ LoadIsolate(R2);
3271-
__ ldr(CODE_REG, Address(R2, target::Isolate::ic_miss_code_offset()));
3272-
__ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
3273-
__ br(R1);
3274-
}
3275-
32763232
void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
32773233
Label loop, found, miss;
32783234
__ ldr(R8, FieldAddress(R5, target::ICData::entries_offset()));

runtime/vm/compiler/stub_code_compiler_ia32.cc

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,15 +2674,6 @@ void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
26742674
__ jmp(&cid_loaded);
26752675
}
26762676

2677-
// Called from switchable IC calls.
2678-
// EBX: receiver
2679-
// ECX: ICData (preserved)
2680-
// Passed to target:
2681-
// EDX: arguments descriptor
2682-
void StubCodeCompiler::GenerateICCallThroughFunctionStub(Assembler* assembler) {
2683-
__ int3(); // AOT only.
2684-
}
2685-
26862677
void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
26872678
__ int3(); // AOT only.
26882679
}

runtime/vm/compiler/stub_code_compiler_x64.cc

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3234,52 +3234,6 @@ void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
32343234
__ jmp(&cid_loaded);
32353235
}
32363236

3237-
// Called from switchable IC calls.
3238-
// RDX: receiver
3239-
// RBX: ICData (preserved)
3240-
// Passed to target:
3241-
// CODE_REG: target Code object
3242-
// R10: arguments descriptor
3243-
void StubCodeCompiler::GenerateICCallThroughFunctionStub(Assembler* assembler) {
3244-
Label loop, found, miss;
3245-
__ movq(R13, FieldAddress(RBX, target::ICData::entries_offset()));
3246-
__ movq(R10,
3247-
FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
3248-
__ leaq(R13, FieldAddress(R13, target::Array::data_offset()));
3249-
// R13: first IC entry
3250-
__ LoadTaggedClassIdMayBeSmi(RAX, RDX);
3251-
// RAX: receiver cid as Smi
3252-
3253-
__ Bind(&loop);
3254-
__ movq(R9, Address(R13, 0));
3255-
__ cmpq(RAX, R9);
3256-
__ j(EQUAL, &found, Assembler::kNearJump);
3257-
3258-
ASSERT(target::ToRawSmi(kIllegalCid) == 0);
3259-
__ testq(R9, R9);
3260-
__ j(ZERO, &miss, Assembler::kNearJump);
3261-
3262-
const intptr_t entry_length =
3263-
target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
3264-
target::kWordSize;
3265-
__ addq(R13, Immediate(entry_length)); // Next entry.
3266-
__ jmp(&loop);
3267-
3268-
__ Bind(&found);
3269-
const intptr_t target_offset =
3270-
target::ICData::TargetIndexFor(1) * target::kWordSize;
3271-
__ movq(RAX, Address(R13, target_offset));
3272-
__ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
3273-
__ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
3274-
__ jmp(RCX);
3275-
3276-
__ Bind(&miss);
3277-
__ LoadIsolate(RAX);
3278-
__ movq(CODE_REG, Address(RAX, target::Isolate::ic_miss_code_offset()));
3279-
__ movq(RCX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
3280-
__ jmp(RCX);
3281-
}
3282-
32833237
void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
32843238
Label loop, found, miss;
32853239
__ movq(R13, FieldAddress(RBX, target::ICData::entries_offset()));

0 commit comments

Comments
 (0)