Chromium Code Reviews| Index: runtime/vm/intermediate_language_x64.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_x64.cc (revision 8119) |
| +++ runtime/vm/intermediate_language_x64.cc (working copy) |
| @@ -1193,6 +1193,85 @@ |
| } |
| } |
| + |
| +LocationSummary* UnaryOpComp::MakeLocationSummary() const { |
| + const intptr_t kNumInputs = 1; |
| + const intptr_t kNumTemps = 1; // Needed for doubles. |
| + LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| + summary->set_in(0, Location::RequiresRegister()); |
| + summary->set_out(Location::SameAsFirstInput()); |
| + summary->set_temp(0, Location::RequiresRegister()); |
| + return summary; |
| +} |
| + |
| + |
| +void UnaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| + const ICData& ic_data = *instance_call()->ic_data(); |
| + ASSERT(!ic_data.IsNull()); |
| + ASSERT(ic_data.num_args_tested() == 1); |
| + // TODO(srdjan): Implement for more checks. |
| + ASSERT(ic_data.NumberOfChecks() == 1); |
| + Class& test_class = Class::Handle(); |
| + Function& target = Function::Handle(); |
| + ic_data.GetOneClassCheckAt(0, &test_class, &target); |
| + |
| + Register value = locs()->in(0).reg(); |
| + Register result = locs()->out().reg(); |
| + ASSERT(value == result); |
| + Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| + instance_call()->token_index(), |
| + instance_call()->try_index(), |
| + kDeoptSmiBinaryOp, |
| + value, |
| + kNoRegister); |
| + if (test_class.index() == kSmi) { |
| + __ testq(value, Immediate(kSmiTagMask)); |
| + __ j(NOT_ZERO, deopt); |
| + switch (op_kind()) { |
| + case Token::kNEGATE: |
| + __ negq(value); |
| + __ j(OVERFLOW, deopt); |
| + break; |
| + case Token::kBIT_NOT: |
| + __ notq(value); |
| + __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + } |
| + return; |
| + } |
| + if (test_class.index() == kDouble) { |
|
Florian Schneider
2012/05/31 09:22:54
Maybe it would make sense to split UnaryOp into tw
srdjan
2012/05/31 20:02:44
UnaryOpComp -> UnarySmiOpComp and adding NumberNe
|
| + if (op_kind() == Token::kBIT_NOT) { |
| + __ jmp(deopt); |
| + return; |
| + } |
| + Register temp = locs()->temp(0).reg(); |
| + __ testq(value, Immediate(kSmiTagMask)); |
| + __ j(ZERO, deopt); // Smi. |
| + __ CompareClassId(value, kDouble); |
| + __ j(NOT_EQUAL, deopt); |
| + ASSERT(op_kind() == Token::kNEGATE); |
| + // Allocate result object. |
| + const Class& double_class = |
| + Class::ZoneHandle(Isolate::Current()->object_store()->double_class()); |
| + const Code& stub = |
| + Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| + const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| + __ pushq(value); |
| + compiler->GenerateCall(instance_call()->token_index(), |
| + instance_call()->try_index(), |
| + &label, |
| + PcDescriptors::kOther); |
| + // Result is in EAX. |
| + __ movq(result, RAX); |
| + __ popq(temp); |
| + __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| + __ DoubleNegate(XMM0); |
| + __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| + } |
| +} |
| + |
| } // namespace dart |
| #undef __ |