[vm] Re-order ICData entries to allow CID and count to be accessed with a load-pair.
Bug: https://github.com/dart-lang/sdk/issues/36731
Change-Id: Ia91ddb7e8991a5ab227ab8758173a99141c259be
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103004
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 8f927b8..758e065 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -368,8 +368,8 @@
return dart::ICData::TargetIndexFor(num_args);
}
-word ICData::ExactnessOffsetFor(word num_args) {
- return dart::ICData::ExactnessOffsetFor(num_args);
+word ICData::ExactnessIndexFor(word num_args) {
+ return dart::ICData::ExactnessIndexFor(num_args);
}
word ICData::TestEntryLengthFor(word num_args, bool exactness_check) {
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index d910575..29ff5ba 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -419,7 +419,7 @@
static word CodeIndexFor(word num_args);
static word CountIndexFor(word num_args);
static word TargetIndexFor(word num_args);
- static word ExactnessOffsetFor(word num_args);
+ static word ExactnessIndexFor(word num_args);
static word TestEntryLengthFor(word num_args, bool exactness_check);
static word EntryPointIndexFor(word num_args);
static word NumArgsTestedShift();
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 4313cd4..91728ca 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -2036,7 +2036,7 @@
const intptr_t count_offset =
target::ICData::CountIndexFor(num_args) * target::kWordSize;
const intptr_t exactness_offset =
- target::ICData::ExactnessOffsetFor(num_args) * target::kWordSize;
+ target::ICData::ExactnessIndexFor(num_args) * target::kWordSize;
__ Bind(&loop);
for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 3307d3e..a0ba01e 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -793,7 +793,7 @@
intptr_t i;
for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
if (cache->data()[i + 0] == receiver_cid) {
- top[0] = cache->data()[i + kCheckedArgs];
+ top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
found = true;
break;
}
@@ -841,7 +841,7 @@
for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
if ((cache->data()[i + 0] == receiver_cid) &&
(cache->data()[i + 1] == arg0_cid)) {
- top[0] = cache->data()[i + kCheckedArgs];
+ top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
found = true;
break;
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index d2e8a61..73cf977 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -13474,7 +13474,8 @@
}
// The final entry is always the sentinel.
ASSERT(IsSentinelAt(len - 1));
- if (NumArgsTested() == 0) {
+ const intptr_t num_args_tested = NumArgsTested();
+ if (num_args_tested == 0) {
// No type feedback is being collected.
const Array& data = Array::Handle(entries());
// Static calls with no argument checks hold only one target and the
@@ -13483,11 +13484,11 @@
// Static calls with no argument checks only need two words.
ASSERT(TestEntryLength() == 2);
// Set the target.
- data.SetAt(0, func);
+ data.SetAt(TargetIndexFor(num_args_tested), func);
// Set count to 0 as this is called during compilation, before the
// call has been executed.
const Smi& value = Smi::Handle(Smi::New(0));
- data.SetAt(1, value);
+ data.SetAt(CountIndexFor(num_args_tested), value);
} else {
// Type feedback on arguments is being collected.
const Array& data = Array::Handle(entries());
@@ -13501,9 +13502,9 @@
for (intptr_t i = 0; i < NumArgsTested(); i++) {
data.SetAt(i, object_cid);
}
- data.SetAt(NumArgsTested(), func);
+ data.SetAt(TargetIndexFor(num_args_tested), func);
const Smi& value = Smi::Handle(Smi::New(0));
- data.SetAt(NumArgsTested() + 1, value);
+ data.SetAt(CountIndexFor(num_args_tested), value);
}
}
@@ -13573,11 +13574,11 @@
WriteSentinel(data, TestEntryLength());
intptr_t data_pos = old_num * TestEntryLength();
ASSERT(!target.IsNull());
- data.SetAt(data_pos++, target);
+ data.SetAt(data_pos + TargetIndexFor(NumArgsTested()), target);
// Set count to 0 as this is called during compilation, before the
// call has been executed.
const Smi& value = Smi::Handle(Smi::New(0));
- data.SetAt(data_pos, value);
+ data.SetAt(data_pos + CountIndexFor(NumArgsTested()), value);
// Multithreaded access to ICData requires setting of array to be the last
// operation.
set_entries(data);
@@ -13608,7 +13609,8 @@
ASSERT((target.name() == target_name()) || ValidateInterceptor(target));
DEBUG_ASSERT(!HasCheck(class_ids));
ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'.
- ASSERT(class_ids.length() == NumArgsTested());
+ const intptr_t num_args_tested = NumArgsTested();
+ ASSERT(class_ids.length() == num_args_tested);
const intptr_t old_num = NumberOfChecks();
Array& data = Array::Handle(entries());
// ICData of static calls with NumArgsTested() > 0 have initially a
@@ -13616,14 +13618,14 @@
// overwritten by first real type feedback data.
if (old_num == 1) {
bool has_dummy_entry = true;
- for (intptr_t i = 0; i < NumArgsTested(); i++) {
+ for (intptr_t i = 0; i < num_args_tested; i++) {
if (Smi::Value(Smi::RawCast(data.At(i))) != kObjectCid) {
has_dummy_entry = false;
break;
}
}
if (has_dummy_entry) {
- ASSERT(target.raw() == data.At(NumArgsTested()));
+ ASSERT(target.raw() == data.At(TargetIndexFor(num_args_tested)));
// Replace dummy entry.
Smi& value = Smi::Handle();
for (intptr_t i = 0; i < NumArgsTested(); i++) {
@@ -13643,12 +13645,12 @@
// kIllegalCid is used as terminating value, do not add it.
ASSERT(class_ids[i] != kIllegalCid);
value = Smi::New(class_ids[i]);
- data.SetAt(data_pos++, value);
+ data.SetAt(data_pos + i, value);
}
ASSERT(!target.IsNull());
- data.SetAt(data_pos++, target);
+ data.SetAt(data_pos + TargetIndexFor(num_args_tested), target);
value = Smi::New(count);
- data.SetAt(data_pos++, value);
+ data.SetAt(data_pos + CountIndexFor(num_args_tested), value);
// Multithreaded access to ICData requires setting of array to be the last
// operation.
set_entries(data);
@@ -13697,7 +13699,8 @@
ASSERT(!HasCheck(class_ids));
#endif // DEBUG
ASSERT(!target.IsNull());
- ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'.
+ const intptr_t kNumArgsTested = 1;
+ ASSERT(NumArgsTested() == kNumArgsTested); // Otherwise use 'AddCheck'.
ASSERT(receiver_class_id != kIllegalCid);
intptr_t index = -1;
@@ -13714,10 +13717,12 @@
}
data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id)));
if (Isolate::Current()->compilation_allowed()) {
- data.SetAt(data_pos + 1, target);
- data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count)));
+ data.SetAt(data_pos + TargetIndexFor(kNumArgsTested), target);
+ data.SetAt(data_pos + CountIndexFor(kNumArgsTested),
+ Smi::Handle(Smi::New(count)));
if (is_tracking_exactness()) {
- data.SetAt(data_pos + 3, Smi::Handle(Smi::New(exactness.Encode())));
+ data.SetAt(data_pos + ExactnessIndexFor(kNumArgsTested),
+ Smi::Handle(Smi::New(exactness.Encode())));
}
} else {
// Precompilation only, after all functions have been compiled.
@@ -13725,8 +13730,8 @@
const Code& code = Code::Handle(target.CurrentCode());
const Smi& entry_point =
Smi::Handle(Smi::FromAlignedAddress(code.EntryPoint()));
- data.SetAt(data_pos + 1, code);
- data.SetAt(data_pos + 2, entry_point);
+ data.SetAt(data_pos + CodeIndexFor(kNumArgsTested), code);
+ data.SetAt(data_pos + EntryPointIndexFor(kNumArgsTested), entry_point);
}
// Multithreaded access to ICData requires setting of array to be the last
// operation.
@@ -13738,9 +13743,10 @@
return StaticTypeExactnessState::NotTracking();
}
const Array& data = Array::Handle(entries());
- intptr_t data_pos = index * TestEntryLength();
+ intptr_t data_pos =
+ index * TestEntryLength() + ExactnessIndexFor(NumArgsTested());
return StaticTypeExactnessState::Decode(
- Smi::Value(Smi::RawCast(data.At(data_pos + NumArgsTested() + 2))));
+ Smi::Value(Smi::RawCast(data.At(data_pos))));
}
void ICData::GetCheckAt(intptr_t index,
@@ -13753,9 +13759,9 @@
const Array& data = Array::Handle(entries());
intptr_t data_pos = index * TestEntryLength();
for (intptr_t i = 0; i < NumArgsTested(); i++) {
- class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++))));
+ class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos + i))));
}
- (*target) ^= data.At(data_pos++);
+ (*target) ^= data.At(data_pos + TargetIndexFor(NumArgsTested()));
}
bool ICData::IsSentinelAt(intptr_t index) const {
@@ -13794,7 +13800,7 @@
const Array& data = Array::Handle(entries());
const intptr_t data_pos = index * TestEntryLength();
*class_id = Smi::Value(Smi::RawCast(data.At(data_pos)));
- *target ^= data.At(data_pos + 1);
+ *target ^= data.At(data_pos + TargetIndexFor(NumArgsTested()));
}
intptr_t ICData::GetCidAt(intptr_t index) const {
@@ -13821,7 +13827,8 @@
RawFunction* ICData::GetTargetAt(intptr_t index) const {
ASSERT(Isolate::Current()->compilation_allowed());
- const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
+ const intptr_t data_pos =
+ index * TestEntryLength() + TargetIndexFor(NumArgsTested());
ASSERT(Object::Handle(Array::Handle(entries()).At(data_pos)).IsFunction());
NoSafepointScope no_safepoint;
@@ -13830,7 +13837,8 @@
}
RawObject* ICData::GetTargetOrCodeAt(intptr_t index) const {
- const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
+ const intptr_t data_pos =
+ index * TestEntryLength() + TargetIndexFor(NumArgsTested());
NoSafepointScope no_safepoint;
RawArray* raw_data = entries();
@@ -13894,18 +13902,6 @@
}
#if !defined(DART_PRECOMPILED_RUNTIME)
-RawFunction* ICData::GetTargetForReceiverClassId(intptr_t class_id,
- intptr_t* count_return) const {
- const intptr_t len = NumberOfChecks();
- for (intptr_t i = 0; i < len; i++) {
- if (GetReceiverClassIdAt(i) == class_id) {
- *count_return = GetCountAt(i);
- return GetTargetAt(i);
- }
- }
- return Function::null();
-}
-
RawICData* ICData::AsUnaryClassChecksForCid(intptr_t cid,
const Function& target) const {
ASSERT(!IsNull());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 2b04c83..725bc63 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1775,8 +1775,6 @@
intptr_t GetClassIdAt(intptr_t index, intptr_t arg_nr) const;
RawFunction* GetTargetAt(intptr_t index) const;
- RawFunction* GetTargetForReceiverClassId(intptr_t class_id,
- intptr_t* count_return) const;
RawObject* GetTargetOrCodeAt(intptr_t index) const;
void SetCodeAt(intptr_t index, const Code& value) const;
@@ -1829,16 +1827,13 @@
static intptr_t TestEntryLengthFor(intptr_t num_args,
bool tracking_exactness);
- static intptr_t TargetIndexFor(intptr_t num_args) { return num_args; }
- static intptr_t CodeIndexFor(intptr_t num_args) { return num_args; }
+ static intptr_t CountIndexFor(intptr_t num_args) { return num_args; }
+ static intptr_t EntryPointIndexFor(intptr_t num_args) { return num_args; }
- static intptr_t CountIndexFor(intptr_t num_args) { return (num_args + 1); }
- static intptr_t EntryPointIndexFor(intptr_t num_args) {
- return (num_args + 1);
- }
- static intptr_t ExactnessOffsetFor(intptr_t num_args) {
- return (num_args + 2);
- }
+ static intptr_t TargetIndexFor(intptr_t num_args) { return num_args + 1; }
+ static intptr_t CodeIndexFor(intptr_t num_args) { return num_args + 1; }
+
+ static intptr_t ExactnessIndexFor(intptr_t num_args) { return num_args + 2; }
bool IsUsedAt(intptr_t i) const;
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 23fa5e7..21c3382 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -874,7 +874,7 @@
intptr_t i;
for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
if (cache->data()[i + 0] == receiver_cid) {
- top[0] = cache->data()[i + kCheckedArgs];
+ top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
found = true;
break;
}
@@ -920,7 +920,7 @@
for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
if ((cache->data()[i + 0] == receiver_cid) &&
(cache->data()[i + 1] == arg0_cid)) {
- top[0] = cache->data()[i + kCheckedArgs];
+ top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
found = true;
break;
}