Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Unified Diff: runtime/vm/intermediate_language_ia32.cc

Issue 10545186: Improve equality operation (inline, direct calls). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/intermediate_language_ia32.cc
===================================================================
--- runtime/vm/intermediate_language_ia32.cc (revision 8678)
+++ runtime/vm/intermediate_language_ia32.cc (working copy)
@@ -190,7 +190,7 @@
LocationSummary* EqualityCompareComp::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
- if (operands_class_id() == kSmi) {
+ if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) {
const intptr_t kNumTemps = 1;
LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
locs->set_in(0, Location::RequiresRegister());
@@ -201,18 +201,25 @@
}
return locs;
}
- if (operands_class_id() == kObject) {
- const intptr_t kNumTemps = 0;
+ if (NumTargets() > 0) {
+ const intptr_t kNumTemps = 1;
LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
locs->set_in(0, Location::RequiresRegister());
locs->set_in(1, Location::RequiresRegister());
+ locs->set_temp(0, Location::RequiresRegister());
if (!is_fused_with_branch()) {
locs->set_out(Location::RegisterLocation(EAX));
}
return locs;
}
- UNREACHABLE();
- return NULL;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
+ locs->set_in(0, Location::RequiresRegister());
+ locs->set_in(1, Location::RequiresRegister());
+ if (!is_fused_with_branch()) {
+ locs->set_out(Location::RegisterLocation(EAX));
+ }
+ return locs;
}
@@ -248,6 +255,108 @@
}
+static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
+ EqualityCompareComp* comp) {
+ compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
+ comp->cid(),
+ comp->token_index(),
+ comp->try_index());
+ const String& operator_name = String::ZoneHandle(String::NewSymbol("=="));
+ const int kNumberOfArguments = 2;
+ const Array& kNoArgumentNames = Array::Handle();
+ const int kNumArgumentsChecked = 2;
+
+ compiler->GenerateInstanceCall(comp->cid(),
+ comp->token_index(),
+ comp->try_index(),
+ operator_name,
+ kNumberOfArguments,
+ kNoArgumentNames,
+ kNumArgumentsChecked);
+ ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == EAX));
+
+ if (comp->is_fused_with_branch()) {
+ __ CompareObject(EAX, compiler->bool_true());
+ comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
+ }
+}
+
+
+static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
+ EqualityCompareComp* comp,
+ Register left,
+ Register right) {
+ ASSERT(comp->NumTargets() > 0);
+ Label* deopt = compiler->AddDeoptStub(comp->cid(),
+ comp->token_index(),
+ comp->try_index(),
+ kDeoptEquality);
+ __ testl(left, Immediate(kSmiTagMask));
+ Register temp = comp->locs()->temp(0).reg();
+ if (comp->ClassIdAt(0) == kSmi) {
+ Label done, load_class_id;
+ __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump);
+ __ movl(temp, Immediate(kSmi));
+ __ jmp(&done, Assembler::kNearJump);
+ __ Bind(&load_class_id);
+ __ LoadClassId(temp, left);
+ __ Bind(&done);
+ } else {
+ __ j(ZERO, deopt); // Smi deopts.
+ __ LoadClassId(temp, left);
+ }
+ Label done;
+ for (intptr_t i = 0; i < comp->NumTargets(); i++) {
+ ASSERT(comp->ClassIdAt(i) != kSmi || i == 0);
regis 2012/06/14 23:59:41 Add parenthesis.
srdjan 2012/06/15 00:27:19 Done.
+ Label next_test;
+ __ cmpl(temp, Immediate(comp->ClassIdAt(i)));
+ __ j(NOT_EQUAL, &next_test, Assembler::kNearJump);
+ const Function& target = *comp->TargetAt(i);
+ ObjectStore* object_store = Isolate::Current()->object_store();
+ if (target.owner() == object_store->object_class()) {
+ // Object.== is same as ===.
+ __ Drop(2);
+ __ cmpl(left, right);
+ if (comp->is_fused_with_branch()) {
+ comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
+ } else {
+ // This case should be rare.
+ Register result = comp->locs()->out().reg();
+ Label load_true;
+ __ j(EQUAL, &load_true, Assembler::kNearJump);
+ __ LoadObject(result, compiler->bool_false());
+ __ jmp(&done);
+ __ Bind(&load_true);
+ __ LoadObject(result, compiler->bool_true());
+ }
+ } else {
+ const int kNumberOfArguments = 2;
+ const Array& kNoArgumentNames = Array::Handle();
+ compiler->GenerateStaticCall(comp->cid(),
+ comp->token_index(),
+ comp->try_index(),
+ target,
+ kNumberOfArguments,
+ kNoArgumentNames);
+ ASSERT(comp->is_fused_with_branch() ||
+ (comp->locs()->out().reg() == EAX));
+ if (comp->is_fused_with_branch()) {
+ __ CompareObject(EAX, compiler->bool_true());
+ comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
+ }
+ }
+ __ jmp(&done);
+ __ Bind(&next_test);
+ }
+ // Fall through leads to deoptimization
+ __ jmp(deopt);
+ __ Bind(&done);
+}
+
+
+// First test if receiver is NULL, in which case === is applied.
+// If type feedback was provided (lists of <class-id, target>), do a
+// type by type check (either === or static call to the operator.
static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
EqualityCompareComp* comp) {
Register left = comp->locs()->in(0).reg();
@@ -266,51 +375,30 @@
Label load_true;
__ j(EQUAL, &load_true, Assembler::kNearJump);
__ LoadObject(result, compiler->bool_false());
- __ jmp(&done, Assembler::kNearJump);
+ __ jmp(&done);
__ Bind(&load_true);
__ LoadObject(result, compiler->bool_true());
}
__ jmp(&done);
- __ Bind(&non_null_compare);
+ __ Bind(&non_null_compare); // Receiver is not null.
__ pushl(left);
__ pushl(right);
- compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
- comp->cid(),
- comp->token_index(),
- comp->try_index());
- const String& operator_name = String::ZoneHandle(String::NewSymbol("=="));
- const int kNumberOfArguments = 2;
- const Array& kNoArgumentNames = Array::Handle();
- const int kNumArgumentsChecked = 2;
-
- compiler->GenerateInstanceCall(comp->cid(),
- comp->token_index(),
- comp->try_index(),
- operator_name,
- kNumberOfArguments,
- kNoArgumentNames,
- kNumArgumentsChecked);
- ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == EAX));
-
- if (comp->is_fused_with_branch()) {
- __ CompareObject(EAX, compiler->bool_true());
- comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
+ if (comp->NumTargets() > 0) {
+ EmitEqualityAsPolymorphicCall(compiler, comp, left, right);
+ } else {
+ EmitEqualityAsInstanceCall(compiler, comp);
}
__ Bind(&done);
}
void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
- if (operands_class_id() == kSmi) {
+ if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) {
EmitSmiEqualityCompare(compiler, this);
return;
}
- if (operands_class_id() == kObject) {
- EmitGenericEqualityCompare(compiler, this);
- return;
- }
- UNREACHABLE();
+ EmitGenericEqualityCompare(compiler, this);
}

Powered by Google App Engine
This is Rietveld 408576698