Skip to content

Commit 5f509dc

Browse files
Removing more IC calls in optimized code.
Review URL: https://chromiumcodereview.appspot.com//10572050 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8950 260f80e4-7a28-3924-810f-c04153c831b5
1 parent 8a3a9f4 commit 5f509dc

7 files changed

+254
-49
lines changed

runtime/vm/code_generator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ DECLARE_RUNTIME_ENTRY(TraceFunctionExit);
6161
V(DeoptInstanceGetterSameTarget) \
6262
V(DeoptInstanceGetter) \
6363
V(DeoptStoreIndexed) \
64+
V(DeoptStoreIndexedPolymorphic) \
6465
V(DeoptPolymorphicInstanceCallSmiOnly) \
6566
V(DeoptPolymorphicInstanceCallSmiFail) \
6667
V(DeoptPolymorphicInstanceCallTestFail) \
@@ -80,6 +81,7 @@ DECLARE_RUNTIME_ENTRY(TraceFunctionExit);
8081
V(DeoptDoubleComparison) \
8182
V(DeoptLoadIndexedFixedArray) \
8283
V(DeoptLoadIndexedGrowableArray) \
84+
V(DeoptLoadIndexedPolymorphic) \
8385
V(DeoptNoTypeFeedback) \
8486
V(DeoptSAR) \
8587
V(DeoptUnaryOp) \

runtime/vm/flow_graph_compiler.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,37 @@ void FlowGraphCompiler::EmitLoadIndexedGeneric(LoadIndexedComp* comp) {
404404
}
405405

406406

407+
void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
408+
Register class_id_reg,
409+
intptr_t arg_count,
410+
const Array& arg_names,
411+
Label* deopt,
412+
Label* done,
413+
intptr_t cid,
414+
intptr_t token_index,
415+
intptr_t try_index) {
416+
// TODO(srdjan): better loop please!
417+
for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
418+
Label next_test;
419+
assembler()->cmpl(class_id_reg, Immediate(ic_data.GetReceiverClassIdAt(i)));
420+
assembler()->j(NOT_EQUAL, &next_test);
421+
const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
422+
GenerateStaticCall(cid,
423+
token_index,
424+
try_index,
425+
target,
426+
arg_count,
427+
arg_names);
428+
assembler()->jmp(done);
429+
assembler()->Bind(&next_test);
430+
}
431+
assembler()->jmp(deopt);
432+
}
433+
434+
435+
436+
437+
407438
Register FrameRegisterAllocator::AllocateFreeRegister(bool* blocked_registers) {
408439
for (intptr_t regno = 0; regno < kNumberOfCpuRegisters; regno++) {
409440
if (!blocked_registers[regno] && (registers_[regno] == NULL)) {

runtime/vm/flow_graph_compiler_ia32.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,15 @@ class FlowGraphCompiler : public ValueObject {
143143
Register instance_reg,
144144
Register temp_reg,
145145
Label* deopt);
146+
void EmitTestAndCall(const ICData& ic_data,
147+
Register class_id_reg,
148+
intptr_t arg_count,
149+
const Array& arg_names,
150+
Label* deopt,
151+
Label* done,
152+
intptr_t cid,
153+
intptr_t token_index,
154+
intptr_t try_index);
146155

147156
intptr_t StackSize() const;
148157

runtime/vm/flow_graph_compiler_x64.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@ class FlowGraphCompiler : public ValueObject {
134134
intptr_t argument_count);
135135

136136
void EmitLoadIndexedGeneric(LoadIndexedComp* comp);
137+
void EmitTestAndCall(const ICData& ic_data,
138+
Register class_id_reg,
139+
intptr_t arg_count,
140+
const Array& arg_names,
141+
Label* deopt,
142+
Label* done,
143+
intptr_t cid,
144+
intptr_t token_index,
145+
intptr_t try_index);
137146

138147
intptr_t StackSize() const;
139148

runtime/vm/flow_graph_optimizer.cc

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -371,13 +371,18 @@ void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) {
371371
return;
372372
}
373373
const intptr_t kMaxChecks = 4;
374-
if (comp->ic_data()->num_args_tested() <= kMaxChecks) {
374+
if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) {
375375
PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp);
376376
ICData& unary_checks =
377-
ICData::Handle(ToUnaryClassChecks(*comp->ic_data()));
377+
ICData::ZoneHandle(ToUnaryClassChecks(*comp->ic_data()));
378378
call->set_ic_data(&unary_checks);
379379
comp->ReplaceWith(call);
380380
}
381+
} else {
382+
// Mark it for deopt.
383+
PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp);
384+
call->set_ic_data(&ICData::ZoneHandle());
385+
comp->ReplaceWith(call);
381386
}
382387
}
383388

