Index: runtime/vm/intermediate_language_x64.cc |
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc |
index 59c8987938ef3f82e1799d78935989fe38fe783b..bd5701402705c494975d54a20ab866cd4deb9b33 100644 |
--- a/runtime/vm/intermediate_language_x64.cc |
+++ b/runtime/vm/intermediate_language_x64.cc |
@@ -1779,6 +1779,158 @@ void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
} |
+LocationSummary* CheckEitherNonSmiComp::MakeLocationSummary() const { |
+ ASSERT((left()->ResultCid() != kDoubleCid) && |
+ (right()->ResultCid() != kDoubleCid)); |
+ const intptr_t kNumInputs = 2; |
+ const intptr_t kNumTemps = 1; |
+ LocationSummary* summary = |
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
+ summary->set_in(0, Location::RequiresRegister()); |
+ summary->set_in(1, Location::RequiresRegister()); |
+ summary->set_temp(0, Location::RequiresRegister()); |
+ return summary; |
+} |
+ |
+ |
+void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(), |
+ instance_call_->try_index(), |
+ kDeoptBinaryDoubleOp); |
+ |
+ Register temp = locs()->temp(0).reg(); |
+ __ movq(temp, locs()->in(0).reg()); |
+ __ orq(temp, locs()->in(1).reg()); |
+ __ testl(temp, Immediate(kSmiTagMask)); |
+ __ j(ZERO, deopt); |
+} |
+ |
+ |
+LocationSummary* BoxDoubleComp::MakeLocationSummary() const { |
+ const intptr_t kNumInputs = 1; |
+ const intptr_t kNumTemps = 0; |
+ LocationSummary* summary = |
+ new LocationSummary(kNumInputs, |
+ kNumTemps, |
+ LocationSummary::kCallOnSlowPath); |
+ summary->set_in(0, Location::RequiresXmmRegister()); |
+ summary->set_out(Location::RequiresRegister()); |
+ return summary; |
+} |
+ |
+ |
+class BoxDoubleSlowPath : public SlowPathCode { |
+ public: |
+ explicit BoxDoubleSlowPath(BoxDoubleComp* computation) |
+ : computation_(computation) { } |
+ |
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
+ __ Bind(entry_label()); |
+ const Class& double_class = compiler->double_class(); |
+ const Code& stub = |
+ Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
+ const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
+ |
+ // TODO(vegorov): here stack map needs to be set up correctly to skip |
+ // double registers. |
+ LocationSummary* locs = computation_->locs(); |
+ locs->live_registers()->Remove(locs->out()); |
+ |
+ compiler->SaveLiveRegisters(locs); |
+ compiler->GenerateCall(computation_->instance_call()->token_pos(), |
+ computation_->instance_call()->try_index(), |
+ &label, |
+ PcDescriptors::kOther, |
+ locs); |
+ if (RAX != locs->out().reg()) __ movq(locs->out().reg(), RAX); |
+ compiler->RestoreLiveRegisters(locs); |
+ |
+ __ jmp(exit_label()); |
+ } |
+ |
+ private: |
+ BoxDoubleComp* computation_; |
+}; |
+ |
+ |
+void BoxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
+ compiler->AddSlowPathCode(slow_path); |
+ |
+ Register out_reg = locs()->out().reg(); |
+ XmmRegister value = locs()->in(0).xmm_reg(); |
+ |
+ AssemblerMacros::TryAllocate(compiler->assembler(), |
+ compiler->double_class(), |
+ slow_path->entry_label(), |
+ Assembler::kFarJump, |
+ out_reg); |
+ __ Bind(slow_path->exit_label()); |
+ __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
+} |
+ |
+ |
+LocationSummary* UnboxDoubleComp::MakeLocationSummary() const { |
+ const intptr_t v_cid = value()->ResultCid(); |
+ |
+ const intptr_t kNumInputs = 1; |
+ const intptr_t kNumTemps = (v_cid != kDoubleCid) ? 1 : 0; |
+ LocationSummary* summary = |
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
+ summary->set_in(0, Location::RequiresRegister()); |
+ if (v_cid != kDoubleCid) summary->set_temp(0, Location::RequiresRegister()); |
+ summary->set_out(Location::RequiresXmmRegister()); |
+ return summary; |
+} |
+ |
+ |
+void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ const intptr_t v_cid = value()->ResultCid(); |
+ |
+ const Register value = locs()->in(0).reg(); |
+ const XmmRegister result = locs()->out().xmm_reg(); |
+ if (v_cid != kDoubleCid) { |
+ Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
+ instance_call()->try_index(), |
+ kDeoptBinaryDoubleOp); |
+ compiler->LoadDoubleOrSmiToXmm(result, |
+ value, |
+ locs()->temp(0).reg(), |
+ deopt); |
+ } else { |
+ __ movsd(result, FieldAddress(value, Double::value_offset())); |
+ } |
+} |
+ |
+ |
+LocationSummary* UnboxedDoubleBinaryOpComp::MakeLocationSummary() const { |
+ const intptr_t kNumInputs = 2; |
+ const intptr_t kNumTemps = 0; |
+ LocationSummary* summary = |
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
+ summary->set_in(0, Location::RequiresXmmRegister()); |
+ summary->set_in(1, Location::RequiresXmmRegister()); |
+ summary->set_out(Location::SameAsFirstInput()); |
+ return summary; |
+} |
+ |
+ |
+void UnboxedDoubleBinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ XmmRegister left = locs()->in(0).xmm_reg(); |
+ XmmRegister right = locs()->in(1).xmm_reg(); |
+ |
+ ASSERT(locs()->out().xmm_reg() == left); |
+ |
+ switch (op_kind()) { |
+ case Token::kADD: __ addsd(left, right); break; |
+ case Token::kSUB: __ subsd(left, right); break; |
+ case Token::kMUL: __ mulsd(left, right); break; |
+ case Token::kDIV: __ divsd(left, right); break; |
+ default: UNREACHABLE(); |
+ } |
+} |
+ |
+ |
LocationSummary* UnarySmiOpComp::MakeLocationSummary() const { |
const intptr_t kNumInputs = 1; |
const intptr_t kNumTemps = 0; |