Index: runtime/vm/intermediate_language_x64.cc |
=================================================================== |
--- runtime/vm/intermediate_language_x64.cc (revision 7907) |
+++ runtime/vm/intermediate_language_x64.cc (working copy) |
@@ -7,6 +7,7 @@ |
#include "vm/flow_graph_compiler.h" |
#include "vm/locations.h" |
+#include "vm/object_store.h" |
#include "vm/stub_code.h" |
#define __ compiler->assembler()-> |
@@ -137,6 +138,10 @@ |
void InstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
ASSERT(VerifyCallComputation(this)); |
+ compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
+ cid(), |
+ token_index(), |
+ try_index()); |
compiler->EmitInstanceCall(cid(), |
token_index(), |
try_index(), |
@@ -484,6 +489,75 @@ |
} |
+LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
+ return MakeSimpleLocationSummary(2, Location::SameAsFirstInput()); |
+} |
+ |
+ |
+// TODO(srdjan): Implement variations. |
+static bool EmitSmiBinaryOp(FlowGraphCompiler* compiler, |
+ BinaryOpComp* comp) { |
+ ASSERT((comp->ic_data() != NULL)); |
+ const ICData& ic_data = *comp->ic_data(); |
+ if (ic_data.IsNull()) return false; |
+ if (ic_data.num_args_tested() != 2) return false; |
+ if (ic_data.NumberOfChecks() != 1) return false; |
+ Function& target = Function::Handle(); |
+ GrowableArray<const Class*> classes; |
+ ic_data.GetCheckAt(0, &classes, &target); |
+ const Class& smi_class = |
+ Class::Handle(Isolate::Current()->object_store()->smi_class()); |
+ if ((classes[0]->raw() != smi_class.raw()) || |
+ (classes[1]->raw() != smi_class.raw())) { |
+ return false; |
+ } |
+ // TODO(srdjan): need to allocate a temporary register (now using r10) |
+ Register left = comp->locs()->in(0).reg(); |
+ Register right = comp->locs()->in(1).reg(); |
+ Register result = comp->locs()->out().reg(); |
+ Register kTemp = R10; |
Florian Schneider
2012/05/24 00:20:39
It is a little confusing to use "k" as prefix for
|
+ Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
+ comp->instance_call()->token_index(), |
+ comp->instance_call()->try_index(), |
+ kDeoptSmiBinaryOp, |
+ kTemp, |
+ right); |
+ __ movq(kTemp, left); |
+ __ orq(left, right); |
+ __ testq(left, Immediate(kSmiTagMask)); |
+ __ j(NOT_ZERO, deopt); |
+ __ movq(left, kTemp); |
+ switch (comp->op_kind()) { |
+ case Token::kADD: { |
+ __ addq(left, right); |
+ __ j(OVERFLOW, deopt); |
+ if (result != left) { |
+ __ movq(result, left); |
+ } |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ } |
+ return true; |
+} |
+ |
+void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ if (EmitSmiBinaryOp(compiler, this)) { |
Florian Schneider
2012/05/24 00:20:39
Maybe rename it to TryEmitSmiBinaryOp to indicate
srdjan
2012/05/24 01:36:26
Done.
|
+ // Operation inlined. |
+ return; |
+ } |
+ Register left = locs()->in(0).reg(); |
+ Register right = locs()->in(1).reg(); |
+ __ pushq(left); |
+ __ pushq(right); |
+ InstanceCallComp* instance_call_comp = instance_call(); |
+ instance_call_comp->EmitNativeCode(compiler); |
+ if (locs()->out().reg() != RAX) { |
+ __ movq(locs()->out().reg(), RAX); |
+ } |
+} |
+ |
} // namespace dart |
#undef __ |