mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm] When loading a compilation trace, speculatively populate ICData based on the receiver's static type.
If the receiver's static type has one concrete implementation, lookup the target for that implementation and add it to the ICData's entries. For some well-known interfaces, do the same for the most common concrete implementation (e.g., int -> _Smi). Avoids method resolution during application startup. Bug: https://github.com/dart-lang/sdk/issues/36428 Change-Id: I57edf9c9cb5cb13af3182a100adce2802571a3aa Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/98445 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
parent
f93b93dd91
commit
9e1adc54a7
|
@ -60,6 +60,13 @@ CompilationTraceLoader::CompilationTraceLoader(Thread* thread)
|
|||
function_(Function::Handle(zone_)),
|
||||
function2_(Function::Handle(zone_)),
|
||||
field_(Field::Handle(zone_)),
|
||||
sites_(Array::Handle(zone_)),
|
||||
site_(ICData::Handle(zone_)),
|
||||
static_type_(AbstractType::Handle(zone_)),
|
||||
receiver_cls_(Class::Handle(zone_)),
|
||||
target_(Function::Handle(zone_)),
|
||||
selector_(String::Handle(zone_)),
|
||||
args_desc_(Array::Handle(zone_)),
|
||||
error_(Object::Handle(zone_)) {}
|
||||
|
||||
static char* FindCharacter(char* str, char goal, char* limit) {
|
||||
|
@ -354,14 +361,73 @@ RawObject* CompilationTraceLoader::CompileTriple(const char* uri_cstr,
|
|||
}
|
||||
|
||||
RawObject* CompilationTraceLoader::CompileFunction(const Function& function) {
|
||||
if (function.is_abstract()) {
|
||||
if (function.is_abstract() || function.HasCode()) {
|
||||
return Object::null();
|
||||
}
|
||||
|
||||
// Prevent premature code collection due to major GC during startup.
|
||||
if (function.usage_counter() < Function::kGraceUsageCounter) {
|
||||
function.set_usage_counter(Function::kGraceUsageCounter);
|
||||
}
|
||||
return Compiler::CompileFunction(thread_, function);
|
||||
|
||||
error_ = Compiler::CompileFunction(thread_, function);
|
||||
if (error_.IsError()) {
|
||||
return error_.raw();
|
||||
}
|
||||
|
||||
SpeculateInstanceCallTargets(function);
|
||||
|
||||
return error_.raw();
|
||||
}
|
||||
|
||||
// For instance calls, if the receiver's static type has one concrete
|
||||
// implementation, lookup the target for that implementation and add it
|
||||
// to the ICData's entries.
|
||||
// For some well-known interfaces, do the same for the most common concrete
|
||||
// implementation (e.g., int -> _Smi).
|
||||
void CompilationTraceLoader::SpeculateInstanceCallTargets(
|
||||
const Function& function) {
|
||||
sites_ = function.ic_data_array();
|
||||
ASSERT(!sites_.IsNull());
|
||||
for (intptr_t i = 1; i < sites_.Length(); i++) {
|
||||
site_ ^= sites_.At(i);
|
||||
if (site_.rebind_rule() != ICData::kInstance) {
|
||||
continue;
|
||||
}
|
||||
if (site_.NumArgsTested() != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
static_type_ = site_.receivers_static_type();
|
||||
if (static_type_.IsNull()) {
|
||||
continue;
|
||||
} else if (static_type_.IsDoubleType()) {
|
||||
receiver_cls_ = Isolate::Current()->class_table()->At(kDoubleCid);
|
||||
} else if (static_type_.IsIntType()) {
|
||||
receiver_cls_ = Isolate::Current()->class_table()->At(kSmiCid);
|
||||
} else if (static_type_.IsStringType()) {
|
||||
receiver_cls_ = Isolate::Current()->class_table()->At(kOneByteStringCid);
|
||||
} else if (static_type_.IsDartFunctionType() ||
|
||||
static_type_.IsDartClosureType()) {
|
||||
receiver_cls_ = Isolate::Current()->class_table()->At(kClosureCid);
|
||||
} else if (static_type_.HasTypeClass()) {
|
||||
receiver_cls_ = static_type_.type_class();
|
||||
if (receiver_cls_.is_implemented() || receiver_cls_.is_abstract()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
selector_ = site_.target_name();
|
||||
args_desc_ = site_.arguments_descriptor();
|
||||
target_ = Resolver::ResolveDynamicForReceiverClass(
|
||||
receiver_cls_, selector_, ArgumentsDescriptor(args_desc_));
|
||||
if (!target_.IsNull() && !site_.HasReceiverClassId(receiver_cls_.id())) {
|
||||
intptr_t count = 0; // Don't pollute type feedback and coverage data.
|
||||
site_.AddReceiverCheck(receiver_cls_.id(), target_, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TypeFeedbackSaver::TypeFeedbackSaver(WriteStream* stream)
|
||||
|
|
|
@ -42,6 +42,7 @@ class CompilationTraceLoader : public ValueObject {
|
|||
const char* cls_cstr,
|
||||
const char* func_cstr);
|
||||
RawObject* CompileFunction(const Function& function);
|
||||
void SpeculateInstanceCallTargets(const Function& function);
|
||||
|
||||
Thread* thread_;
|
||||
Zone* zone_;
|
||||
|
@ -54,6 +55,13 @@ class CompilationTraceLoader : public ValueObject {
|
|||
Function& function_;
|
||||
Function& function2_;
|
||||
Field& field_;
|
||||
Array& sites_;
|
||||
ICData& site_;
|
||||
AbstractType& static_type_;
|
||||
Class& receiver_cls_;
|
||||
Function& target_;
|
||||
String& selector_;
|
||||
Array& args_desc_;
|
||||
Object& error_;
|
||||
};
|
||||
|
||||
|
|
|
@ -567,7 +567,7 @@ void FlowGraph::AddExactnessGuard(InstanceCallInstr* call,
|
|||
InsertBefore(call, load_type_args, call->env(), FlowGraph::kValue);
|
||||
|
||||
const AbstractType& type =
|
||||
AbstractType::Handle(zone(), call->ic_data()->StaticReceiverType());
|
||||
AbstractType::Handle(zone(), call->ic_data()->receivers_static_type());
|
||||
ASSERT(!type.IsNull());
|
||||
const TypeArguments& args = TypeArguments::Handle(zone(), type.arguments());
|
||||
Instruction* guard = new (zone()) CheckConditionInstr(
|
||||
|
|
|
@ -1259,7 +1259,7 @@ static const Code& StubEntryFor(const ICData& ic_data, bool optimized) {
|
|||
switch (ic_data.NumArgsTested()) {
|
||||
case 1:
|
||||
#if defined(TARGET_ARCH_X64)
|
||||
if (ic_data.IsTrackingExactness()) {
|
||||
if (ic_data.is_tracking_exactness()) {
|
||||
if (optimized) {
|
||||
return StubCode::OneArgOptimizedCheckInlineCacheWithExactnessCheck();
|
||||
} else {
|
||||
|
@ -1268,12 +1268,12 @@ static const Code& StubEntryFor(const ICData& ic_data, bool optimized) {
|
|||
}
|
||||
#else
|
||||
// TODO(dartbug.com/34170) Port exactness tracking to other platforms.
|
||||
ASSERT(!ic_data.IsTrackingExactness());
|
||||
ASSERT(!ic_data.is_tracking_exactness());
|
||||
#endif
|
||||
return optimized ? StubCode::OneArgOptimizedCheckInlineCache()
|
||||
: StubCode::OneArgCheckInlineCache();
|
||||
case 2:
|
||||
ASSERT(!ic_data.IsTrackingExactness());
|
||||
ASSERT(!ic_data.is_tracking_exactness());
|
||||
return optimized ? StubCode::TwoArgsOptimizedCheckInlineCache()
|
||||
: StubCode::TwoArgsCheckInlineCache();
|
||||
default:
|
||||
|
@ -1759,7 +1759,7 @@ const ICData* FlowGraphCompiler::GetOrAddInstanceCallICData(
|
|||
ASSERT(res->TypeArgsLen() ==
|
||||
ArgumentsDescriptor(arguments_descriptor).TypeArgsLen());
|
||||
ASSERT(!res->is_static_call());
|
||||
ASSERT(res->StaticReceiverType() == receiver_type.raw());
|
||||
ASSERT(res->receivers_static_type() == receiver_type.raw());
|
||||
return res;
|
||||
}
|
||||
const ICData& ic_data = ICData::ZoneHandle(
|
||||
|
|
|
@ -4107,26 +4107,14 @@ void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
const Array& arguments_descriptor =
|
||||
Array::Handle(zone, GetArgumentsDescriptor());
|
||||
|
||||
AbstractType& static_receiver_type = AbstractType::Handle(zone);
|
||||
|
||||
#if defined(TARGET_ARCH_X64)
|
||||
// Enable static type exactness tracking for the callsite by setting
|
||||
// static receiver type on the ICData.
|
||||
if (checked_argument_count() == 1) {
|
||||
if (static_receiver_type_ != nullptr &&
|
||||
static_receiver_type_->HasTypeClass()) {
|
||||
const Class& cls =
|
||||
Class::Handle(zone, static_receiver_type_->type_class());
|
||||
if (cls.IsGeneric() && !cls.IsFutureOrClass()) {
|
||||
static_receiver_type = static_receiver_type_->raw();
|
||||
}
|
||||
}
|
||||
AbstractType& receivers_static_type = AbstractType::Handle(zone);
|
||||
if (receivers_static_type_ != nullptr) {
|
||||
receivers_static_type = receivers_static_type_->raw();
|
||||
}
|
||||
#endif
|
||||
|
||||
call_ic_data = compiler->GetOrAddInstanceCallICData(
|
||||
deopt_id(), function_name(), arguments_descriptor,
|
||||
checked_argument_count(), static_receiver_type);
|
||||
checked_argument_count(), receivers_static_type);
|
||||
} else {
|
||||
call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw());
|
||||
}
|
||||
|
|
|
@ -3327,9 +3327,9 @@ class InstanceCallInstr : public TemplateDartCall<0> {
|
|||
intptr_t checked_argument_count() const { return checked_argument_count_; }
|
||||
const Function& interface_target() const { return interface_target_; }
|
||||
|
||||
void set_static_receiver_type(const AbstractType* receiver_type) {
|
||||
ASSERT(receiver_type != nullptr && receiver_type->IsInstantiated());
|
||||
static_receiver_type_ = receiver_type;
|
||||
void set_receivers_static_type(const AbstractType* receiver_type) {
|
||||
ASSERT(receiver_type != nullptr);
|
||||
receivers_static_type_ = receiver_type;
|
||||
}
|
||||
|
||||
bool has_unique_selector() const { return has_unique_selector_; }
|
||||
|
@ -3390,7 +3390,7 @@ class InstanceCallInstr : public TemplateDartCall<0> {
|
|||
bool has_unique_selector_;
|
||||
Code::EntryKind entry_kind_ = Code::EntryKind::kNormal;
|
||||
|
||||
const AbstractType* static_receiver_type_ = nullptr;
|
||||
const AbstractType* receivers_static_type_ = nullptr;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(InstanceCallInstr);
|
||||
};
|
||||
|
|
|
@ -252,9 +252,9 @@ static void PrintICDataHelper(BufferFormatter* f,
|
|||
const ICData& ic_data,
|
||||
intptr_t num_checks_to_print) {
|
||||
f->Print(" IC[");
|
||||
if (ic_data.IsTrackingExactness()) {
|
||||
if (ic_data.is_tracking_exactness()) {
|
||||
f->Print("(%s) ",
|
||||
AbstractType::Handle(ic_data.StaticReceiverType()).ToCString());
|
||||
AbstractType::Handle(ic_data.receivers_static_type()).ToCString());
|
||||
}
|
||||
f->Print("%" Pd ": ", ic_data.NumberOfChecks());
|
||||
Function& target = Function::Handle();
|
||||
|
@ -278,7 +278,7 @@ static void PrintICDataHelper(BufferFormatter* f,
|
|||
f->Print("%s", String::Handle(cls.Name()).ToCString());
|
||||
}
|
||||
f->Print(" cnt:%" Pd " trgt:'%s'", count, target.ToQualifiedCString());
|
||||
if (ic_data.IsTrackingExactness()) {
|
||||
if (ic_data.is_tracking_exactness()) {
|
||||
f->Print(" %s", ic_data.GetExactnessAt(i).ToCString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -357,7 +357,12 @@ Fragment FlowGraphBuilder::InstanceCall(
|
|||
}
|
||||
if (call_site_attrs != nullptr && call_site_attrs->receiver_type != nullptr &&
|
||||
call_site_attrs->receiver_type->IsInstantiated()) {
|
||||
call->set_static_receiver_type(call_site_attrs->receiver_type);
|
||||
call->set_receivers_static_type(call_site_attrs->receiver_type);
|
||||
} else if (!interface_target.IsNull()) {
|
||||
const Class& owner = Class::Handle(Z, interface_target.Owner());
|
||||
const AbstractType& type =
|
||||
AbstractType::ZoneHandle(Z, owner.DeclarationType());
|
||||
call->set_receivers_static_type(&type);
|
||||
}
|
||||
Push(call);
|
||||
return Fragment(call);
|
||||
|
|
|
@ -348,8 +348,8 @@ word ICData::entries_offset() {
|
|||
return dart::ICData::entries_offset();
|
||||
}
|
||||
|
||||
word ICData::static_receiver_type_offset() {
|
||||
return dart::ICData::static_receiver_type_offset();
|
||||
word ICData::receivers_static_type_offset() {
|
||||
return dart::ICData::receivers_static_type_offset();
|
||||
}
|
||||
|
||||
word ICData::state_bits_offset() {
|
||||
|
|
|
@ -411,7 +411,7 @@ class ICData : public AllStatic {
|
|||
static word owner_offset();
|
||||
static word arguments_descriptor_offset();
|
||||
static word entries_offset();
|
||||
static word static_receiver_type_offset();
|
||||
static word receivers_static_type_offset();
|
||||
static word state_bits_offset();
|
||||
|
||||
static word CodeIndexFor(word num_args);
|
||||
|
|
|
@ -2017,10 +2017,10 @@ void StubCodeCompiler::GenerateNArgsCheckInlineCacheStub(
|
|||
__ j(EQUAL, &call_target_function_through_unchecked_entry);
|
||||
|
||||
// Check trivial exactness.
|
||||
// Note: RawICData::static_receiver_type_ is guaranteed to be not null
|
||||
// Note: RawICData::receivers_static_type_ is guaranteed to be not null
|
||||
// because we only emit calls to this stub when it is not null.
|
||||
__ movq(RCX,
|
||||
FieldAddress(RBX, target::ICData::static_receiver_type_offset()));
|
||||
FieldAddress(RBX, target::ICData::receivers_static_type_offset()));
|
||||
__ movq(RCX, FieldAddress(RCX, target::Type::arguments_offset()));
|
||||
// RAX contains an offset to type arguments in words as a smi,
|
||||
// hence TIMES_4. RDX is guaranteed to be non-smi because it is expected to
|
||||
|
|
|
@ -13146,14 +13146,24 @@ RawUnlinkedCall* UnlinkedCall::New() {
|
|||
}
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
void ICData::SetStaticReceiverType(const AbstractType& type) const {
|
||||
StorePointer(&raw_ptr()->static_receiver_type_, type.raw());
|
||||
void ICData::SetReceiversStaticType(const AbstractType& type) const {
|
||||
StorePointer(&raw_ptr()->receivers_static_type_, type.raw());
|
||||
|
||||
#if defined(TARGET_ARCH_X64)
|
||||
if (!type.IsNull() && type.HasTypeClass() && (NumArgsTested() == 1) &&
|
||||
type.IsInstantiated()) {
|
||||
const Class& cls = Class::Handle(type.type_class());
|
||||
if (cls.IsGeneric() && !cls.IsFutureOrClass()) {
|
||||
set_tracking_exactness(true);
|
||||
}
|
||||
}
|
||||
#endif // defined(TARGET_ARCH_X64)
|
||||
}
|
||||
#endif
|
||||
|
||||
void ICData::ResetSwitchable(Zone* zone) const {
|
||||
ASSERT(NumArgsTested() == 1);
|
||||
ASSERT(!IsTrackingExactness());
|
||||
ASSERT(!is_tracking_exactness());
|
||||
set_entries(Array::Handle(zone, CachedEmptyICDataArray(1, false)));
|
||||
}
|
||||
|
||||
|
@ -13298,7 +13308,7 @@ intptr_t ICData::TestEntryLengthFor(intptr_t num_args,
|
|||
}
|
||||
|
||||
intptr_t ICData::TestEntryLength() const {
|
||||
return TestEntryLengthFor(NumArgsTested(), IsTrackingExactness());
|
||||
return TestEntryLengthFor(NumArgsTested(), is_tracking_exactness());
|
||||
}
|
||||
|
||||
intptr_t ICData::Length() const {
|
||||
|
@ -13535,7 +13545,7 @@ bool ICData::ValidateInterceptor(const Function& target) const {
|
|||
void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids,
|
||||
const Function& target,
|
||||
intptr_t count) const {
|
||||
ASSERT(!IsTrackingExactness());
|
||||
ASSERT(!is_tracking_exactness());
|
||||
ASSERT(!target.IsNull());
|
||||
ASSERT((target.name() == target_name()) || ValidateInterceptor(target));
|
||||
DEBUG_ASSERT(!HasCheck(class_ids));
|
||||
|
@ -13648,7 +13658,7 @@ void ICData::AddReceiverCheck(intptr_t receiver_class_id,
|
|||
if (Isolate::Current()->compilation_allowed()) {
|
||||
data.SetAt(data_pos + 1, target);
|
||||
data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count)));
|
||||
if (IsTrackingExactness()) {
|
||||
if (is_tracking_exactness()) {
|
||||
data.SetAt(data_pos + 3, Smi::Handle(Smi::New(exactness.Encode())));
|
||||
}
|
||||
} else {
|
||||
|
@ -13666,7 +13676,7 @@ void ICData::AddReceiverCheck(intptr_t receiver_class_id,
|
|||
}
|
||||
|
||||
StaticTypeExactnessState ICData::GetExactnessAt(intptr_t index) const {
|
||||
if (!IsTrackingExactness()) {
|
||||
if (!is_tracking_exactness()) {
|
||||
return StaticTypeExactnessState::NotTracking();
|
||||
}
|
||||
const Array& data = Array::Handle(entries());
|
||||
|
@ -14086,7 +14096,7 @@ RawICData* ICData::NewDescriptor(Zone* zone,
|
|||
intptr_t deopt_id,
|
||||
intptr_t num_args_tested,
|
||||
RebindRule rebind_rule,
|
||||
const AbstractType& static_receiver_type) {
|
||||
const AbstractType& receivers_static_type) {
|
||||
ASSERT(!owner.IsNull());
|
||||
ASSERT(!target_name.IsNull());
|
||||
ASSERT(!arguments_descriptor.IsNull());
|
||||
|
@ -14107,7 +14117,7 @@ RawICData* ICData::NewDescriptor(Zone* zone,
|
|||
result.set_state_bits(0);
|
||||
result.set_rebind_rule(rebind_rule);
|
||||
result.SetNumArgsTested(num_args_tested);
|
||||
NOT_IN_PRECOMPILED(result.SetStaticReceiverType(static_receiver_type));
|
||||
NOT_IN_PRECOMPILED(result.SetReceiversStaticType(receivers_static_type));
|
||||
return result.raw();
|
||||
}
|
||||
|
||||
|
@ -14136,15 +14146,15 @@ RawICData* ICData::New(const Function& owner,
|
|||
intptr_t deopt_id,
|
||||
intptr_t num_args_tested,
|
||||
RebindRule rebind_rule,
|
||||
const AbstractType& static_receiver_type) {
|
||||
const AbstractType& receivers_static_type) {
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
const ICData& result = ICData::Handle(
|
||||
zone,
|
||||
NewDescriptor(zone, owner, target_name, arguments_descriptor, deopt_id,
|
||||
num_args_tested, rebind_rule, static_receiver_type));
|
||||
num_args_tested, rebind_rule, receivers_static_type));
|
||||
result.set_entries(Array::Handle(
|
||||
zone,
|
||||
CachedEmptyICDataArray(num_args_tested, result.IsTrackingExactness())));
|
||||
CachedEmptyICDataArray(num_args_tested, result.is_tracking_exactness())));
|
||||
return result.raw();
|
||||
}
|
||||
|
||||
|
@ -14154,7 +14164,7 @@ RawICData* ICData::NewFrom(const ICData& from, intptr_t num_args_tested) {
|
|||
Function::Handle(from.Owner()), String::Handle(from.target_name()),
|
||||
Array::Handle(from.arguments_descriptor()), from.deopt_id(),
|
||||
num_args_tested, from.rebind_rule(),
|
||||
AbstractType::Handle(from.StaticReceiverType())));
|
||||
AbstractType::Handle(from.receivers_static_type())));
|
||||
// Copy deoptimization reasons.
|
||||
result.SetDeoptReasons(from.DeoptReasons());
|
||||
return result.raw();
|
||||
|
@ -14162,12 +14172,13 @@ RawICData* ICData::NewFrom(const ICData& from, intptr_t num_args_tested) {
|
|||
|
||||
RawICData* ICData::Clone(const ICData& from) {
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
const ICData& result = ICData::Handle(ICData::NewDescriptor(
|
||||
zone, Function::Handle(zone, from.Owner()),
|
||||
String::Handle(zone, from.target_name()),
|
||||
Array::Handle(zone, from.arguments_descriptor()), from.deopt_id(),
|
||||
from.NumArgsTested(), from.rebind_rule(),
|
||||
AbstractType::Handle(from.StaticReceiverType())));
|
||||
const ICData& result = ICData::Handle(
|
||||
zone, ICData::NewDescriptor(
|
||||
zone, Function::Handle(zone, from.Owner()),
|
||||
String::Handle(zone, from.target_name()),
|
||||
Array::Handle(zone, from.arguments_descriptor()),
|
||||
from.deopt_id(), from.NumArgsTested(), from.rebind_rule(),
|
||||
AbstractType::Handle(zone, from.receivers_static_type())));
|
||||
// Clone entry array.
|
||||
const Array& from_array = Array::Handle(zone, from.entries());
|
||||
const intptr_t len = from_array.Length();
|
||||
|
|
|
@ -1588,15 +1588,20 @@ class ICData : public Object {
|
|||
bool IsImmutable() const;
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
RawAbstractType* StaticReceiverType() const {
|
||||
return raw_ptr()->static_receiver_type_;
|
||||
RawAbstractType* receivers_static_type() const {
|
||||
return raw_ptr()->receivers_static_type_;
|
||||
}
|
||||
void SetStaticReceiverType(const AbstractType& type) const;
|
||||
bool IsTrackingExactness() const {
|
||||
return StaticReceiverType() != Object::null();
|
||||
void SetReceiversStaticType(const AbstractType& type) const;
|
||||
bool is_tracking_exactness() const {
|
||||
return TrackingExactnessBit::decode(raw_ptr()->state_bits_);
|
||||
}
|
||||
void set_tracking_exactness(bool value) const {
|
||||
StoreNonPointer(
|
||||
&raw_ptr()->state_bits_,
|
||||
TrackingExactnessBit::update(value, raw_ptr()->state_bits_));
|
||||
}
|
||||
#else
|
||||
bool IsTrackingExactness() const { return false; }
|
||||
bool is_tracking_exactness() const { return false; }
|
||||
#endif
|
||||
|
||||
void Reset(Zone* zone) const;
|
||||
|
@ -1702,8 +1707,8 @@ class ICData : public Object {
|
|||
static intptr_t owner_offset() { return OFFSET_OF(RawICData, owner_); }
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
static intptr_t static_receiver_type_offset() {
|
||||
return OFFSET_OF(RawICData, static_receiver_type_);
|
||||
static intptr_t receivers_static_type_offset() {
|
||||
return OFFSET_OF(RawICData, receivers_static_type_);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1882,7 +1887,9 @@ class ICData : public Object {
|
|||
enum {
|
||||
kNumArgsTestedPos = 0,
|
||||
kNumArgsTestedSize = 2,
|
||||
kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize,
|
||||
kTrackingExactnessPos = kNumArgsTestedPos + kNumArgsTestedSize,
|
||||
kTrackingExactnessSize = 1,
|
||||
kDeoptReasonPos = kTrackingExactnessPos + kTrackingExactnessSize,
|
||||
kDeoptReasonSize = kLastRecordedDeoptReason + 1,
|
||||
kRebindRulePos = kDeoptReasonPos + kDeoptReasonSize,
|
||||
kRebindRuleSize = 3
|
||||
|
@ -1894,6 +1901,10 @@ class ICData : public Object {
|
|||
uint32_t,
|
||||
kNumArgsTestedPos,
|
||||
kNumArgsTestedSize> {};
|
||||
class TrackingExactnessBit : public BitField<uint32_t,
|
||||
bool,
|
||||
kTrackingExactnessPos,
|
||||
kTrackingExactnessSize> {};
|
||||
class DeoptReasonBits : public BitField<uint32_t,
|
||||
uint32_t,
|
||||
ICData::kDeoptReasonPos,
|
||||
|
|
|
@ -703,7 +703,7 @@ void ICData::Reset(Zone* zone) const {
|
|||
RebindRule rule = rebind_rule();
|
||||
if (rule == kInstance) {
|
||||
const intptr_t num_args = NumArgsTested();
|
||||
const bool tracking_exactness = IsTrackingExactness();
|
||||
const bool tracking_exactness = is_tracking_exactness();
|
||||
const intptr_t len = Length();
|
||||
// We need at least one non-sentinel entry to require a check
|
||||
// for the smi fast path case.
|
||||
|
|
|
@ -1701,10 +1701,8 @@ class RawICData : public RawObject {
|
|||
RawArray* entries_; // Contains class-ids, target and count.
|
||||
RawString* target_name_; // Name of target function.
|
||||
RawArray* args_descriptor_; // Arguments descriptor.
|
||||
// Static type of the receiver. If it is set then we are performing
|
||||
// exactness profiling for the receiver type. See StaticTypeExactnessState
|
||||
// class for more information.
|
||||
NOT_IN_PRECOMPILED(RawAbstractType* static_receiver_type_);
|
||||
// Static type of the receiver, if instance call and available.
|
||||
NOT_IN_PRECOMPILED(RawAbstractType* receivers_static_type_);
|
||||
RawObject* owner_; // Parent/calling function or original IC of cloned IC.
|
||||
VISIT_TO(RawObject*, owner_);
|
||||
RawObject** to_snapshot(Snapshot::Kind kind) {
|
||||
|
|
|
@ -1142,14 +1142,14 @@ static RawFunction* InlineCacheMissHandler(
|
|||
return target_function.raw();
|
||||
}
|
||||
if (args.length() == 1) {
|
||||
if (ic_data.IsTrackingExactness()) {
|
||||
if (ic_data.is_tracking_exactness()) {
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
const auto& receiver = *args[0];
|
||||
const auto state = receiver.IsNull()
|
||||
? StaticTypeExactnessState::NotExact()
|
||||
: StaticTypeExactnessState::Compute(
|
||||
Type::Cast(AbstractType::Handle(
|
||||
ic_data.StaticReceiverType())),
|
||||
ic_data.receivers_static_type())),
|
||||
receiver);
|
||||
ic_data.AddReceiverCheck(
|
||||
receiver.GetClassId(), target_function,
|
||||
|
|
Loading…
Reference in a new issue