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:
regis@google.com
2014-04-25 23:45:14 +00:00
parent 2cc32fd9fc
commit e0ab99b0b2
37 changed files with 1020 additions and 914 deletions
+6 -5
View File
@@ -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 {
+10 -10
View File
@@ -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());
+1 -39
View File
@@ -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();
+1 -1
View File
@@ -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());
}
+1 -1
View File
@@ -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());
}
+2 -2
View File
@@ -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
}
+1 -1
View File
@@ -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());
}
+1 -1
View File
@@ -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());
}
+2 -2
View File
@@ -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
}
+1 -1
View File
@@ -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());
}
+4 -1
View File
@@ -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");
}
+8 -7
View File
@@ -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);
}
+2 -2
View File
@@ -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_;
+6 -6
View File
@@ -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();
+6 -6
View File
@@ -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);
+3 -3
View File
@@ -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();
+2 -2
View File
@@ -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();
+3 -3
View File
@@ -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();
+3 -3
View File
@@ -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();
+3 -3
View File
@@ -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();
+2 -2
View File
@@ -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(),
+30 -30
View File
@@ -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.
+1 -1
View File
@@ -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.
+33 -29
View File
@@ -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) {
+33 -30
View File
@@ -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);
+24 -20
View File
@@ -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);
+23 -22
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+215 -158
View File
@@ -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;
+4 -4
View File
@@ -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);
+5 -6
View File
@@ -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.
};
+1 -1
View File
@@ -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
+11 -7
View File
@@ -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");
+13 -7
View File
@@ -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");
+11 -7
View File
@@ -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");
+11 -7
View File
@@ -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);
+11 -7
View File
@@ -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");