@@ -399,7 +404,7 @@ bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) {
399404
return false;
400405
}
401406
if (!HasOneTarget(ic_data)) {
402-
// TODO(srdjan): Implement when not all targets are the sa,e.
407+
// TODO(srdjan): Implement when not all targets are the same.
403408
return false;
404409
}
405410
Function& target = Function::Handle();
@@ -426,10 +431,13 @@ bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) {
426431

427432

428433
void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) {
429-
// TODO(srdjan): Add assigneable check node if --enable_type_checks.
434+
// TODO(srdjan): Add assignable check node if --enable_type_checks.
430435
if (comp->HasICData() && !FLAG_enable_type_checks) {
431-
TryInlineInstanceSetter(comp);
436+
if (TryInlineInstanceSetter(comp)) {
437+
return;
438+
}
432439
}
440+
// TODO(srdjan): Polymorphic dispatch to setters or deoptimize.
433441
}
434442

435443

@@ -542,9 +550,8 @@ void FlowGraphOptimizer::VisitStrictCompareComp(StrictCompareComp* comp) {
542550

543551

544552
void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp) {
545-
const intptr_t kMaxChecks = 4;
546-
if (comp->HasICData() && (comp->ic_data()->num_args_tested() <= kMaxChecks)) {
547-
// Replace binary checks with unary ones.
553+
if (comp->HasICData()) {
554+
// Replace binary checks with unary ones since EmitNative expects it.
548555
ICData& unary_checks =
549556
ICData::Handle(ToUnaryClassChecks(*comp->ic_data()));
550557
comp->set_ic_data(&unary_checks);

runtime/vm/intermediate_language_ia32.cc

Lines changed: 93 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
306306
ASSERT(comp->HasICData());
307307
const ICData& ic_data = *comp->ic_data();
308308
ASSERT(ic_data.NumberOfChecks() > 0);
309+
ASSERT(ic_data.num_args_tested() == 1);
309310
Label* deopt = compiler->AddDeoptStub(comp->cid(),
310311
comp->token_index(),
311312
comp->try_index(),
@@ -637,10 +638,47 @@ LocationSummary* LoadIndexedComp::MakeLocationSummary() const {
637638
}
638639

639640

641+
static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler,
642+
LoadIndexedComp* comp) {
643+
Label* deopt = compiler->AddDeoptStub(comp->cid(),
644+
comp->token_index(),
645+
comp->try_index(),
646+
kDeoptLoadIndexedPolymorphic);
647+
if (comp->ic_data()->NumberOfChecks() == 0) {
648+
__ jmp(deopt);
649+
return;
650+
}
651+
ASSERT(comp->HasICData());
652+
const ICData& ic_data = *comp->ic_data();
653+
ASSERT(ic_data.num_args_tested() == 1);
654+
// No indexed access on Smi.
655+
ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi);
656+
// Load receiver into EAX.
657+
const intptr_t kNumArguments = 2;
658+
__ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize));
659+
__ testl(EAX, Immediate(kSmiTagMask));
660+
__ j(ZERO, deopt);
661+
Label done;
662+
__ LoadClassId(EDI, EAX);
663+
compiler->EmitTestAndCall(ic_data,
664+
EDI, // Class id register.
665+
kNumArguments,
666+
Array::Handle(), // No named arguments.
667+
deopt, &done, // Labels.
668+
comp->cid(),
669+
comp->token_index(),
670+
comp->try_index());
671+
__ Bind(&done);
672+
}
673+
640674

