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

Unified Diff: runtime/vm/intermediate_language_x64.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
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intermediate_language_x64.cc
===================================================================
--- runtime/vm/intermediate_language_x64.cc (revision 8699)
+++ runtime/vm/intermediate_language_x64.cc (working copy)
@@ -199,7 +199,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());
@@ -210,18 +210,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(RAX));
}
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(RAX));
+ }
+ return locs;
}
@@ -257,6 +264,109 @@
}
+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() == RAX));
+
+ if (comp->is_fused_with_branch()) {
+ __ CompareObject(RAX, 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);
+ __ testq(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);
+ __ movq(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));
+ Label next_test;
+ __ cmpq(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);
+ __ cmpq(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() == RAX));
+ if (comp->is_fused_with_branch()) {
+ __ CompareObject(RAX, 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) {
const Immediate raw_null =
@@ -275,51 +385,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.
__ pushq(left);
__ pushq(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() == RAX));
-
- if (comp->is_fused_with_branch()) {
- __ CompareObject(RAX, 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);
}
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698