Chromium Code Reviews| Index: runtime/vm/intermediate_language_ia32.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_ia32.cc (revision 8181) |
| +++ runtime/vm/intermediate_language_ia32.cc (working copy) |
| @@ -9,6 +9,7 @@ |
| #include "vm/flow_graph_compiler.h" |
| #include "vm/locations.h" |
| +#include "vm/object_store.h" |
| #include "vm/stub_code.h" |
| #define __ compiler->assembler()-> |
| @@ -589,22 +590,113 @@ |
| LocationSummary* UnarySmiOpComp::MakeLocationSummary() const { |
| - return NULL; |
| + const intptr_t kNumInputs = 1; |
| + const intptr_t kNumTemps = 0; |
| + LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| + summary->set_in(0, Location::RequiresRegister()); |
| + summary->set_out(Location::SameAsFirstInput()); |
| + return summary; |
| } |
| -void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compile) { |
| - UNIMPLEMENTED(); |
| +void UnarySmiOpComp::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.id() == kSmi) { |
| + __ testl(value, Immediate(kSmiTagMask)); |
| + __ j(NOT_ZERO, deopt); |
| + switch (op_kind()) { |
| + case Token::kNEGATE: |
| + __ negl(value); |
| + __ j(OVERFLOW, deopt); |
| + break; |
| + case Token::kBIT_NOT: |
| + __ notl(value); |
| + __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + } |
| + } else { |
| + UNREACHABLE(); |
| + } |
| } |
| LocationSummary* NumberNegateComp::MakeLocationSummary() const { |
| - return NULL; |
| + 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 NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compile) { |
| - UNIMPLEMENTED(); |
| +void NumberNegateComp::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.id() == kDouble) { |
| + Register temp = locs()->temp(0).reg(); |
| + ASSERT(result != temp); |
| + __ testl(value, Immediate(kSmiTagMask)); |
| + __ j(ZERO, deopt); // Smi. |
| + __ CompareClassId(value, kDouble, temp); |
| + __ j(NOT_EQUAL, deopt); |
| + // 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()); |
| + __ pushl(value); |
| + compiler->GenerateCall(instance_call()->token_index(), |
| + instance_call()->try_index(), |
| + &label, |
| + PcDescriptors::kOther); |
| + // Result is in EAX. |
| + __ movl(result, EAX); |
|
Florian Schneider
2012/06/01 15:49:10
You could avoid the mov if result is already EAX.
srdjan
2012/06/01 18:27:25
Unless preformance/code-size is hurt, I'd like to
Florian Schneider
2012/06/02 18:54:11
Ok, I meant more along this here without changing
|
| + __ popl(temp); |
| + __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| + __ DoubleNegate(XMM0); |
| + __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| } |