Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| 11 #include "vm/locations.h" | 11 #include "vm/locations.h" |
| 12 #include "vm/object_store.h" | |
| 12 #include "vm/stub_code.h" | 13 #include "vm/stub_code.h" |
| 13 | 14 |
| 14 #define __ compiler->assembler()-> | 15 #define __ compiler->assembler()-> |
| 15 | 16 |
| 16 namespace dart { | 17 namespace dart { |
| 17 | 18 |
| 18 DECLARE_FLAG(int, optimization_counter_threshold); | 19 DECLARE_FLAG(int, optimization_counter_threshold); |
| 19 DECLARE_FLAG(bool, trace_functions); | 20 DECLARE_FLAG(bool, trace_functions); |
| 20 | 21 |
| 21 // True iff. the arguments to a call will be properly pushed and can | 22 // True iff. the arguments to a call will be properly pushed and can |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 582 __ pushl(right); | 583 __ pushl(right); |
| 583 InstanceCallComp* instance_call_comp = instance_call(); | 584 InstanceCallComp* instance_call_comp = instance_call(); |
| 584 instance_call_comp->EmitNativeCode(compiler); | 585 instance_call_comp->EmitNativeCode(compiler); |
| 585 if (locs()->out().reg() != EAX) { | 586 if (locs()->out().reg() != EAX) { |
| 586 __ movl(locs()->out().reg(), EAX); | 587 __ movl(locs()->out().reg(), EAX); |
| 587 } | 588 } |
| 588 } | 589 } |
| 589 | 590 |
| 590 | 591 |
| 591 LocationSummary* UnarySmiOpComp::MakeLocationSummary() const { | 592 LocationSummary* UnarySmiOpComp::MakeLocationSummary() const { |
| 592 return NULL; | 593 const intptr_t kNumInputs = 1; |
| 594 const intptr_t kNumTemps = 0; | |
| 595 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | |
| 596 summary->set_in(0, Location::RequiresRegister()); | |
| 597 summary->set_out(Location::SameAsFirstInput()); | |
| 598 return summary; | |
| 593 } | 599 } |
| 594 | 600 |
| 595 | 601 |
| 596 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compile) { | 602 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 597 UNIMPLEMENTED(); | 603 const ICData& ic_data = *instance_call()->ic_data(); |
| 604 ASSERT(!ic_data.IsNull()); | |
| 605 ASSERT(ic_data.num_args_tested() == 1); | |
| 606 // TODO(srdjan): Implement for more checks. | |
| 607 ASSERT(ic_data.NumberOfChecks() == 1); | |
| 608 Class& test_class = Class::Handle(); | |
| 609 Function& target = Function::Handle(); | |
| 610 ic_data.GetOneClassCheckAt(0, &test_class, &target); | |
| 611 | |
| 612 Register value = locs()->in(0).reg(); | |
| 613 Register result = locs()->out().reg(); | |
| 614 ASSERT(value == result); | |
| 615 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | |
| 616 instance_call()->token_index(), | |
| 617 instance_call()->try_index(), | |
| 618 kDeoptSmiBinaryOp, | |
| 619 value, | |
| 620 kNoRegister); | |
| 621 if (test_class.id() == kSmi) { | |
| 622 __ testl(value, Immediate(kSmiTagMask)); | |
| 623 __ j(NOT_ZERO, deopt); | |
| 624 switch (op_kind()) { | |
| 625 case Token::kNEGATE: | |
| 626 __ negl(value); | |
| 627 __ j(OVERFLOW, deopt); | |
| 628 break; | |
| 629 case Token::kBIT_NOT: | |
| 630 __ notl(value); | |
| 631 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | |
| 632 break; | |
| 633 default: | |
| 634 UNREACHABLE(); | |
| 635 } | |
| 636 } else { | |
| 637 UNREACHABLE(); | |
| 638 } | |
| 598 } | 639 } |
| 599 | 640 |
| 600 | 641 |
| 601 LocationSummary* NumberNegateComp::MakeLocationSummary() const { | 642 LocationSummary* NumberNegateComp::MakeLocationSummary() const { |
| 602 return NULL; | 643 const intptr_t kNumInputs = 1; |
| 644 const intptr_t kNumTemps = 1; // Needed for doubles. | |
| 645 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | |
| 646 summary->set_in(0, Location::RequiresRegister()); | |
| 647 summary->set_out(Location::SameAsFirstInput()); | |
| 648 summary->set_temp(0, Location::RequiresRegister()); | |
| 649 return summary; | |
| 603 } | 650 } |
| 604 | 651 |
| 605 | 652 |
| 606 void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compile) { | 653 void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 607 UNIMPLEMENTED(); | 654 const ICData& ic_data = *instance_call()->ic_data(); |
| 655 ASSERT(!ic_data.IsNull()); | |
| 656 ASSERT(ic_data.num_args_tested() == 1); | |
| 657 | |
| 658 // TODO(srdjan): Implement for more checks. | |
| 659 ASSERT(ic_data.NumberOfChecks() == 1); | |
| 660 Class& test_class = Class::Handle(); | |
| 661 Function& target = Function::Handle(); | |
| 662 ic_data.GetOneClassCheckAt(0, &test_class, &target); | |
| 663 | |
| 664 Register value = locs()->in(0).reg(); | |
| 665 Register result = locs()->out().reg(); | |
| 666 ASSERT(value == result); | |
| 667 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | |
| 668 instance_call()->token_index(), | |
| 669 instance_call()->try_index(), | |
| 670 kDeoptSmiBinaryOp, | |
| 671 value, | |
| 672 kNoRegister); | |
| 673 if (test_class.id() == kDouble) { | |
| 674 Register temp = locs()->temp(0).reg(); | |
| 675 ASSERT(result != temp); | |
| 676 __ testl(value, Immediate(kSmiTagMask)); | |
| 677 __ j(ZERO, deopt); // Smi. | |
| 678 __ CompareClassId(value, kDouble, temp); | |
| 679 __ j(NOT_EQUAL, deopt); | |
| 680 // Allocate result object. | |
| 681 const Class& double_class = | |
| 682 Class::ZoneHandle(Isolate::Current()->object_store()->double_class()); | |
| 683 const Code& stub = | |
| 684 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | |
| 685 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | |
| 686 __ pushl(value); | |
| 687 compiler->GenerateCall(instance_call()->token_index(), | |
| 688 instance_call()->try_index(), | |
| 689 &label, | |
| 690 PcDescriptors::kOther); | |
| 691 // Result is in EAX. | |
| 692 __ 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
| |
| 693 __ popl(temp); | |
| 694 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | |
| 695 __ DoubleNegate(XMM0); | |
| 696 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | |
| 697 } else { | |
| 698 UNREACHABLE(); | |
| 699 } | |
| 608 } | 700 } |
| 609 | 701 |
| 610 | 702 |
| 611 } // namespace dart | 703 } // namespace dart |
| 612 | 704 |
| 613 #undef __ | 705 #undef __ |
| 614 | 706 |
| 615 #endif // defined TARGET_ARCH_X64 | 707 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |