Remember all deopt reasons in ic_data, not just the last one.
Remember if a JS warning was issued in ic_data. Save a word in ic_data on 64-bit platforms. R=iposva@google.com, srdjan@google.com Review URL: https://codereview.chromium.org//254723003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@35457 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -19,13 +19,14 @@ class DescriptorList : public ZoneAllocated {
|
||||
intptr_t pc_offset; // PC offset value of the descriptor.
|
||||
PcDescriptors::Kind kind; // Descriptor kind (kDeopt, kOther).
|
||||
intptr_t deopt_id; // Deoptimization id.
|
||||
intptr_t data; // Token position or deopt rason.
|
||||
intptr_t data; // Token position or deopt reason.
|
||||
intptr_t try_index; // Try block index of PC or deopt array index.
|
||||
void SetTokenPos(intptr_t value) { data = value; }
|
||||
intptr_t TokenPos() const { return data; }
|
||||
void SetDeoptReason(DeoptReasonId value) { data = value; }
|
||||
DeoptReasonId DeoptReason() const {
|
||||
return static_cast<DeoptReasonId>(data);
|
||||
void SetDeoptReason(ICData::DeoptReasonId value) { data = value; }
|
||||
ICData::DeoptReasonId DeoptReason() const {
|
||||
ASSERT((0 <= data) && (data < ICData::ICData::kDeoptNumReasons));
|
||||
return static_cast<ICData::DeoptReasonId>(data);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -49,7 +50,7 @@ class DescriptorList : public ZoneAllocated {
|
||||
intptr_t TokenPos(intptr_t index) const {
|
||||
return list_[index].TokenPos();
|
||||
}
|
||||
DeoptReasonId DeoptReason(intptr_t index) const {
|
||||
ICData::DeoptReasonId DeoptReason(intptr_t index) const {
|
||||
return list_[index].DeoptReason();
|
||||
}
|
||||
intptr_t TryIndex(intptr_t index) const {
|
||||
|
||||
@@ -747,7 +747,7 @@ static RawFunction* InlineCacheMissHandler(
|
||||
String::Handle(ic_data.target_name()).ToCString(),
|
||||
receiver.ToCString());
|
||||
}
|
||||
ic_data.set_is_closure_call(true);
|
||||
ic_data.SetIsClosureCall();
|
||||
target_function = InlineCacheMissHelper(receiver, ic_data);
|
||||
}
|
||||
ASSERT(!target_function.IsNull());
|
||||
@@ -755,7 +755,7 @@ static RawFunction* InlineCacheMissHandler(
|
||||
ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function);
|
||||
} else {
|
||||
GrowableArray<intptr_t> class_ids(args.length());
|
||||
ASSERT(ic_data.num_args_tested() == args.length());
|
||||
ASSERT(ic_data.NumArgsTested() == args.length());
|
||||
for (intptr_t i = 0; i < args.length(); i++) {
|
||||
class_ids.Add(args[i]->GetClassId());
|
||||
}
|
||||
@@ -908,7 +908,7 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
|
||||
name,
|
||||
args_desc));
|
||||
if (target_function.IsNull()) {
|
||||
ic_data.set_is_closure_call(true);
|
||||
ic_data.SetIsClosureCall();
|
||||
target_function = InlineCacheMissHelper(receiver, ic_data);
|
||||
}
|
||||
|
||||
@@ -1187,7 +1187,7 @@ DEFINE_RUNTIME_ENTRY(TraceICCall, 2) {
|
||||
ic_data.raw(),
|
||||
function.usage_counter(),
|
||||
ic_data.NumberOfChecks(),
|
||||
ic_data.is_closure_call() ? "closure" : "",
|
||||
ic_data.IsClosureCall() ? "closure" : "",
|
||||
function.ToFullyQualifiedCString());
|
||||
}
|
||||
|
||||
@@ -1269,11 +1269,11 @@ DEFINE_RUNTIME_ENTRY(FixCallersTarget, 0) {
|
||||
}
|
||||
|
||||
|
||||
const char* DeoptReasonToText(intptr_t deopt_id) {
|
||||
switch (deopt_id) {
|
||||
#define DEOPT_REASON_ID_TO_TEXT(name) case kDeopt##name: return #name;
|
||||
DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT)
|
||||
#undef DEOPT_REASON_ID_TO_TEXT
|
||||
const char* DeoptReasonToCString(ICData::ICData::DeoptReasonId deopt_reason) {
|
||||
switch (deopt_reason) {
|
||||
#define DEOPT_REASON_TO_TEXT(name) case ICData::kDeopt##name: return #name;
|
||||
DEOPT_REASONS(DEOPT_REASON_TO_TEXT)
|
||||
#undef DEOPT_REASON_TO_TEXT
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return "";
|
||||
@@ -1283,7 +1283,7 @@ DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT)
|
||||
|
||||
void DeoptimizeAt(const Code& optimized_code, uword pc) {
|
||||
ASSERT(optimized_code.is_optimized());
|
||||
intptr_t deopt_reason = kDeoptUnknown;
|
||||
ICData::DeoptReasonId deopt_reason = ICData::kDeoptUnknown;
|
||||
const DeoptInfo& deopt_info =
|
||||
DeoptInfo::Handle(optimized_code.GetDeoptInfoAtPc(pc, &deopt_reason));
|
||||
ASSERT(!deopt_info.IsNull());
|
||||
|
||||
@@ -47,45 +47,7 @@ DECLARE_RUNTIME_ENTRY(TraceFunctionExit);
|
||||
DECLARE_RUNTIME_ENTRY(DeoptimizeMaterialize);
|
||||
DECLARE_RUNTIME_ENTRY(UpdateFieldCid);
|
||||
|
||||
#define DEOPT_REASONS(V) \
|
||||
V(Unknown) \
|
||||
V(InstanceGetter) \
|
||||
V(PolymorphicInstanceCallTestFail) \
|
||||
V(InstanceCallNoICData) \
|
||||
V(IntegerToDouble) \
|
||||
V(BinarySmiOp) \
|
||||
V(BinaryMintOp) \
|
||||
V(UnaryMintOp) \
|
||||
V(ShiftMintOp) \
|
||||
V(BinaryDoubleOp) \
|
||||
V(InstanceSetter) \
|
||||
V(Equality) \
|
||||
V(RelationalOp) \
|
||||
V(EqualityClassCheck) \
|
||||
V(NoTypeFeedback) \
|
||||
V(UnaryOp) \
|
||||
V(UnboxInteger) \
|
||||
V(CheckClass) \
|
||||
V(HoistedCheckClass) \
|
||||
V(CheckSmi) \
|
||||
V(CheckArrayBound) \
|
||||
V(AtCall) \
|
||||
V(DoubleToSmi) \
|
||||
V(Int32Load) \
|
||||
V(Uint32Load) \
|
||||
V(GuardField) \
|
||||
V(TestCids) \
|
||||
V(NumReasons) \
|
||||
|
||||
enum DeoptReasonId {
|
||||
#define DEFINE_ENUM_LIST(name) kDeopt##name,
|
||||
DEOPT_REASONS(DEFINE_ENUM_LIST)
|
||||
#undef DEFINE_ENUM_LIST
|
||||
};
|
||||
|
||||
|
||||
const char* DeoptReasonToText(intptr_t deopt_id);
|
||||
|
||||
const char* DeoptReasonToCString(ICData::ICData::DeoptReasonId deopt_reason);
|
||||
|
||||
void DeoptimizeAt(const Code& optimized_code, uword pc);
|
||||
void DeoptimizeAll();
|
||||
|
||||
@@ -54,7 +54,7 @@ ASSEMBLER_TEST_RUN(IcDataAccess, test) {
|
||||
CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
|
||||
EXPECT_STREQ("targetFunction",
|
||||
String::Handle(ic_data.target_name()).ToCString());
|
||||
EXPECT_EQ(1, ic_data.num_args_tested());
|
||||
EXPECT_EQ(1, ic_data.NumArgsTested());
|
||||
EXPECT_EQ(0, ic_data.NumberOfChecks());
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ ASSEMBLER_TEST_RUN(IcDataAccess, test) {
|
||||
CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
|
||||
EXPECT_STREQ("targetFunction",
|
||||
String::Handle(ic_data.target_name()).ToCString());
|
||||
EXPECT_EQ(1, ic_data.num_args_tested());
|
||||
EXPECT_EQ(1, ic_data.NumArgsTested());
|
||||
EXPECT_EQ(0, ic_data.NumberOfChecks());
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ class InstanceCall : public UnoptimizedCall {
|
||||
#if defined(DEBUG)
|
||||
ICData& test_ic_data = ICData::Handle();
|
||||
test_ic_data ^= ic_data();
|
||||
ASSERT(test_ic_data.num_args_tested() > 0);
|
||||
ASSERT(test_ic_data.NumArgsTested() > 0);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ class UnoptimizedStaticCall : public UnoptimizedCall {
|
||||
#if defined(DEBUG)
|
||||
ICData& test_ic_data = ICData::Handle();
|
||||
test_ic_data ^= ic_data();
|
||||
ASSERT(test_ic_data.num_args_tested() >= 0);
|
||||
ASSERT(test_ic_data.NumArgsTested() >= 0);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ ASSEMBLER_TEST_RUN(IcDataAccess, test) {
|
||||
CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
|
||||
EXPECT_STREQ("targetFunction",
|
||||
String::Handle(ic_data.target_name()).ToCString());
|
||||
EXPECT_EQ(1, ic_data.num_args_tested());
|
||||
EXPECT_EQ(1, ic_data.NumArgsTested());
|
||||
EXPECT_EQ(0, ic_data.NumberOfChecks());
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ ASSEMBLER_TEST_RUN(IcDataAccess, test) {
|
||||
CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
|
||||
EXPECT_STREQ("targetFunction",
|
||||
String::Handle(ic_data.target_name()).ToCString());
|
||||
EXPECT_EQ(1, ic_data.num_args_tested());
|
||||
EXPECT_EQ(1, ic_data.NumArgsTested());
|
||||
EXPECT_EQ(0, ic_data.NumberOfChecks());
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class InstanceCall : public UnoptimizedCall {
|
||||
#if defined(DEBUG)
|
||||
ICData& test_ic_data = ICData::Handle();
|
||||
test_ic_data ^= ic_data();
|
||||
ASSERT(test_ic_data.num_args_tested() > 0);
|
||||
ASSERT(test_ic_data.NumArgsTested() > 0);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ class UnoptimizedStaticCall : public UnoptimizedCall {
|
||||
#if defined(DEBUG)
|
||||
ICData& test_ic_data = ICData::Handle();
|
||||
test_ic_data ^= ic_data();
|
||||
ASSERT(test_ic_data.num_args_tested() >= 0);
|
||||
ASSERT(test_ic_data.NumArgsTested() >= 0);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ ASSEMBLER_TEST_RUN(IcDataAccess, test) {
|
||||
CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
|
||||
EXPECT_STREQ("targetFunction",
|
||||
String::Handle(ic_data.target_name()).ToCString());
|
||||
EXPECT_EQ(1, ic_data.num_args_tested());
|
||||
EXPECT_EQ(1, ic_data.NumArgsTested());
|
||||
EXPECT_EQ(0, ic_data.NumberOfChecks());
|
||||
}
|
||||
|
||||
|
||||
@@ -659,11 +659,14 @@ static void DisassembleCode(const Function& function, bool optimized) {
|
||||
Smi& reason = Smi::Handle();
|
||||
for (intptr_t i = 0; i < deopt_table_length; ++i) {
|
||||
DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason);
|
||||
ASSERT((0 <= reason.Value()) &&
|
||||
(reason.Value() < ICData::kDeoptNumReasons));
|
||||
OS::Print("%4" Pd ": 0x%" Px " %s (%s)\n",
|
||||
i,
|
||||
start + offset.Value(),
|
||||
info.ToCString(),
|
||||
DeoptReasonToText(reason.Value()));
|
||||
DeoptReasonToCString(
|
||||
static_cast<ICData::DeoptReasonId>(reason.Value())));
|
||||
}
|
||||
OS::Print("}\n");
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ DeoptContext::DeoptContext(const StackFrame* frame,
|
||||
cpu_registers_(cpu_registers),
|
||||
fpu_registers_(fpu_registers),
|
||||
num_args_(0),
|
||||
deopt_reason_(kDeoptUnknown),
|
||||
deopt_reason_(ICData::kDeoptUnknown),
|
||||
isolate_(Isolate::Current()),
|
||||
deferred_boxes_(NULL),
|
||||
deferred_object_refs_(NULL),
|
||||
@@ -44,12 +44,12 @@ DeoptContext::DeoptContext(const StackFrame* frame,
|
||||
deferred_objects_(NULL) {
|
||||
object_table_ = code.object_table();
|
||||
|
||||
intptr_t deopt_reason = kDeoptUnknown;
|
||||
ICData::DeoptReasonId deopt_reason = ICData::kDeoptUnknown;
|
||||
const DeoptInfo& deopt_info =
|
||||
DeoptInfo::Handle(code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason));
|
||||
ASSERT(!deopt_info.IsNull());
|
||||
deopt_info_ = deopt_info.raw();
|
||||
deopt_reason_ = static_cast<DeoptReasonId>(deopt_reason);
|
||||
deopt_reason_ = deopt_reason;
|
||||
|
||||
const Function& function = Function::Handle(code.function());
|
||||
|
||||
@@ -96,9 +96,9 @@ DeoptContext::DeoptContext(const StackFrame* frame,
|
||||
|
||||
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
|
||||
OS::PrintErr(
|
||||
"Deoptimizing (reason %" Pd " '%s') at pc %#" Px " '%s' (count %d)\n",
|
||||
"Deoptimizing (reason %d '%s') at pc %#" Px " '%s' (count %d)\n",
|
||||
deopt_reason,
|
||||
DeoptReasonToText(deopt_reason_),
|
||||
DeoptReasonToCString(deopt_reason_),
|
||||
frame->pc(),
|
||||
function.ToFullyQualifiedCString(),
|
||||
function.deoptimization_counter());
|
||||
@@ -615,9 +615,10 @@ class DeoptRetAddressInstr : public DeoptInstr {
|
||||
ICData& ic_data = ICData::Handle();
|
||||
CodePatcher::GetInstanceCallAt(pc, code, &ic_data);
|
||||
if (!ic_data.IsNull()) {
|
||||
ic_data.set_deopt_reason(deopt_context->deopt_reason());
|
||||
ic_data.AddDeoptReason(deopt_context->deopt_reason());
|
||||
}
|
||||
} else if (deopt_context->deopt_reason() == kDeoptHoistedCheckClass) {
|
||||
} else if (deopt_context->deopt_reason() ==
|
||||
ICData::kDeoptHoistedCheckClass) {
|
||||
// Prevent excessive deoptimization.
|
||||
Function::Handle(code.function()).set_allows_hoisting_check_class(false);
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ class DeoptContext {
|
||||
|
||||
RawCode* code() const { return code_; }
|
||||
|
||||
DeoptReasonId deopt_reason() const { return deopt_reason_; }
|
||||
ICData::DeoptReasonId deopt_reason() const { return deopt_reason_; }
|
||||
|
||||
RawDeoptInfo* deopt_info() const { return deopt_info_; }
|
||||
|
||||
@@ -191,7 +191,7 @@ class DeoptContext {
|
||||
intptr_t* cpu_registers_;
|
||||
fpu_register_t* fpu_registers_;
|
||||
intptr_t num_args_;
|
||||
DeoptReasonId deopt_reason_;
|
||||
ICData::DeoptReasonId deopt_reason_;
|
||||
intptr_t caller_fp_;
|
||||
Isolate* isolate_;
|
||||
|
||||
|
||||
@@ -476,7 +476,7 @@ void FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id,
|
||||
ASSERT(is_optimizing());
|
||||
CompilerDeoptInfo* info =
|
||||
new CompilerDeoptInfo(deopt_id,
|
||||
kDeoptAtCall,
|
||||
ICData::kDeoptAtCall,
|
||||
pending_deoptimization_env_);
|
||||
info->set_pc_offset(assembler()->CodeSize());
|
||||
deopt_infos_.Add(info);
|
||||
@@ -633,7 +633,7 @@ Environment* FlowGraphCompiler::SlowPathEnvironmentFor(
|
||||
|
||||
|
||||
Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id,
|
||||
DeoptReasonId reason) {
|
||||
ICData::DeoptReasonId reason) {
|
||||
ASSERT(is_optimizing_);
|
||||
CompilerDeoptInfoWithStub* stub =
|
||||
new CompilerDeoptInfoWithStub(deopt_id,
|
||||
@@ -772,7 +772,7 @@ void FlowGraphCompiler::GenerateInstanceCall(
|
||||
ASSERT(FLAG_propagate_ic_data || (ic_data.NumberOfChecks() == 0));
|
||||
uword label_address = 0;
|
||||
if (is_optimizing() && (ic_data.NumberOfChecks() == 0)) {
|
||||
if (ic_data.is_closure_call()) {
|
||||
if (ic_data.IsClosureCall()) {
|
||||
// This IC call may be closure call only.
|
||||
label_address = StubCode::ClosureCallInlineCacheEntryPoint();
|
||||
ExternalLabel target_label("InlineCache", label_address);
|
||||
@@ -786,7 +786,7 @@ void FlowGraphCompiler::GenerateInstanceCall(
|
||||
ASSERT(!is_optimizing()
|
||||
|| may_reoptimize()
|
||||
|| flow_graph().IsCompiledForOsr());
|
||||
switch (ic_data.num_args_tested()) {
|
||||
switch (ic_data.NumArgsTested()) {
|
||||
case 1:
|
||||
label_address = StubCode::OneArgOptimizedCheckInlineCacheEntryPoint();
|
||||
break;
|
||||
@@ -812,7 +812,7 @@ void FlowGraphCompiler::GenerateInstanceCall(
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ic_data.num_args_tested()) {
|
||||
switch (ic_data.NumArgsTested()) {
|
||||
case 1:
|
||||
label_address = StubCode::OneArgCheckInlineCacheEntryPoint();
|
||||
break;
|
||||
@@ -1289,7 +1289,7 @@ static int HighestCountFirst(const CidTarget* a, const CidTarget* b) {
|
||||
// The expected number of elements to sort is less than 10.
|
||||
void FlowGraphCompiler::SortICDataByCount(const ICData& ic_data,
|
||||
GrowableArray<CidTarget>* sorted) {
|
||||
ASSERT(ic_data.num_args_tested() == 1);
|
||||
ASSERT(ic_data.NumArgsTested() == 1);
|
||||
const intptr_t len = ic_data.NumberOfChecks();
|
||||
sorted->Clear();
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ class ParallelMoveResolver : public ValueObject {
|
||||
class CompilerDeoptInfo : public ZoneAllocated {
|
||||
public:
|
||||
CompilerDeoptInfo(intptr_t deopt_id,
|
||||
DeoptReasonId reason,
|
||||
ICData::DeoptReasonId reason,
|
||||
Environment* deopt_env)
|
||||
: pc_offset_(-1),
|
||||
deopt_id_(deopt_id),
|
||||
@@ -131,7 +131,7 @@ class CompilerDeoptInfo : public ZoneAllocated {
|
||||
void set_pc_offset(intptr_t offset) { pc_offset_ = offset; }
|
||||
|
||||
intptr_t deopt_id() const { return deopt_id_; }
|
||||
DeoptReasonId reason() const { return reason_; }
|
||||
ICData::DeoptReasonId reason() const { return reason_; }
|
||||
const Environment* deopt_env() const { return deopt_env_; }
|
||||
|
||||
private:
|
||||
@@ -142,7 +142,7 @@ class CompilerDeoptInfo : public ZoneAllocated {
|
||||
|
||||
intptr_t pc_offset_;
|
||||
const intptr_t deopt_id_;
|
||||
const DeoptReasonId reason_;
|
||||
const ICData::DeoptReasonId reason_;
|
||||
Environment* deopt_env_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CompilerDeoptInfo);
|
||||
@@ -152,10 +152,10 @@ class CompilerDeoptInfo : public ZoneAllocated {
|
||||
class CompilerDeoptInfoWithStub : public CompilerDeoptInfo {
|
||||
public:
|
||||
CompilerDeoptInfoWithStub(intptr_t deopt_id,
|
||||
DeoptReasonId reason,
|
||||
ICData::DeoptReasonId reason,
|
||||
Environment* deopt_env)
|
||||
: CompilerDeoptInfo(deopt_id, reason, deopt_env), entry_label_() {
|
||||
ASSERT(reason != kDeoptAtCall);
|
||||
ASSERT(reason != ICData::kDeoptAtCall);
|
||||
}
|
||||
|
||||
Label* entry_label() { return &entry_label_; }
|
||||
@@ -414,7 +414,7 @@ class FlowGraphCompiler : public ValueObject {
|
||||
|
||||
void RecordSafepoint(LocationSummary* locs);
|
||||
|
||||
Label* AddDeoptStub(intptr_t deopt_id, DeoptReasonId reason);
|
||||
Label* AddDeoptStub(intptr_t deopt_id, ICData::DeoptReasonId reason);
|
||||
|
||||
void AddDeoptIndexAtCall(intptr_t deopt_id, intptr_t token_pos);
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
|
||||
void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
|
||||
intptr_t stub_ix) {
|
||||
// Calls do not need stubs, they share a deoptimization trampoline.
|
||||
ASSERT(reason() != kDeoptAtCall);
|
||||
ASSERT(reason() != ICData::kDeoptAtCall);
|
||||
Assembler* assem = compiler->assembler();
|
||||
#define __ assem->
|
||||
__ Comment("Deopt stub for id %" Pd "", deopt_id());
|
||||
@@ -1315,9 +1315,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
||||
num_args_checked)); // No arguments checked.
|
||||
ic_data.AddTarget(target_function);
|
||||
uword label_address = 0;
|
||||
if (ic_data.num_args_tested() == 0) {
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = StubCode::ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.num_args_tested() == 2) {
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = StubCode::TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
|
||||
@@ -692,9 +692,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
||||
num_args_checked)); // No arguments checked.
|
||||
ic_data.AddTarget(target_function);
|
||||
uword label_address = 0;
|
||||
if (ic_data.num_args_tested() == 0) {
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = StubCode::ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.num_args_tested() == 2) {
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = StubCode::TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
|
||||
@@ -153,7 +153,7 @@ RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
|
||||
void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
|
||||
intptr_t stub_ix) {
|
||||
// Calls do not need stubs, they share a deoptimization trampoline.
|
||||
ASSERT(reason() != kDeoptAtCall);
|
||||
ASSERT(reason() != ICData::kDeoptAtCall);
|
||||
Assembler* assem = compiler->assembler();
|
||||
#define __ assem->
|
||||
__ Comment("Deopt stub for id %" Pd "", deopt_id());
|
||||
@@ -1200,9 +1200,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
||||
num_args_checked)); // No arguments checked.
|
||||
ic_data.AddTarget(target_function);
|
||||
uword label_address = 0;
|
||||
if (ic_data.num_args_tested() == 0) {
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = StubCode::ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.num_args_tested() == 2) {
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = StubCode::TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
|
||||
@@ -152,7 +152,7 @@ RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
|
||||
void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
|
||||
intptr_t stub_ix) {
|
||||
// Calls do not need stubs, they share a deoptimization trampoline.
|
||||
ASSERT(reason() != kDeoptAtCall);
|
||||
ASSERT(reason() != ICData::kDeoptAtCall);
|
||||
Assembler* assem = compiler->assembler();
|
||||
#define __ assem->
|
||||
__ Comment("Deopt stub for id %" Pd "", deopt_id());
|
||||
@@ -1357,9 +1357,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
||||
num_args_checked)); // No arguments checked.
|
||||
ic_data.AddTarget(target_function);
|
||||
uword label_address = 0;
|
||||
if (ic_data.num_args_tested() == 0) {
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = StubCode::ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.num_args_tested() == 2) {
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = StubCode::TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
|
||||
@@ -150,7 +150,7 @@ RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
|
||||
void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
|
||||
intptr_t stub_ix) {
|
||||
// Calls do not need stubs, they share a deoptimization trampoline.
|
||||
ASSERT(reason() != kDeoptAtCall);
|
||||
ASSERT(reason() != ICData::kDeoptAtCall);
|
||||
Assembler* assem = compiler->assembler();
|
||||
#define __ assem->
|
||||
__ Comment("Deopt stub for id %" Pd "", deopt_id());
|
||||
@@ -1234,9 +1234,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
||||
num_args_checked)); // No arguments checked.
|
||||
ic_data.AddTarget(target_function);
|
||||
uword label_address = 0;
|
||||
if (ic_data.num_args_tested() == 0) {
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = StubCode::ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.num_args_tested() == 2) {
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = StubCode::TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
|
||||
@@ -1416,7 +1416,7 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
} else {
|
||||
const ICData& old_checks = call_->ic_data();
|
||||
const ICData& new_checks = ICData::ZoneHandle(
|
||||
ICData::New(Function::Handle(old_checks.function()),
|
||||
ICData::New(Function::Handle(old_checks.owner()),
|
||||
String::Handle(old_checks.target_name()),
|
||||
Array::Handle(old_checks.arguments_descriptor()),
|
||||
old_checks.deopt_id(),
|
||||
@@ -1548,7 +1548,7 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
|
||||
}
|
||||
const ICData& old_checks = call_->ic_data();
|
||||
const ICData& new_checks = ICData::ZoneHandle(
|
||||
ICData::New(Function::Handle(old_checks.function()),
|
||||
ICData::New(Function::Handle(old_checks.owner()),
|
||||
String::Handle(old_checks.target_name()),
|
||||
Array::Handle(old_checks.arguments_descriptor()),
|
||||
old_checks.deopt_id(),
|
||||
|
||||
@@ -109,9 +109,9 @@ bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
||||
// to megamorphic call.
|
||||
return false;
|
||||
}
|
||||
GrowableArray<intptr_t> class_ids(call->ic_data()->num_args_tested());
|
||||
ASSERT(call->ic_data()->num_args_tested() <= call->ArgumentCount());
|
||||
for (intptr_t i = 0; i < call->ic_data()->num_args_tested(); i++) {
|
||||
GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
|
||||
ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount());
|
||||
for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
|
||||
const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid();
|
||||
class_ids.Add(cid);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
||||
|
||||
|
||||
static const ICData& TrySpecializeICData(const ICData& ic_data, intptr_t cid) {
|
||||
ASSERT(ic_data.num_args_tested() == 1);
|
||||
ASSERT(ic_data.NumArgsTested() == 1);
|
||||
|
||||
if ((ic_data.NumberOfChecks() == 1) &&
|
||||
(ic_data.GetReceiverClassIdAt(0) == cid)) {
|
||||
@@ -186,12 +186,12 @@ static const ICData& TrySpecializeICData(const ICData& ic_data, intptr_t cid) {
|
||||
// not found in the ICData.
|
||||
if (!function.IsNull()) {
|
||||
const ICData& new_ic_data = ICData::ZoneHandle(ICData::New(
|
||||
Function::Handle(ic_data.function()),
|
||||
Function::Handle(ic_data.owner()),
|
||||
String::Handle(ic_data.target_name()),
|
||||
Object::empty_array(), // Dummy argument descriptor.
|
||||
ic_data.deopt_id(),
|
||||
ic_data.num_args_tested()));
|
||||
new_ic_data.set_deopt_reason(ic_data.deopt_reason());
|
||||
ic_data.NumArgsTested()));
|
||||
new_ic_data.SetDeoptReasons(ic_data.DeoptReasons());
|
||||
new_ic_data.AddReceiverCheck(cid, function);
|
||||
return new_ic_data;
|
||||
}
|
||||
@@ -817,7 +817,7 @@ static bool ICDataHasReceiverArgumentClassIds(const ICData& ic_data,
|
||||
intptr_t argument_class_id) {
|
||||
ASSERT(receiver_class_id != kIllegalCid);
|
||||
ASSERT(argument_class_id != kIllegalCid);
|
||||
if (ic_data.num_args_tested() != 2) return false;
|
||||
if (ic_data.NumArgsTested() != 2) return false;
|
||||
|
||||
Function& target = Function::Handle();
|
||||
const intptr_t len = ic_data.NumberOfChecks();
|
||||
@@ -851,7 +851,7 @@ static bool ICDataHasOnlyReceiverArgumentClassIds(
|
||||
const ICData& ic_data,
|
||||
const GrowableArray<intptr_t>& receiver_class_ids,
|
||||
const GrowableArray<intptr_t>& argument_class_ids) {
|
||||
if (ic_data.num_args_tested() != 2) return false;
|
||||
if (ic_data.NumArgsTested() != 2) return false;
|
||||
Function& target = Function::Handle();
|
||||
const intptr_t len = ic_data.NumberOfChecks();
|
||||
for (intptr_t i = 0; i < len; i++) {
|
||||
@@ -988,7 +988,7 @@ void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) {
|
||||
static bool ArgIsAlways(intptr_t cid,
|
||||
const ICData& ic_data,
|
||||
intptr_t arg_number) {
|
||||
ASSERT(ic_data.num_args_tested() > arg_number);
|
||||
ASSERT(ic_data.NumArgsTested() > arg_number);
|
||||
const intptr_t num_checks = ic_data.NumberOfChecks();
|
||||
if (num_checks == 0) return false;
|
||||
for (intptr_t i = 0; i < num_checks; i++) {
|
||||
@@ -1585,8 +1585,8 @@ bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind,
|
||||
(array_cid == kTypedDataUint32ArrayCid)) {
|
||||
// Set deopt_id if we can optimistically assume that the result is Smi.
|
||||
// Assume mixed Mint/Smi if this instruction caused deoptimization once.
|
||||
deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
|
||||
call->deopt_id() : Isolate::kNoDeoptId;
|
||||
deopt_id = ic_data.HasDeoptReasons() ?
|
||||
Isolate::kNoDeoptId : call->deopt_id();
|
||||
}
|
||||
|
||||
// Array load and return.
|
||||
@@ -1767,7 +1767,7 @@ static bool SmiFitsInDouble() { return kSmiBits < 53; }
|
||||
bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
|
||||
Token::Kind op_kind) {
|
||||
const ICData& ic_data = *call->ic_data();
|
||||
ASSERT(ic_data.num_args_tested() == 2);
|
||||
ASSERT(ic_data.NumArgsTested() == 2);
|
||||
|
||||
ASSERT(call->ArgumentCount() == 2);
|
||||
Definition* left = call->ArgumentAt(0);
|
||||
@@ -1871,7 +1871,7 @@ bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
|
||||
bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
|
||||
Token::Kind op_kind) {
|
||||
const ICData& ic_data = *call->ic_data();
|
||||
ASSERT(ic_data.num_args_tested() == 2);
|
||||
ASSERT(ic_data.NumArgsTested() == 2);
|
||||
|
||||
ASSERT(call->ArgumentCount() == 2);
|
||||
Definition* left = call->ArgumentAt(0);
|
||||
@@ -1936,14 +1936,14 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
||||
if (HasOnlyTwoOf(ic_data, kSmiCid)) {
|
||||
// Don't generate smi code if the IC data is marked because
|
||||
// of an overflow.
|
||||
operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp)
|
||||
operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)
|
||||
? kMintCid
|
||||
: kSmiCid;
|
||||
} else if (HasTwoMintOrSmi(ic_data) &&
|
||||
FlowGraphCompiler::SupportsUnboxedMints()) {
|
||||
// Don't generate mint code if the IC data is marked because of an
|
||||
// overflow.
|
||||
if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false;
|
||||
if (ic_data.HasDeoptReason(ICData::kDeoptBinaryMintOp)) return false;
|
||||
operands_type = kMintCid;
|
||||
} else if (ShouldSpecializeForDouble(ic_data)) {
|
||||
operands_type = kDoubleCid;
|
||||
@@ -1962,7 +1962,7 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
||||
// Don't generate smi code if the IC data is marked because of an
|
||||
// overflow.
|
||||
// TODO(fschneider): Add unboxed mint multiplication.
|
||||
if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false;
|
||||
if (ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)) return false;
|
||||
operands_type = kSmiCid;
|
||||
} else if (ShouldSpecializeForDouble(ic_data)) {
|
||||
operands_type = kDoubleCid;
|
||||
@@ -2005,10 +2005,10 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
||||
// Left shift may overflow from smi into mint or big ints.
|
||||
// Don't generate smi code if the IC data is marked because
|
||||
// of an overflow.
|
||||
if (ic_data.deopt_reason() == kDeoptShiftMintOp) {
|
||||
if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) {
|
||||
return false;
|
||||
}
|
||||
operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp)
|
||||
operands_type = ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)
|
||||
? kMintCid
|
||||
: kSmiCid;
|
||||
} else if (HasTwoMintOrSmi(ic_data) &&
|
||||
@@ -2016,7 +2016,7 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
||||
ic_data.AsUnaryClassChecksForArgNr(1)))) {
|
||||
// Don't generate mint code if the IC data is marked because of an
|
||||
// overflow.
|
||||
if (ic_data.deopt_reason() == kDeoptShiftMintOp) {
|
||||
if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) {
|
||||
return false;
|
||||
}
|
||||
// Check for smi/mint << smi or smi/mint >> smi.
|
||||
@@ -2028,7 +2028,7 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
||||
case Token::kMOD:
|
||||
case Token::kTRUNCDIV:
|
||||
if (HasOnlyTwoOf(ic_data, kSmiCid)) {
|
||||
if (ic_data.deopt_reason() == kDeoptBinarySmiOp) {
|
||||
if (ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)) {
|
||||
return false;
|
||||
}
|
||||
operands_type = kSmiCid;
|
||||
@@ -2831,7 +2831,7 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
||||
const ICData& ic_data = *call->ic_data();
|
||||
Definition* input = call->ArgumentAt(0);
|
||||
Definition* d2i_instr = NULL;
|
||||
if (ic_data.deopt_reason() == kDeoptDoubleToSmi) {
|
||||
if (ic_data.HasDeoptReason(ICData::kDeoptDoubleToSmi)) {
|
||||
// Do not repeatedly deoptimize because result didn't fit into Smi.
|
||||
d2i_instr = new DoubleToIntegerInstr(new Value(input), call);
|
||||
} else {
|
||||
@@ -2939,12 +2939,12 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
||||
|
||||
if (recognized_kind == MethodRecognizer::kIntegerLeftShiftWithMask32) {
|
||||
ASSERT(call->ArgumentCount() == 3);
|
||||
ASSERT(ic_data.num_args_tested() == 2);
|
||||
ASSERT(ic_data.NumArgsTested() == 2);
|
||||
Definition* value = call->ArgumentAt(0);
|
||||
Definition* count = call->ArgumentAt(1);
|
||||
Definition* int32_mask = call->ArgumentAt(2);
|
||||
if (HasOnlyTwoOf(ic_data, kSmiCid)) {
|
||||
if (ic_data.deopt_reason() == kDeoptShiftMintOp) {
|
||||
if (ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) {
|
||||
return false;
|
||||
}
|
||||
// We cannot overflow. The input value must be a Smi
|
||||
@@ -2981,7 +2981,7 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
||||
if (HasTwoMintOrSmi(ic_data) &&
|
||||
HasOnlyOneSmi(ICData::Handle(ic_data.AsUnaryClassChecksForArgNr(1)))) {
|
||||
if (!FlowGraphCompiler::SupportsUnboxedMints() ||
|
||||
(ic_data.deopt_reason() == kDeoptShiftMintOp)) {
|
||||
ic_data.HasDeoptReason(ICData::kDeoptShiftMintOp)) {
|
||||
return false;
|
||||
}
|
||||
ShiftMintOpInstr* left_shift =
|
||||
@@ -3407,8 +3407,8 @@ bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call,
|
||||
(array_cid == kTypedDataUint32ArrayCid)) {
|
||||
// Set deopt_id if we can optimistically assume that the result is Smi.
|
||||
// Assume mixed Mint/Smi if this instruction caused deoptimization once.
|
||||
deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
|
||||
call->deopt_id() : Isolate::kNoDeoptId;
|
||||
deopt_id = ic_data.HasDeoptReasons() ?
|
||||
Isolate::kNoDeoptId : call->deopt_id();
|
||||
}
|
||||
|
||||
*last = new LoadIndexedInstr(new Value(array),
|
||||
@@ -3489,7 +3489,7 @@ bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target,
|
||||
// We don't have ICData for the value stored, so we optimistically assume
|
||||
// smis first. If we ever deoptimized here, we require to unbox the value
|
||||
// before storing to handle the mint case, too.
|
||||
if (i_call->ic_data()->deopt_reason() == kDeoptUnknown) {
|
||||
if (!i_call->ic_data()->HasDeoptReasons()) {
|
||||
value_check = ICData::New(flow_graph_->parsed_function().function(),
|
||||
i_call->function_name(),
|
||||
Object::empty_array(), // Dummy args. descr.
|
||||
@@ -3684,7 +3684,7 @@ RawBool* FlowGraphOptimizer::InstanceOfAsBool(
|
||||
const AbstractType& type,
|
||||
ZoneGrowableArray<intptr_t>* results) const {
|
||||
results->Clear();
|
||||
ASSERT(ic_data.num_args_tested() == 1); // Unary checks only.
|
||||
ASSERT(ic_data.NumArgsTested() == 1); // Unary checks only.
|
||||
if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) {
|
||||
return Bool::null();
|
||||
}
|
||||
@@ -4228,7 +4228,7 @@ void FlowGraphOptimizer::VisitStoreInstanceField(
|
||||
bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
|
||||
const ICData& unary_ic_data) {
|
||||
ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
|
||||
(unary_ic_data.num_args_tested() == 1));
|
||||
(unary_ic_data.NumArgsTested() == 1));
|
||||
if (FLAG_enable_type_checks) {
|
||||
// Checked mode setters are inlined like normal methods by conventional
|
||||
// inlining.
|
||||
|
||||
@@ -91,7 +91,7 @@ CheckClassInstr::CheckClassInstr(Value* value,
|
||||
// Expected useful check data.
|
||||
ASSERT(!unary_checks_.IsNull());
|
||||
ASSERT(unary_checks_.NumberOfChecks() > 0);
|
||||
ASSERT(unary_checks_.num_args_tested() == 1);
|
||||
ASSERT(unary_checks_.NumArgsTested() == 1);
|
||||
SetInputAt(0, value);
|
||||
deopt_id_ = deopt_id;
|
||||
// Otherwise use CheckSmiInstr.
|
||||
|
||||
@@ -710,7 +710,7 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
Register cid_reg = locs()->temp(0).reg();
|
||||
|
||||
Label* deopt = CanDeoptimize() ?
|
||||
compiler->AddDeoptStub(deopt_id(), kDeoptTestCids) : NULL;
|
||||
compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL;
|
||||
|
||||
const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
|
||||
const ZoneGrowableArray<intptr_t>& data = cid_results();
|
||||
@@ -1246,7 +1246,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ SmiTag(result);
|
||||
break;
|
||||
case kTypedDataInt32ArrayCid: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptInt32Load);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptInt32Load);
|
||||
__ ldr(result, element_address);
|
||||
// Verify that the signed value in 'result' can fit inside a Smi.
|
||||
__ CompareImmediate(result, 0xC0000000);
|
||||
@@ -1255,7 +1256,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
break;
|
||||
case kTypedDataUint32ArrayCid: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptUint32Load);
|
||||
__ ldr(result, element_address);
|
||||
// Verify that the unsigned value in 'result' can fit inside a Smi.
|
||||
__ TestImmediate(result, 0xC0000000);
|
||||
@@ -1553,7 +1555,7 @@ void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label ok, fail_label;
|
||||
|
||||
Label* deopt = compiler->is_optimizing() ?
|
||||
compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL;
|
||||
compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
|
||||
|
||||
Label* fail = (deopt != NULL) ? deopt : &fail_label;
|
||||
|
||||
@@ -2747,7 +2749,8 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
|
||||
Register left = locs.in(0).reg();
|
||||
Register result = locs.out(0).reg();
|
||||
Label* deopt = shift_left->CanDeoptimize() ?
|
||||
compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL;
|
||||
compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
|
||||
: NULL;
|
||||
if (locs.in(1).IsConstant()) {
|
||||
const Object& constant = locs.in(1).constant();
|
||||
ASSERT(constant.IsSmi());
|
||||
@@ -2902,7 +2905,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register result = locs()->out(0).reg();
|
||||
Label* deopt = NULL;
|
||||
if (CanDeoptimize()) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
||||
}
|
||||
|
||||
if (locs()->in(1).IsConstant()) {
|
||||
@@ -3197,7 +3200,8 @@ LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptBinaryDoubleOp);
|
||||
intptr_t left_cid = left()->Type()->ToCid();
|
||||
intptr_t right_cid = right()->Type()->ToCid();
|
||||
Register left = locs()->in(0).reg();
|
||||
@@ -3273,7 +3277,8 @@ void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ vmovsr(STMP, value);
|
||||
__ vcvtdi(result, STMP);
|
||||
} else {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_,
|
||||
ICData::kDeoptBinaryDoubleOp);
|
||||
Register temp = locs()->temp(0).reg();
|
||||
Label is_smi, done;
|
||||
__ tst(value, ShifterOperand(kSmiTagMask));
|
||||
@@ -3348,7 +3353,7 @@ void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
if (value_cid != kFloat32x4Cid) {
|
||||
const Register temp = locs()->temp(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass);
|
||||
__ tst(value, ShifterOperand(kSmiTagMask));
|
||||
__ b(deopt, EQ);
|
||||
__ CompareClassId(value, kFloat32x4Cid, temp);
|
||||
@@ -3417,7 +3422,7 @@ void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
if (value_cid != kFloat64x2Cid) {
|
||||
const Register temp = locs()->temp(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass);
|
||||
__ tst(value, ShifterOperand(kSmiTagMask));
|
||||
__ b(deopt, EQ);
|
||||
__ CompareClassId(value, kFloat64x2Cid, temp);
|
||||
@@ -3517,7 +3522,7 @@ void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
if (value_cid != kInt32x4Cid) {
|
||||
const Register temp = locs()->temp(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass);
|
||||
__ tst(value, ShifterOperand(kSmiTagMask));
|
||||
__ b(deopt, EQ);
|
||||
__ CompareClassId(value, kInt32x4Cid, temp);
|
||||
@@ -4828,8 +4833,7 @@ void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register result = locs()->out(0).reg();
|
||||
switch (op_kind()) {
|
||||
case Token::kNEGATE: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptUnaryOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
|
||||
__ rsbs(result, value, ShifterOperand(0));
|
||||
__ b(deopt, VS);
|
||||
break;
|
||||
@@ -4947,7 +4951,7 @@ LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi);
|
||||
Register result = locs()->out(0).reg();
|
||||
DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg());
|
||||
// First check for NaN. Checking for minint after the conversion doesn't work
|
||||
@@ -5209,7 +5213,7 @@ LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
|
||||
void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = NULL;
|
||||
if (CanDeoptimize()) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
||||
}
|
||||
if (kind() == MergedMathInstr::kTruncDivMod) {
|
||||
Register left = locs()->in(0).reg();
|
||||
@@ -5275,13 +5279,13 @@ LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
|
||||
|
||||
|
||||
void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptPolymorphicInstanceCallTestFail);
|
||||
Label* deopt = compiler->AddDeoptStub(
|
||||
deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
|
||||
if (ic_data().NumberOfChecks() == 0) {
|
||||
__ b(deopt);
|
||||
return;
|
||||
}
|
||||
ASSERT(ic_data().num_args_tested() == 1);
|
||||
ASSERT(ic_data().NumArgsTested() == 1);
|
||||
if (!with_checks()) {
|
||||
ASSERT(ic_data().HasOneTarget());
|
||||
const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
|
||||
@@ -5339,8 +5343,8 @@ LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const DeoptReasonId deopt_reason =
|
||||
licm_hoisted_ ? kDeoptHoistedCheckClass : kDeoptCheckClass;
|
||||
const ICData::DeoptReasonId deopt_reason = licm_hoisted_ ?
|
||||
ICData::kDeoptHoistedCheckClass : ICData::kDeoptCheckClass;
|
||||
if (IsNullCheck()) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
|
||||
__ CompareImmediate(locs()->in(0).reg(),
|
||||
@@ -5391,8 +5395,7 @@ LocationSummary* CheckSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register value = locs()->in(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptCheckSmi);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi);
|
||||
__ tst(value, ShifterOperand(kSmiTagMask));
|
||||
__ b(deopt, NE);
|
||||
}
|
||||
@@ -5410,7 +5413,8 @@ LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptCheckArrayBound);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptCheckArrayBound);
|
||||
|
||||
Location length_loc = locs()->in(kLengthPos);
|
||||
Location index_loc = locs()->in(kIndexPos);
|
||||
@@ -5510,7 +5514,8 @@ void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ vmovdrr(EvenDRegisterOf(result), value, temp);
|
||||
} else {
|
||||
Register temp = locs()->temp(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptUnboxInteger);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_,
|
||||
ICData::kDeoptUnboxInteger);
|
||||
Label is_smi, done;
|
||||
__ tst(value, ShifterOperand(kSmiTagMask));
|
||||
__ b(&is_smi, EQ);
|
||||
@@ -5662,7 +5667,7 @@ void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
Label* deopt = NULL;
|
||||
if (FLAG_throw_on_javascript_int_overflow) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
|
||||
}
|
||||
switch (op_kind()) {
|
||||
case Token::kBIT_AND: __ vandq(out, left, right); break;
|
||||
@@ -5675,7 +5680,7 @@ void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
|
||||
ASSERT(ro == Q7);
|
||||
if (!FLAG_throw_on_javascript_int_overflow) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
|
||||
}
|
||||
if (op_kind() == Token::kADD) {
|
||||
__ vaddqi(kWordPair, out, left, right);
|
||||
@@ -5729,7 +5734,7 @@ void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
SRegister stemp0 = EvenSRegisterOf(dtemp0);
|
||||
SRegister stemp1 = OddSRegisterOf(dtemp0);
|
||||
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptShiftMintOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
|
||||
Label done;
|
||||
|
||||
__ CompareImmediate(shift, 0);
|
||||
@@ -5807,8 +5812,7 @@ void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
QRegister out = locs()->out(0).fpu_reg();
|
||||
Label* deopt = NULL;
|
||||
if (FLAG_throw_on_javascript_int_overflow) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptUnaryMintOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
|
||||
}
|
||||
__ vmvnq(out, value);
|
||||
if (FLAG_throw_on_javascript_int_overflow) {
|
||||
|
||||
@@ -602,7 +602,7 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
Register cid_reg = locs()->temp(0).reg();
|
||||
|
||||
Label* deopt = CanDeoptimize() ?
|
||||
compiler->AddDeoptStub(deopt_id(), kDeoptTestCids) : NULL;
|
||||
compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL;
|
||||
|
||||
const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
|
||||
const ZoneGrowableArray<intptr_t>& data = cid_results();
|
||||
@@ -1080,7 +1080,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ SmiTag(result);
|
||||
break;
|
||||
case kTypedDataInt32ArrayCid: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptInt32Load);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptInt32Load);
|
||||
__ movl(result, element_address);
|
||||
// Verify that the signed value in 'result' can fit inside a Smi.
|
||||
__ cmpl(result, Immediate(0xC0000000));
|
||||
@@ -1089,7 +1090,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
break;
|
||||
case kTypedDataUint32ArrayCid: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptUint32Load);
|
||||
__ movl(result, element_address);
|
||||
// Verify that the unsigned value in 'result' can fit inside a Smi.
|
||||
__ testl(result, Immediate(0xC0000000));
|
||||
@@ -1374,7 +1376,7 @@ void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label ok, fail_label;
|
||||
|
||||
Label* deopt = compiler->is_optimizing() ?
|
||||
compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL;
|
||||
compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
|
||||
|
||||
Label* fail = (deopt != NULL) ? deopt : &fail_label;
|
||||
|
||||
@@ -2686,7 +2688,8 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
|
||||
Register result = locs.out(0).reg();
|
||||
ASSERT(left == result);
|
||||
Label* deopt = shift_left->CanDeoptimize() ?
|
||||
compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL;
|
||||
compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
|
||||
: NULL;
|
||||
if (locs.in(1).IsConstant()) {
|
||||
const Object& constant = locs.in(1).constant();
|
||||
ASSERT(constant.IsSmi());
|
||||
@@ -2880,7 +2883,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(left == result);
|
||||
Label* deopt = NULL;
|
||||
if (CanDeoptimize()) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
||||
}
|
||||
|
||||
if (locs()->in(1).IsConstant()) {
|
||||
@@ -3186,7 +3189,8 @@ LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptBinaryDoubleOp);
|
||||
intptr_t left_cid = left()->Type()->ToCid();
|
||||
intptr_t right_cid = right()->Type()->ToCid();
|
||||
Register left = locs()->in(0).reg();
|
||||
@@ -3266,7 +3270,8 @@ void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ SmiUntag(value); // Untag input before conversion.
|
||||
__ cvtsi2sd(result, value);
|
||||
} else {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_,
|
||||
ICData::kDeoptBinaryDoubleOp);
|
||||
Register temp = locs()->temp(0).reg();
|
||||
Label is_smi, done;
|
||||
__ testl(value, Immediate(kSmiTagMask));
|
||||
@@ -3337,7 +3342,7 @@ void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
if (value_cid != kFloat32x4Cid) {
|
||||
const Register temp = locs()->temp(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass);
|
||||
__ testl(value, Immediate(kSmiTagMask));
|
||||
__ j(ZERO, deopt);
|
||||
__ CompareClassId(value, kFloat32x4Cid, temp);
|
||||
@@ -3400,7 +3405,7 @@ void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
if (value_cid != kFloat64x2Cid) {
|
||||
const Register temp = locs()->temp(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass);
|
||||
__ testl(value, Immediate(kSmiTagMask));
|
||||
__ j(ZERO, deopt);
|
||||
__ CompareClassId(value, kFloat64x2Cid, temp);
|
||||
@@ -3495,7 +3500,7 @@ void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
if (value_cid != kInt32x4Cid) {
|
||||
const Register temp = locs()->temp(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass);
|
||||
__ testl(value, Immediate(kSmiTagMask));
|
||||
__ j(ZERO, deopt);
|
||||
__ CompareClassId(value, kInt32x4Cid, temp);
|
||||
@@ -4638,8 +4643,7 @@ void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(value == locs()->out(0).reg());
|
||||
switch (op_kind()) {
|
||||
case Token::kNEGATE: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptUnaryOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
|
||||
__ negl(value);
|
||||
__ j(OVERFLOW, deopt);
|
||||
break;
|
||||
@@ -4747,7 +4751,7 @@ LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi);
|
||||
Register result = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
__ cvttsd2si(result, value);
|
||||
@@ -5022,7 +5026,7 @@ extern const RuntimeEntry kSinCosRuntimeEntry(
|
||||
void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = NULL;
|
||||
if (CanDeoptimize()) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
||||
}
|
||||
|
||||
if (kind() == MergedMathInstr::kTruncDivMod) {
|
||||
@@ -5121,13 +5125,13 @@ LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
|
||||
|
||||
|
||||
void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptPolymorphicInstanceCallTestFail);
|
||||
Label* deopt = compiler->AddDeoptStub(
|
||||
deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
|
||||
if (ic_data().NumberOfChecks() == 0) {
|
||||
__ jmp(deopt);
|
||||
return;
|
||||
}
|
||||
ASSERT(ic_data().num_args_tested() == 1);
|
||||
ASSERT(ic_data().NumArgsTested() == 1);
|
||||
if (!with_checks()) {
|
||||
ASSERT(ic_data().HasOneTarget());
|
||||
const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
|
||||
@@ -5185,8 +5189,8 @@ LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const DeoptReasonId deopt_reason =
|
||||
licm_hoisted_ ? kDeoptHoistedCheckClass : kDeoptCheckClass;
|
||||
const ICData::DeoptReasonId deopt_reason = licm_hoisted_ ?
|
||||
ICData::kDeoptHoistedCheckClass : ICData::kDeoptCheckClass;
|
||||
if (IsNullCheck()) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
|
||||
const Immediate& raw_null =
|
||||
@@ -5243,8 +5247,7 @@ LocationSummary* CheckSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register value = locs()->in(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptCheckSmi);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi);
|
||||
__ testl(value, Immediate(kSmiTagMask));
|
||||
__ j(NOT_ZERO, deopt);
|
||||
}
|
||||
@@ -5269,7 +5272,8 @@ LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptCheckArrayBound);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptCheckArrayBound);
|
||||
|
||||
Location length_loc = locs()->in(kLengthPos);
|
||||
Location index_loc = locs()->in(kIndexPos);
|
||||
@@ -5352,7 +5356,8 @@ void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ pmovsxdq(result, result);
|
||||
} else {
|
||||
Register temp = locs()->temp(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptUnboxInteger);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_,
|
||||
ICData::kDeoptUnboxInteger);
|
||||
Label is_smi, done;
|
||||
__ testl(value, Immediate(kSmiTagMask));
|
||||
__ j(ZERO, &is_smi);
|
||||
@@ -5504,7 +5509,7 @@ void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
Label* deopt = NULL;
|
||||
if (FLAG_throw_on_javascript_int_overflow) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
|
||||
}
|
||||
switch (op_kind()) {
|
||||
case Token::kBIT_AND: __ andpd(left, right); break;
|
||||
@@ -5515,7 +5520,7 @@ void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register lo = locs()->temp(0).reg();
|
||||
Register hi = locs()->temp(1).reg();
|
||||
if (!FLAG_throw_on_javascript_int_overflow) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
|
||||
}
|
||||
|
||||
Label done, overflow;
|
||||
@@ -5570,8 +5575,7 @@ void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->in(1).reg() == ECX);
|
||||
ASSERT(locs()->out(0).fpu_reg() == left);
|
||||
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptShiftMintOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
|
||||
Label done;
|
||||
__ testl(ECX, ECX);
|
||||
__ j(ZERO, &done); // Shift by 0 is a nop.
|
||||
@@ -5644,8 +5648,7 @@ void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(value == locs()->out(0).fpu_reg());
|
||||
Label* deopt = NULL;
|
||||
if (FLAG_throw_on_javascript_int_overflow) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptUnaryMintOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
|
||||
}
|
||||
__ pcmpeqq(XMM0, XMM0); // Generate all 1's.
|
||||
__ pxor(value, XMM0);
|
||||
|
||||
@@ -675,7 +675,7 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
Register cid_reg = locs()->temp(0).reg();
|
||||
|
||||
Label* deopt = CanDeoptimize() ?
|
||||
compiler->AddDeoptStub(deopt_id(), kDeoptTestCids) : NULL;
|
||||
compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL;
|
||||
|
||||
const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
|
||||
const ZoneGrowableArray<intptr_t>& data = cid_results();
|
||||
@@ -1176,7 +1176,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ SmiTag(result);
|
||||
break;
|
||||
case kTypedDataInt32ArrayCid: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptInt32Load);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptInt32Load);
|
||||
__ lw(result, element_address);
|
||||
// Verify that the signed value in 'result' can fit inside a Smi.
|
||||
__ BranchSignedLess(result, 0xC0000000, deopt);
|
||||
@@ -1184,7 +1185,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
break;
|
||||
case kTypedDataUint32ArrayCid: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptUint32Load);
|
||||
__ lw(result, element_address);
|
||||
// Verify that the unsigned value in 'result' can fit inside a Smi.
|
||||
__ LoadImmediate(TMP, 0xC0000000);
|
||||
@@ -1473,7 +1475,7 @@ void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label ok, fail_label;
|
||||
|
||||
Label* deopt = compiler->is_optimizing() ?
|
||||
compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL;
|
||||
compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
|
||||
|
||||
Label* fail = (deopt != NULL) ? deopt : &fail_label;
|
||||
|
||||
@@ -2484,7 +2486,8 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
|
||||
Register left = locs.in(0).reg();
|
||||
Register result = locs.out(0).reg();
|
||||
Label* deopt = shift_left->CanDeoptimize() ?
|
||||
compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL;
|
||||
compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
|
||||
: NULL;
|
||||
|
||||
__ TraceSimMsg("EmitSmiShiftLeft");
|
||||
|
||||
@@ -2644,7 +2647,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register result = locs()->out(0).reg();
|
||||
Label* deopt = NULL;
|
||||
if (CanDeoptimize()) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
||||
}
|
||||
|
||||
if (locs()->in(1).IsConstant()) {
|
||||
@@ -2953,7 +2956,8 @@ LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptBinaryDoubleOp);
|
||||
intptr_t left_cid = left()->Type()->ToCid();
|
||||
intptr_t right_cid = right()->Type()->ToCid();
|
||||
Register left = locs()->in(0).reg();
|
||||
@@ -3027,7 +3031,8 @@ void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ mtc1(value, STMP1);
|
||||
__ cvtdw(result, STMP1);
|
||||
} else {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_,
|
||||
ICData::kDeoptBinaryDoubleOp);
|
||||
Label is_smi, done;
|
||||
|
||||
__ andi(CMPRES1, value, Immediate(kSmiTagMask));
|
||||
@@ -3613,8 +3618,7 @@ void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register result = locs()->out(0).reg();
|
||||
switch (op_kind()) {
|
||||
case Token::kNEGATE: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptUnaryOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
|
||||
__ SubuDetectOverflow(result, ZR, value, CMPRES1);
|
||||
__ bltz(CMPRES1, deopt);
|
||||
break;
|
||||
@@ -3732,7 +3736,7 @@ LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi);
|
||||
Register result = locs()->out(0).reg();
|
||||
DRegister value = locs()->in(0).fpu_reg();
|
||||
__ cvtwd(STMP1, value);
|
||||
@@ -3954,7 +3958,7 @@ LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
|
||||
void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = NULL;
|
||||
if (CanDeoptimize()) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
||||
}
|
||||
if (kind() == MergedMathInstr::kTruncDivMod) {
|
||||
Register left = locs()->in(0).reg();
|
||||
@@ -4018,14 +4022,14 @@ LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
|
||||
|
||||
|
||||
void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptPolymorphicInstanceCallTestFail);
|
||||
Label* deopt = compiler->AddDeoptStub(
|
||||
deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
|
||||
__ TraceSimMsg("PolymorphicInstanceCallInstr");
|
||||
if (ic_data().NumberOfChecks() == 0) {
|
||||
__ b(deopt);
|
||||
return;
|
||||
}
|
||||
ASSERT(ic_data().num_args_tested() == 1);
|
||||
ASSERT(ic_data().NumArgsTested() == 1);
|
||||
if (!with_checks()) {
|
||||
ASSERT(ic_data().HasOneTarget());
|
||||
const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
|
||||
@@ -4083,8 +4087,8 @@ LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const DeoptReasonId deopt_reason =
|
||||
licm_hoisted_ ? kDeoptHoistedCheckClass : kDeoptCheckClass;
|
||||
const ICData::DeoptReasonId deopt_reason = licm_hoisted_ ?
|
||||
ICData::kDeoptHoistedCheckClass : ICData::kDeoptCheckClass;
|
||||
if (IsNullCheck()) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
|
||||
__ BranchEqual(locs()->in(0).reg(),
|
||||
@@ -4136,8 +4140,7 @@ LocationSummary* CheckSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ TraceSimMsg("CheckSmiInstr");
|
||||
Register value = locs()->in(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptCheckSmi);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi);
|
||||
__ andi(CMPRES1, value, Immediate(kSmiTagMask));
|
||||
__ bne(CMPRES1, ZR, deopt);
|
||||
}
|
||||
@@ -4155,7 +4158,8 @@ LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptCheckArrayBound);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptCheckArrayBound);
|
||||
|
||||
Location length_loc = locs()->in(kLengthPos);
|
||||
Location index_loc = locs()->in(kIndexPos);
|
||||
|
||||
@@ -549,7 +549,7 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
|
||||
Register cid_reg = locs()->temp(0).reg();
|
||||
|
||||
Label* deopt = CanDeoptimize() ?
|
||||
compiler->AddDeoptStub(deopt_id(), kDeoptTestCids) : NULL;
|
||||
compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL;
|
||||
|
||||
const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
|
||||
const ZoneGrowableArray<intptr_t>& data = cid_results();
|
||||
@@ -1278,7 +1278,7 @@ void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label ok, fail_label;
|
||||
|
||||
Label* deopt = compiler->is_optimizing() ?
|
||||
compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL;
|
||||
compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL;
|
||||
|
||||
Label* fail = (deopt != NULL) ? deopt : &fail_label;
|
||||
|
||||
@@ -2484,7 +2484,8 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
|
||||
Register result = locs.out(0).reg();
|
||||
ASSERT(left == result);
|
||||
Label* deopt = shift_left->CanDeoptimize() ?
|
||||
compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL;
|
||||
compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
|
||||
: NULL;
|
||||
if (locs.in(1).IsConstant()) {
|
||||
const Object& constant = locs.in(1).constant();
|
||||
ASSERT(constant.IsSmi());
|
||||
@@ -2708,8 +2709,7 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(left == result);
|
||||
Label* deopt = NULL;
|
||||
if (CanDeoptimize()) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptBinarySmiOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
||||
}
|
||||
|
||||
if (locs()->in(1).IsConstant()) {
|
||||
@@ -3080,7 +3080,8 @@ LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptBinaryDoubleOp);
|
||||
intptr_t left_cid = left()->Type()->ToCid();
|
||||
intptr_t right_cid = right()->Type()->ToCid();
|
||||
Register left = locs()->in(0).reg();
|
||||
@@ -3154,7 +3155,8 @@ void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ SmiUntag(value); // Untag input before conversion.
|
||||
__ cvtsi2sd(result, value);
|
||||
} else {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_,
|
||||
ICData::kDeoptBinaryDoubleOp);
|
||||
Label is_smi, done;
|
||||
__ testq(value, Immediate(kSmiTagMask));
|
||||
__ j(ZERO, &is_smi);
|
||||
@@ -3214,7 +3216,7 @@ void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const XmmRegister result = locs()->out(0).fpu_reg();
|
||||
|
||||
if (value_cid != kFloat32x4Cid) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass);
|
||||
__ testq(value, Immediate(kSmiTagMask));
|
||||
__ j(ZERO, deopt);
|
||||
__ CompareClassId(value, kFloat32x4Cid);
|
||||
@@ -3272,7 +3274,7 @@ void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const XmmRegister result = locs()->out(0).fpu_reg();
|
||||
|
||||
if (value_cid != kFloat64x2Cid) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass);
|
||||
__ testq(value, Immediate(kSmiTagMask));
|
||||
__ j(ZERO, deopt);
|
||||
__ CompareClassId(value, kFloat64x2Cid);
|
||||
@@ -3361,7 +3363,7 @@ void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const XmmRegister result = locs()->out(0).fpu_reg();
|
||||
|
||||
if (value_cid != kInt32x4Cid) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id_, ICData::kDeoptCheckClass);
|
||||
__ testq(value, Immediate(kSmiTagMask));
|
||||
__ j(ZERO, deopt);
|
||||
__ CompareClassId(value, kInt32x4Cid);
|
||||
@@ -4433,8 +4435,7 @@ void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(value == locs()->out(0).reg());
|
||||
switch (op_kind()) {
|
||||
case Token::kNEGATE: {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptUnaryOp);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
|
||||
__ negq(value);
|
||||
__ j(OVERFLOW, deopt);
|
||||
if (FLAG_throw_on_javascript_int_overflow) {
|
||||
@@ -4643,7 +4644,7 @@ LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi);
|
||||
Register result = locs()->out(0).reg();
|
||||
XmmRegister value = locs()->in(0).fpu_reg();
|
||||
Register temp = locs()->temp(0).reg();
|
||||
@@ -4935,7 +4936,7 @@ extern const RuntimeEntry kSinCosRuntimeEntry(
|
||||
void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = NULL;
|
||||
if (CanDeoptimize()) {
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
||||
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
|
||||
}
|
||||
if (kind() == MergedMathInstr::kTruncDivMod) {
|
||||
Register left = locs()->in(0).reg();
|
||||
@@ -5072,13 +5073,13 @@ LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
|
||||
|
||||
|
||||
void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptPolymorphicInstanceCallTestFail);
|
||||
Label* deopt = compiler->AddDeoptStub(
|
||||
deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
|
||||
if (ic_data().NumberOfChecks() == 0) {
|
||||
__ jmp(deopt);
|
||||
return;
|
||||
}
|
||||
ASSERT(ic_data().num_args_tested() == 1);
|
||||
ASSERT(ic_data().NumArgsTested() == 1);
|
||||
if (!with_checks()) {
|
||||
ASSERT(ic_data().HasOneTarget());
|
||||
const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
|
||||
@@ -5134,8 +5135,8 @@ LocationSummary* CheckClassInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const DeoptReasonId deopt_reason =
|
||||
licm_hoisted_ ? kDeoptHoistedCheckClass : kDeoptCheckClass;
|
||||
const ICData::DeoptReasonId deopt_reason = licm_hoisted_ ?
|
||||
ICData::kDeoptHoistedCheckClass : ICData::kDeoptCheckClass;
|
||||
if (IsNullCheck()) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason);
|
||||
__ CompareObject(locs()->in(0).reg(),
|
||||
@@ -5191,8 +5192,7 @@ LocationSummary* CheckSmiInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register value = locs()->in(0).reg();
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
kDeoptCheckSmi);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi);
|
||||
__ testq(value, Immediate(kSmiTagMask));
|
||||
__ j(NOT_ZERO, deopt);
|
||||
}
|
||||
@@ -5210,7 +5210,8 @@ LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const {
|
||||
|
||||
|
||||
void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptCheckArrayBound);
|
||||
Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
||||
ICData::kDeoptCheckArrayBound);
|
||||
|
||||
Location length_loc = locs()->in(kLengthPos);
|
||||
Location index_loc = locs()->in(kIndexPos);
|
||||
|
||||
+526
-477
File diff suppressed because it is too large
Load Diff
+215
-158
@@ -3180,6 +3180,219 @@ class DeoptInfo : public Object {
|
||||
};
|
||||
|
||||
|
||||
// Object holding information about an IC: test classes and their
|
||||
// corresponding targets.
|
||||
class ICData : public Object {
|
||||
public:
|
||||
RawFunction* owner() const {
|
||||
return raw_ptr()->owner_;
|
||||
}
|
||||
|
||||
RawString* target_name() const {
|
||||
return raw_ptr()->target_name_;
|
||||
}
|
||||
|
||||
RawArray* arguments_descriptor() const {
|
||||
return raw_ptr()->args_descriptor_;
|
||||
}
|
||||
|
||||
intptr_t NumArgsTested() const;
|
||||
|
||||
intptr_t deopt_id() const {
|
||||
return raw_ptr()->deopt_id_;
|
||||
}
|
||||
|
||||
#define DEOPT_REASONS(V) \
|
||||
V(Unknown) \
|
||||
V(InstanceGetter) \
|
||||
V(PolymorphicInstanceCallTestFail) \
|
||||
V(InstanceCallNoICData) \
|
||||
V(IntegerToDouble) \
|
||||
V(BinarySmiOp) \
|
||||
V(BinaryMintOp) \
|
||||
V(UnaryMintOp) \
|
||||
V(ShiftMintOp) \
|
||||
V(BinaryDoubleOp) \
|
||||
V(InstanceSetter) \
|
||||
V(Equality) \
|
||||
V(RelationalOp) \
|
||||
V(EqualityClassCheck) \
|
||||
V(NoTypeFeedback) \
|
||||
V(UnaryOp) \
|
||||
V(UnboxInteger) \
|
||||
V(CheckClass) \
|
||||
V(HoistedCheckClass) \
|
||||
V(CheckSmi) \
|
||||
V(CheckArrayBound) \
|
||||
V(AtCall) \
|
||||
V(DoubleToSmi) \
|
||||
V(Int32Load) \
|
||||
V(Uint32Load) \
|
||||
V(GuardField) \
|
||||
V(TestCids) \
|
||||
V(NumReasons) \
|
||||
|
||||
enum DeoptReasonId {
|
||||
#define DEFINE_ENUM_LIST(name) kDeopt##name,
|
||||
DEOPT_REASONS(DEFINE_ENUM_LIST)
|
||||
#undef DEFINE_ENUM_LIST
|
||||
};
|
||||
|
||||
bool HasDeoptReasons() const { return DeoptReasons() != 0; }
|
||||
uint32_t DeoptReasons() const;
|
||||
void SetDeoptReasons(uint32_t reasons) const;
|
||||
|
||||
bool HasDeoptReason(ICData::DeoptReasonId reason) const;
|
||||
void AddDeoptReason(ICData::DeoptReasonId reason) const;
|
||||
|
||||
bool IssuedJSWarning() const;
|
||||
void SetIssuedJSWarning() const;
|
||||
|
||||
bool IsClosureCall() const;
|
||||
void SetIsClosureCall() const;
|
||||
|
||||
intptr_t NumberOfChecks() const;
|
||||
|
||||
static intptr_t InstanceSize() {
|
||||
return RoundedAllocationSize(sizeof(RawICData));
|
||||
}
|
||||
|
||||
static intptr_t target_name_offset() {
|
||||
return OFFSET_OF(RawICData, target_name_);
|
||||
}
|
||||
|
||||
static intptr_t state_bits_offset() {
|
||||
return OFFSET_OF(RawICData, state_bits_);
|
||||
}
|
||||
|
||||
static intptr_t NumArgsTestedShift() {
|
||||
return kNumArgsTestedPos;
|
||||
}
|
||||
|
||||
static intptr_t NumArgsTestedMask() {
|
||||
return ((1 << kNumArgsTestedSize) - 1) << kNumArgsTestedPos;
|
||||
}
|
||||
|
||||
static intptr_t arguments_descriptor_offset() {
|
||||
return OFFSET_OF(RawICData, args_descriptor_);
|
||||
}
|
||||
|
||||
static intptr_t ic_data_offset() {
|
||||
return OFFSET_OF(RawICData, ic_data_);
|
||||
}
|
||||
|
||||
static intptr_t owner_offset() {
|
||||
return OFFSET_OF(RawICData, owner_);
|
||||
}
|
||||
|
||||
// Used for unoptimized static calls when no class-ids are checked.
|
||||
void AddTarget(const Function& target) const;
|
||||
|
||||
// Adding checks.
|
||||
|
||||
// Adds one more class test to ICData. Length of 'classes' must be equal to
|
||||
// the number of arguments tested. Use only for num_args_tested > 1.
|
||||
void AddCheck(const GrowableArray<intptr_t>& class_ids,
|
||||
const Function& target) const;
|
||||
// Adds sorted so that Smi is the first class-id. Use only for
|
||||
// num_args_tested == 1.
|
||||
void AddReceiverCheck(intptr_t receiver_class_id,
|
||||
const Function& target,
|
||||
intptr_t count = 1) const;
|
||||
|
||||
// Retrieving checks.
|
||||
|
||||
void GetCheckAt(intptr_t index,
|
||||
GrowableArray<intptr_t>* class_ids,
|
||||
Function* target) const;
|
||||
// Only for 'num_args_checked == 1'.
|
||||
void GetOneClassCheckAt(intptr_t index,
|
||||
intptr_t* class_id,
|
||||
Function* target) const;
|
||||
// Only for 'num_args_checked == 1'.
|
||||
intptr_t GetCidAt(intptr_t index) const;
|
||||
|
||||
intptr_t GetReceiverClassIdAt(intptr_t index) const;
|
||||
intptr_t GetClassIdAt(intptr_t index, intptr_t arg_nr) const;
|
||||
|
||||
RawFunction* GetTargetAt(intptr_t index) const;
|
||||
RawFunction* GetTargetForReceiverClassId(intptr_t class_id) const;
|
||||
|
||||
void IncrementCountAt(intptr_t index, intptr_t value) const;
|
||||
void SetCountAt(intptr_t index, intptr_t value) const;
|
||||
intptr_t GetCountAt(intptr_t index) const;
|
||||
intptr_t AggregateCount() const;
|
||||
|
||||
// Returns this->raw() if num_args_tested == 1 and arg_nr == 1, otherwise
|
||||
// returns a new ICData object containing only unique arg_nr checks.
|
||||
RawICData* AsUnaryClassChecksForArgNr(intptr_t arg_nr) const;
|
||||
RawICData* AsUnaryClassChecks() const {
|
||||
return AsUnaryClassChecksForArgNr(0);
|
||||
}
|
||||
|
||||
bool AllTargetsHaveSameOwner(intptr_t owner_cid) const;
|
||||
bool AllReceiversAreNumbers() const;
|
||||
bool HasOneTarget() const;
|
||||
bool HasReceiverClassId(intptr_t class_id) const;
|
||||
|
||||
static RawICData* New(const Function& owner,
|
||||
const String& target_name,
|
||||
const Array& arguments_descriptor,
|
||||
intptr_t deopt_id,
|
||||
intptr_t num_args_tested);
|
||||
|
||||
static intptr_t TestEntryLengthFor(intptr_t num_args);
|
||||
|
||||
static intptr_t TargetIndexFor(intptr_t num_args) {
|
||||
return num_args;
|
||||
}
|
||||
|
||||
static intptr_t CountIndexFor(intptr_t num_args) {
|
||||
return (num_args + 1);
|
||||
}
|
||||
|
||||
private:
|
||||
RawArray* ic_data() const {
|
||||
return raw_ptr()->ic_data_;
|
||||
}
|
||||
|
||||
void set_owner(const Function& value) const;
|
||||
void set_target_name(const String& value) const;
|
||||
void set_arguments_descriptor(const Array& value) const;
|
||||
void set_deopt_id(intptr_t value) const;
|
||||
void SetNumArgsTested(intptr_t value) const;
|
||||
void set_ic_data(const Array& value) const;
|
||||
void set_state_bits(uint32_t bits) const;
|
||||
|
||||
enum {
|
||||
kNumArgsTestedPos = 0,
|
||||
kNumArgsTestedSize = 2,
|
||||
kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize,
|
||||
kDeoptReasonSize = kDeoptNumReasons,
|
||||
kIssuedJSWarningBit = kDeoptReasonPos + kDeoptReasonSize,
|
||||
kIsClosureCallBit = kIssuedJSWarningBit + 1,
|
||||
};
|
||||
|
||||
class NumArgsTestedBits : public BitField<uint32_t,
|
||||
kNumArgsTestedPos, kNumArgsTestedSize> {}; // NOLINT
|
||||
class DeoptReasonBits : public BitField<uint32_t,
|
||||
ICData::kDeoptReasonPos, ICData::kDeoptReasonSize> {}; // NOLINT
|
||||
class IssuedJSWarningBit : public BitField<bool, kIssuedJSWarningBit, 1> {};
|
||||
class IsClosureCallBit : public BitField<bool, kIsClosureCallBit, 1> {};
|
||||
|
||||
#if defined(DEBUG)
|
||||
// Used in asserts to verify that a check is not added twice.
|
||||
bool HasCheck(const GrowableArray<intptr_t>& cids) const;
|
||||
#endif // DEBUG
|
||||
|
||||
intptr_t TestEntryLength() const;
|
||||
void WriteSentinel(const Array& data) const;
|
||||
|
||||
FINAL_HEAP_OBJECT_IMPLEMENTATION(ICData, Object);
|
||||
friend class Class;
|
||||
};
|
||||
|
||||
|
||||
class Code : public Object {
|
||||
public:
|
||||
RawInstructions* instructions() const { return raw_ptr()->instructions_; }
|
||||
@@ -3257,7 +3470,8 @@ class Code : public Object {
|
||||
return raw_ptr()->static_calls_target_table_;
|
||||
}
|
||||
|
||||
RawDeoptInfo* GetDeoptInfoAtPc(uword pc, intptr_t* deopt_reason) const;
|
||||
RawDeoptInfo* GetDeoptInfoAtPc(
|
||||
uword pc, ICData::ICData::DeoptReasonId* deopt_reason) const;
|
||||
|
||||
// Returns null if there is no static call at 'pc'.
|
||||
RawFunction* GetStaticCallTargetFunctionAt(uword pc) const;
|
||||
@@ -3604,163 +3818,6 @@ class ContextScope : public Object {
|
||||
};
|
||||
|
||||
|
||||
// Object holding information about an IC: test classes and their
|
||||
// corresponding targets.
|
||||
class ICData : public Object {
|
||||
public:
|
||||
RawFunction* function() const {
|
||||
return raw_ptr()->function_;
|
||||
}
|
||||
|
||||
RawString* target_name() const {
|
||||
return raw_ptr()->target_name_;
|
||||
}
|
||||
|
||||
RawArray* arguments_descriptor() const {
|
||||
return raw_ptr()->args_descriptor_;
|
||||
}
|
||||
|
||||
intptr_t num_args_tested() const {
|
||||
return raw_ptr()->num_args_tested_;
|
||||
}
|
||||
|
||||
intptr_t deopt_id() const {
|
||||
return raw_ptr()->deopt_id_;
|
||||
}
|
||||
|
||||
intptr_t deopt_reason() const {
|
||||
return raw_ptr()->deopt_reason_;
|
||||
}
|
||||
|
||||
void set_deopt_reason(intptr_t reason) const;
|
||||
|
||||
bool is_closure_call() const {
|
||||
return raw_ptr()->is_closure_call_ == 1;
|
||||
}
|
||||
|
||||
void set_is_closure_call(bool value) const;
|
||||
|
||||
intptr_t NumberOfChecks() const;
|
||||
|
||||
static intptr_t InstanceSize() {
|
||||
return RoundedAllocationSize(sizeof(RawICData));
|
||||
}
|
||||
|
||||
static intptr_t target_name_offset() {
|
||||
return OFFSET_OF(RawICData, target_name_);
|
||||
}
|
||||
|
||||
static intptr_t num_args_tested_offset() {
|
||||
return OFFSET_OF(RawICData, num_args_tested_);
|
||||
}
|
||||
|
||||
static intptr_t arguments_descriptor_offset() {
|
||||
return OFFSET_OF(RawICData, args_descriptor_);
|
||||
}
|
||||
|
||||
static intptr_t ic_data_offset() {
|
||||
return OFFSET_OF(RawICData, ic_data_);
|
||||
}
|
||||
|
||||
static intptr_t function_offset() {
|
||||
return OFFSET_OF(RawICData, function_);
|
||||
}
|
||||
|
||||
static intptr_t is_closure_call_offset() {
|
||||
return OFFSET_OF(RawICData, is_closure_call_);
|
||||
}
|
||||
|
||||
// Used for unoptimized static calls when no class-ids are checked.
|
||||
void AddTarget(const Function& target) const;
|
||||
|
||||
// Adding checks.
|
||||
|
||||
// Adds one more class test to ICData. Length of 'classes' must be equal to
|
||||
// the number of arguments tested. Use only for num_args_tested > 1.
|
||||
void AddCheck(const GrowableArray<intptr_t>& class_ids,
|
||||
const Function& target) const;
|
||||
// Adds sorted so that Smi is the first class-id. Use only for
|
||||
// num_args_tested == 1.
|
||||
void AddReceiverCheck(intptr_t receiver_class_id,
|
||||
const Function& target,
|
||||
intptr_t count = 1) const;
|
||||
|
||||
// Retrieving checks.
|
||||
|
||||
void GetCheckAt(intptr_t index,
|
||||
GrowableArray<intptr_t>* class_ids,
|
||||
Function* target) const;
|
||||
// Only for 'num_args_checked == 1'.
|
||||
void GetOneClassCheckAt(intptr_t index,
|
||||
intptr_t* class_id,
|
||||
Function* target) const;
|
||||
// Only for 'num_args_checked == 1'.
|
||||
intptr_t GetCidAt(intptr_t index) const;
|
||||
|
||||
intptr_t GetReceiverClassIdAt(intptr_t index) const;
|
||||
intptr_t GetClassIdAt(intptr_t index, intptr_t arg_nr) const;
|
||||
|
||||
RawFunction* GetTargetAt(intptr_t index) const;
|
||||
RawFunction* GetTargetForReceiverClassId(intptr_t class_id) const;
|
||||
|
||||
void IncrementCountAt(intptr_t index, intptr_t value) const;
|
||||
void SetCountAt(intptr_t index, intptr_t value) const;
|
||||
intptr_t GetCountAt(intptr_t index) const;
|
||||
intptr_t AggregateCount() const;
|
||||
|
||||
// Returns this->raw() if num_args_tested == 1 and arg_nr == 1, otherwise
|
||||
// returns a new ICData object containing only unique arg_nr checks.
|
||||
RawICData* AsUnaryClassChecksForArgNr(intptr_t arg_nr) const;
|
||||
RawICData* AsUnaryClassChecks() const {
|
||||
return AsUnaryClassChecksForArgNr(0);
|
||||
}
|
||||
|
||||
bool AllTargetsHaveSameOwner(intptr_t owner_cid) const;
|
||||
bool AllReceiversAreNumbers() const;
|
||||
bool HasOneTarget() const;
|
||||
bool HasReceiverClassId(intptr_t class_id) const;
|
||||
|
||||
static RawICData* New(const Function& caller_function,
|
||||
const String& target_name,
|
||||
const Array& arguments_descriptor,
|
||||
intptr_t deopt_id,
|
||||
intptr_t num_args_tested);
|
||||
|
||||
static intptr_t TestEntryLengthFor(intptr_t num_args);
|
||||
|
||||
static intptr_t TargetIndexFor(intptr_t num_args) {
|
||||
return num_args;
|
||||
}
|
||||
|
||||
static intptr_t CountIndexFor(intptr_t num_args) {
|
||||
return (num_args + 1);
|
||||
}
|
||||
|
||||
private:
|
||||
RawArray* ic_data() const {
|
||||
return raw_ptr()->ic_data_;
|
||||
}
|
||||
|
||||
void set_function(const Function& value) const;
|
||||
void set_target_name(const String& value) const;
|
||||
void set_arguments_descriptor(const Array& value) const;
|
||||
void set_deopt_id(intptr_t value) const;
|
||||
void set_num_args_tested(intptr_t value) const;
|
||||
void set_ic_data(const Array& value) const;
|
||||
|
||||
#if defined(DEBUG)
|
||||
// Used in asserts to verify that a check is not added twice.
|
||||
bool HasCheck(const GrowableArray<intptr_t>& cids) const;
|
||||
#endif // DEBUG
|
||||
|
||||
intptr_t TestEntryLength() const;
|
||||
void WriteSentinel(const Array& data) const;
|
||||
|
||||
FINAL_HEAP_OBJECT_IMPLEMENTATION(ICData, Object);
|
||||
friend class Class;
|
||||
};
|
||||
|
||||
|
||||
class MegamorphicCache : public Object {
|
||||
public:
|
||||
static const int kInitialCapacity = 16;
|
||||
|
||||
@@ -2751,9 +2751,9 @@ TEST_CASE(ICData) {
|
||||
Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
|
||||
ICData& o1 = ICData::Handle();
|
||||
o1 = ICData::New(function, target_name, args_descriptor, id, num_args_tested);
|
||||
EXPECT_EQ(1, o1.num_args_tested());
|
||||
EXPECT_EQ(1, o1.NumArgsTested());
|
||||
EXPECT_EQ(id, o1.deopt_id());
|
||||
EXPECT_EQ(function.raw(), o1.function());
|
||||
EXPECT_EQ(function.raw(), o1.owner());
|
||||
EXPECT_EQ(0, o1.NumberOfChecks());
|
||||
EXPECT_EQ(target_name.raw(), o1.target_name());
|
||||
EXPECT_EQ(args_descriptor.raw(), o1.arguments_descriptor());
|
||||
@@ -2783,9 +2783,9 @@ TEST_CASE(ICData) {
|
||||
|
||||
ICData& o2 = ICData::Handle();
|
||||
o2 = ICData::New(function, target_name, args_descriptor, 57, 2);
|
||||
EXPECT_EQ(2, o2.num_args_tested());
|
||||
EXPECT_EQ(2, o2.NumArgsTested());
|
||||
EXPECT_EQ(57, o2.deopt_id());
|
||||
EXPECT_EQ(function.raw(), o2.function());
|
||||
EXPECT_EQ(function.raw(), o2.owner());
|
||||
EXPECT_EQ(0, o2.NumberOfChecks());
|
||||
GrowableArray<intptr_t> classes;
|
||||
classes.Add(kSmiCid);
|
||||
|
||||
@@ -1021,19 +1021,18 @@ class RawICData : public RawObject {
|
||||
RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
|
||||
|
||||
RawObject** from() {
|
||||
return reinterpret_cast<RawObject**>(&ptr()->function_);
|
||||
return reinterpret_cast<RawObject**>(&ptr()->owner_);
|
||||
}
|
||||
RawFunction* function_; // Parent/calling function of this IC.
|
||||
RawFunction* owner_; // Parent/calling function of this IC.
|
||||
RawString* target_name_; // Name of target function.
|
||||
RawArray* args_descriptor_; // Arguments descriptor.
|
||||
RawArray* ic_data_; // Contains class-ids, target and count.
|
||||
RawObject** to() {
|
||||
return reinterpret_cast<RawObject**>(&ptr()->ic_data_);
|
||||
}
|
||||
intptr_t deopt_id_; // Deoptimization id corresponding to this IC.
|
||||
intptr_t num_args_tested_; // Number of arguments tested in IC.
|
||||
uint8_t deopt_reason_; // Last deoptimization reason.
|
||||
uint8_t is_closure_call_; // 0 or 1.
|
||||
int32_t deopt_id_; // Deoptimization id corresponding to this IC.
|
||||
uint32_t state_bits_; // Number of arguments tested in IC, deopt reasons,
|
||||
// is closure call, JS warning issued.
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -397,7 +397,7 @@ InlinedFunctionsIterator::InlinedFunctionsIterator(const Code& code, uword pc)
|
||||
ASSERT(code_.is_optimized());
|
||||
ASSERT(pc_ != 0);
|
||||
ASSERT(code.ContainsInstructionAt(pc));
|
||||
intptr_t deopt_reason = kDeoptUnknown;
|
||||
ICData::DeoptReasonId deopt_reason = ICData::kDeoptUnknown;
|
||||
deopt_info_ = code_.GetDeoptInfoAtPc(pc, &deopt_reason);
|
||||
if (deopt_info_.IsNull()) {
|
||||
// This is the case when a call without deopt info in optimized code
|
||||
|
||||
@@ -1224,7 +1224,7 @@ void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
|
||||
Register ic_reg = R5;
|
||||
Register func_reg = temp_reg;
|
||||
ASSERT(temp_reg == R6);
|
||||
__ ldr(func_reg, FieldAddress(ic_reg, ICData::function_offset()));
|
||||
__ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
|
||||
__ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
|
||||
__ add(R7, R7, ShifterOperand(1));
|
||||
__ str(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
|
||||
@@ -1248,9 +1248,11 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
ASSERT(num_args > 0);
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == num_args.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ ldr(R6, FieldAddress(R5, ICData::num_args_tested_offset()));
|
||||
// Check that the IC data array has NumArgsTested() == num_args.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ ldr(R6, FieldAddress(R5, ICData::state_bits_offset()));
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ and_(R6, R6, ShifterOperand(ICData::NumArgsTestedMask()));
|
||||
__ CompareImmediate(R6, num_args);
|
||||
__ b(&ok, EQ);
|
||||
__ Stop("Incorrect stub for IC data");
|
||||
@@ -1467,9 +1469,11 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, R6);
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == 0.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ ldr(R6, FieldAddress(R5, ICData::num_args_tested_offset()));
|
||||
// Check that the IC data array has NumArgsTested() == 0.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ ldr(R6, FieldAddress(R5, ICData::state_bits_offset()));
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ and_(R6, R6, ShifterOperand(ICData::NumArgsTestedMask()));
|
||||
__ CompareImmediate(R6, 0);
|
||||
__ b(&ok, EQ);
|
||||
__ Stop("Incorrect IC data for unoptimized static call");
|
||||
|
||||
@@ -745,7 +745,7 @@ void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
|
||||
Register ic_reg = R5;
|
||||
Register func_reg = temp_reg;
|
||||
ASSERT(temp_reg == R6);
|
||||
__ LoadFieldFromOffset(func_reg, ic_reg, ICData::function_offset());
|
||||
__ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset());
|
||||
__ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset());
|
||||
__ AddImmediate(R7, R7, 1, PP);
|
||||
__ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset());
|
||||
@@ -769,9 +769,12 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
ASSERT(num_args > 0);
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == num_args.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ LoadFieldFromOffset(R6, R5, ICData::num_args_tested_offset());
|
||||
// Check that the IC data array has NumArgsTested() == num_args.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
|
||||
kUnsignedWord);
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ andi(R6, R6, ICData::NumArgsTestedMask());
|
||||
__ CompareImmediate(R6, num_args, PP);
|
||||
__ b(&ok, EQ);
|
||||
__ Stop("Incorrect stub for IC data");
|
||||
@@ -1010,9 +1013,12 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, R6);
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == 0.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ LoadFieldFromOffset(R6, R5, ICData::num_args_tested_offset());
|
||||
// Check that the IC data array has NumArgsTested() == 0.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
|
||||
kUnsignedWord);
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ andi(R6, R6, ICData::NumArgsTestedMask());
|
||||
__ CompareImmediate(R6, 0, PP);
|
||||
__ b(&ok, EQ);
|
||||
__ Stop("Incorrect IC data for unoptimized static call");
|
||||
|
||||
@@ -1273,7 +1273,7 @@ void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
|
||||
Register ic_reg = ECX;
|
||||
Register func_reg = temp_reg;
|
||||
ASSERT(ic_reg != func_reg);
|
||||
__ movl(func_reg, FieldAddress(ic_reg, ICData::function_offset()));
|
||||
__ movl(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
|
||||
__ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
|
||||
}
|
||||
|
||||
@@ -1295,9 +1295,11 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
ASSERT(num_args > 0);
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == num_args.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset()));
|
||||
// Check that the IC data array has NumArgsTested() == num_args.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset()));
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ andl(EBX, Immediate(ICData::NumArgsTestedMask()));
|
||||
__ cmpl(EBX, Immediate(num_args));
|
||||
__ j(EQUAL, &ok, Assembler::kNearJump);
|
||||
__ Stop("Incorrect stub for IC data");
|
||||
@@ -1526,9 +1528,11 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == num_args.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset()));
|
||||
// Check that the IC data array has NumArgsTested() == num_args.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset()));
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ andl(EBX, Immediate(ICData::NumArgsTestedMask()));
|
||||
__ cmpl(EBX, Immediate(0));
|
||||
__ j(EQUAL, &ok, Assembler::kNearJump);
|
||||
__ Stop("Incorrect IC data for unoptimized static call");
|
||||
|
||||
@@ -1391,7 +1391,7 @@ void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
|
||||
Register ic_reg = S5;
|
||||
Register func_reg = temp_reg;
|
||||
ASSERT(temp_reg == T0);
|
||||
__ lw(func_reg, FieldAddress(ic_reg, ICData::function_offset()));
|
||||
__ lw(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
|
||||
__ lw(T1, FieldAddress(func_reg, Function::usage_counter_offset()));
|
||||
__ addiu(T1, T1, Immediate(1));
|
||||
__ sw(T1, FieldAddress(func_reg, Function::usage_counter_offset()));
|
||||
@@ -1416,9 +1416,11 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
ASSERT(num_args > 0);
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == num_args.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ lw(T0, FieldAddress(S5, ICData::num_args_tested_offset()));
|
||||
// Check that the IC data array has NumArgsTested() == num_args.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ lw(T0, FieldAddress(S5, ICData::state_bits_offset()));
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ andi(T0, T0, Immediate(ICData::NumArgsTestedMask()));
|
||||
__ BranchEqual(T0, num_args, &ok);
|
||||
__ Stop("Incorrect stub for IC data");
|
||||
__ Bind(&ok);
|
||||
@@ -1668,9 +1670,11 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
__ TraceSimMsg("UnoptimizedStaticCallStub");
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == 0.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ lw(T0, FieldAddress(S5, ICData::num_args_tested_offset()));
|
||||
// Check that the IC data array has NumArgsTested() == 0.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ lw(T0, FieldAddress(S5, ICData::state_bits_offset()));
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ andi(T0, T0, Immediate(ICData::NumArgsTestedMask()));
|
||||
__ beq(T0, ZR, &ok);
|
||||
__ Stop("Incorrect IC data for unoptimized static call");
|
||||
__ Bind(&ok);
|
||||
|
||||
@@ -1213,7 +1213,7 @@ void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
|
||||
Register ic_reg = RBX;
|
||||
Register func_reg = temp_reg;
|
||||
ASSERT(ic_reg != func_reg);
|
||||
__ movq(func_reg, FieldAddress(ic_reg, ICData::function_offset()));
|
||||
__ movq(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
|
||||
__ incq(FieldAddress(func_reg, Function::usage_counter_offset()));
|
||||
}
|
||||
|
||||
@@ -1235,9 +1235,11 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
||||
ASSERT(num_args > 0);
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == num_args.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset()));
|
||||
// Check that the IC data array has NumArgsTested() == num_args.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset()));
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ andq(RCX, Immediate(ICData::NumArgsTestedMask()));
|
||||
__ cmpq(RCX, Immediate(num_args));
|
||||
__ j(EQUAL, &ok, Assembler::kNearJump);
|
||||
__ Stop("Incorrect stub for IC data");
|
||||
@@ -1460,9 +1462,11 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, RCX);
|
||||
#if defined(DEBUG)
|
||||
{ Label ok;
|
||||
// Check that the IC data array has NumberOfArgumentsChecked() == 0.
|
||||
// 'num_args_tested' is stored as an untagged int.
|
||||
__ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset()));
|
||||
// Check that the IC data array has NumArgsTested() == 0.
|
||||
// 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
|
||||
__ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset()));
|
||||
ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
|
||||
__ andq(RCX, Immediate(ICData::NumArgsTestedMask()));
|
||||
__ cmpq(RCX, Immediate(0));
|
||||
__ j(EQUAL, &ok, Assembler::kNearJump);
|
||||
__ Stop("Incorrect IC data for unoptimized static call");
|
||||
|
||||
Reference in New Issue
Block a user