641675
void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) {
642676
if (receiver_type() == kIllegalObjectKind) {
643-
compiler->EmitLoadIndexedGeneric(this);
677+
if (HasICData()) {
678+
EmitLoadIndexedPolymorphic(compiler, this);
679+
} else {
680+
compiler->EmitLoadIndexedGeneric(this);
681+
}
644682
ASSERT(locs()->out().reg() == EAX);
645683
return;
646684
}
@@ -719,7 +757,6 @@ LocationSummary* StoreIndexedComp::MakeLocationSummary() const {
719757
}
720758

721759

722-
723760
static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler,
724761
StoreIndexedComp* comp) {
725762
const String& function_name =
@@ -737,14 +774,52 @@ static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler,
737774
comp->try_index(),
738775
function_name,
739776
kNumArguments,
740-
Array::ZoneHandle(), // No optional arguments.
777+
Array::ZoneHandle(), // No named args.
741778
kNumArgsChecked);
742779
}
743780

744781

782+
static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler,
783+
StoreIndexedComp* comp) {
784+
Label* deopt = compiler->AddDeoptStub(comp->cid(),
785+
comp->token_index(),
786+
comp->try_index(),
787+
kDeoptStoreIndexedPolymorphic);
788+
if (comp->ic_data()->NumberOfChecks() == 0) {
789+
__ jmp(deopt);
790+
return;
791+
}
792+
ASSERT(comp->HasICData());
793+
const ICData& ic_data = *comp->ic_data();
794+
ASSERT(ic_data.num_args_tested() == 1);
795+
// No indexed access on Smi.
796+
ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi);
797+
// Load receiver into EAX.
798+
const intptr_t kNumArguments = 3;
799+
__ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize));
800+
__ testl(EAX, Immediate(kSmiTagMask));
801+
__ j(ZERO, deopt);
802+
Label done;
803+
__ LoadClassId(EDI, EAX);
804+
compiler->EmitTestAndCall(ic_data,
805+
EDI, // Class id register.
806+
kNumArguments,
807+
Array::Handle(), // No named arguments.
808+
deopt, &done, // Labels.
809+
comp->cid(),
810+
comp->token_index(),
811+
comp->try_index());
812+
__ Bind(&done);
813+
}
814+
815+
745816
void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) {
746817
if (receiver_type() == kIllegalObjectKind) {
747-
EmitStoreIndexedGeneric(compiler, this);
818+
if (HasICData()) {
819+
EmitStoreIndexedPolymorphic(compiler, this);
820+
} else {
821+
EmitStoreIndexedGeneric(compiler, this);
822+
}
748823
return;
749824
}
750825

@@ -1760,12 +1835,16 @@ LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const {
17601835

17611836
void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
17621837
ASSERT(instance_call()->VerifyComputation());
1763-
ASSERT(HasICData());
1764-
ASSERT(ic_data()->num_args_tested() == 1);
17651838
Label* deopt = compiler->AddDeoptStub(instance_call()->cid(),
17661839
instance_call()->token_index(),
17671840
instance_call()->try_index(),
17681841
kDeoptPolymorphicInstanceCallTestFail);
1842+
if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) {
1843+
__ jmp(deopt);
1844+
return;
1845+
}
1846+
ASSERT(HasICData());
1847+
ASSERT(ic_data()->num_args_tested() == 1);
17691848
Label handle_smi;
17701849
Label* is_smi_label =
17711850
ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt;
@@ -1777,21 +1856,14 @@ void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
17771856
__ j(ZERO, is_smi_label);
17781857
Label done;
17791858
__ LoadClassId(EDI, EAX);
1780-
for (intptr_t i = 0; i < ic_data()->NumberOfChecks(); i++) {
1781-
Label next_test;
1782-
__ cmpl(EDI, Immediate(ic_data()->GetReceiverClassIdAt(i)));
1783-
__ j(NOT_EQUAL, &next_test);
1784-
const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(i));
1785-
compiler->GenerateStaticCall(instance_call()->cid(),
1786-
instance_call()->token_index(),
1787-
instance_call()->try_index(),
1788-
target,
1789-
instance_call()->ArgumentCount(),
1790-
instance_call()->argument_names());
1791-
__ jmp(&done);
1792-
__ Bind(&next_test);
1793-
}
1794-
__ jmp(deopt);
1859+
compiler->EmitTestAndCall(*ic_data(),
1860+
EDI, // Class id register.
1861+
instance_call()->ArgumentCount(),
1862+
instance_call()->argument_names(),
1863+
deopt, &done, // Labels.
1864+
instance_call()->cid(),
1865+
instance_call()->token_index(),
1866+
instance_call()->try_index());
17951867
if (is_smi_label == &handle_smi) {
17961868
__ Bind(&handle_smi);
17971869
ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi);

0 commit comments

Comments
 (0)