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 "lib/error.h" | 10 #include "lib/error.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
| 13 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
| 14 #include "vm/parser.h" | |
|
srdjan
2012/06/22 00:34:40
Why do we need this include?
regis
2012/06/22 01:24:53
Actually, I wonder why it was not needed in the fi
| |
| 14 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
| 15 | 16 |
| 16 #define __ compiler->assembler()-> | 17 #define __ compiler->assembler()-> |
| 17 | 18 |
| 18 namespace dart { | 19 namespace dart { |
| 19 | 20 |
| 20 DECLARE_FLAG(int, optimization_counter_threshold); | 21 DECLARE_FLAG(int, optimization_counter_threshold); |
| 21 DECLARE_FLAG(bool, trace_functions); | 22 DECLARE_FLAG(bool, trace_functions); |
| 22 | 23 |
| 23 // Generic summary for call instructions that have all arguments pushed | 24 // Generic summary for call instructions that have all arguments pushed |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 __ pushl(temp); | 86 __ pushl(temp); |
| 86 compiler->GenerateCallRuntime(AstNode::kNoId, | 87 compiler->GenerateCallRuntime(AstNode::kNoId, |
| 87 0, | 88 0, |
| 88 CatchClauseNode::kInvalidTryIndex, | 89 CatchClauseNode::kInvalidTryIndex, |
| 89 kTraceFunctionExitRuntimeEntry); | 90 kTraceFunctionExitRuntimeEntry); |
| 90 __ popl(temp); // Remove argument. | 91 __ popl(temp); // Remove argument. |
| 91 __ popl(result); // Restore result. | 92 __ popl(result); // Restore result. |
| 92 } | 93 } |
| 93 __ LeaveFrame(); | 94 __ LeaveFrame(); |
| 94 __ ret(); | 95 __ ret(); |
| 95 // Add a NOP to make return code pattern 5 bytes long for patching | 96 |
| 96 // in breakpoints during debugging. | 97 // Generate 1 byte NOP so that the debugger can patch the |
| 98 // return pattern with a call to the debug stub. | |
| 97 __ nop(1); | 99 __ nop(1); |
| 98 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 100 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 99 cid(), | 101 cid(), |
| 100 token_index(), | 102 token_index(), |
| 101 CatchClauseNode::kInvalidTryIndex); | 103 CatchClauseNode::kInvalidTryIndex); |
| 102 } | 104 } |
| 103 | 105 |
| 104 | 106 |
| 105 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 107 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
| 106 const intptr_t kNumInputs = 0; | 108 const intptr_t kNumInputs = 0; |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 437 LocationSummary::kNoCall, | 439 LocationSummary::kNoCall, |
| 438 contains_branch); | 440 contains_branch); |
| 439 summary->set_in(0, Location::RequiresRegister()); | 441 summary->set_in(0, Location::RequiresRegister()); |
| 440 summary->set_in(1, Location::RequiresRegister()); | 442 summary->set_in(1, Location::RequiresRegister()); |
| 441 if (!is_fused_with_branch()) { | 443 if (!is_fused_with_branch()) { |
| 442 summary->set_out(Location::RequiresRegister()); | 444 summary->set_out(Location::RequiresRegister()); |
| 443 } | 445 } |
| 444 summary->set_temp(0, Location::RequiresRegister()); | 446 summary->set_temp(0, Location::RequiresRegister()); |
| 445 return summary; | 447 return summary; |
| 446 } | 448 } |
| 449 ASSERT(!is_fused_with_branch()); | |
| 447 ASSERT(operands_class_id() == kObject); | 450 ASSERT(operands_class_id() == kObject); |
| 448 return MakeCallSummary(); | 451 return MakeCallSummary(); |
| 449 } | 452 } |
| 450 | 453 |
| 451 | 454 |
| 452 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 455 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 453 switch (kind) { | 456 switch (kind) { |
| 454 case Token::kEQ: return EQUAL; | 457 case Token::kEQ: return EQUAL; |
| 455 case Token::kNE: return NOT_EQUAL; | 458 case Token::kNE: return NOT_EQUAL; |
| 456 case Token::kLT: return LESS; | 459 case Token::kLT: return LESS; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 481 __ j(NOT_ZERO, deopt); | 484 __ j(NOT_ZERO, deopt); |
| 482 | 485 |
| 483 Condition true_condition = TokenKindToSmiCondition(comp->kind()); | 486 Condition true_condition = TokenKindToSmiCondition(comp->kind()); |
| 484 __ cmpl(left, right); | 487 __ cmpl(left, right); |
| 485 | 488 |
| 486 if (comp->is_fused_with_branch()) { | 489 if (comp->is_fused_with_branch()) { |
| 487 comp->fused_with_branch()->EmitBranchOnCondition(compiler, true_condition); | 490 comp->fused_with_branch()->EmitBranchOnCondition(compiler, true_condition); |
| 488 } else { | 491 } else { |
| 489 Register result = comp->locs()->out().reg(); | 492 Register result = comp->locs()->out().reg(); |
| 490 Label done, is_true; | 493 Label done, is_true; |
| 491 | |
| 492 __ j(true_condition, &is_true); | 494 __ j(true_condition, &is_true); |
| 493 __ LoadObject(result, compiler->bool_false()); | 495 __ LoadObject(result, compiler->bool_false()); |
| 494 __ jmp(&done); | 496 __ jmp(&done); |
| 495 __ Bind(&is_true); | 497 __ Bind(&is_true); |
| 496 __ LoadObject(result, compiler->bool_true()); | 498 __ LoadObject(result, compiler->bool_true()); |
| 497 __ Bind(&done); | 499 __ Bind(&done); |
| 498 } | 500 } |
| 499 } | 501 } |
| 500 | 502 |
| 501 | 503 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 try_index(), | 576 try_index(), |
| 575 function_name, | 577 function_name, |
| 576 kNumArguments, | 578 kNumArguments, |
| 577 Array::ZoneHandle(), // No optional arguments. | 579 Array::ZoneHandle(), // No optional arguments. |
| 578 kNumArgsChecked); | 580 kNumArgsChecked); |
| 579 ASSERT(locs()->out().reg() == EAX); | 581 ASSERT(locs()->out().reg() == EAX); |
| 580 } | 582 } |
| 581 | 583 |
| 582 | 584 |
| 583 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 585 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| 584 LocationSummary* locs = new LocationSummary(0, 3, LocationSummary::kCall); | 586 const intptr_t kNumInputs = 0; |
| 587 const intptr_t kNumTemps = 3; | |
| 588 LocationSummary* locs = new LocationSummary(kNumInputs, | |
| 589 kNumTemps, | |
| 590 LocationSummary::kCall); | |
| 585 locs->set_temp(0, Location::RegisterLocation(EAX)); | 591 locs->set_temp(0, Location::RegisterLocation(EAX)); |
| 586 locs->set_temp(1, Location::RegisterLocation(ECX)); | 592 locs->set_temp(1, Location::RegisterLocation(ECX)); |
| 587 locs->set_temp(2, Location::RegisterLocation(EDX)); | 593 locs->set_temp(2, Location::RegisterLocation(EDX)); |
| 588 locs->set_out(Location::RequiresRegister()); | 594 locs->set_out(Location::RequiresRegister()); |
| 589 return locs; | 595 return locs; |
| 590 } | 596 } |
| 591 | 597 |
| 592 | 598 |
| 593 void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 599 void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 594 ASSERT(locs()->temp(0).reg() == EAX); | 600 ASSERT(locs()->temp(0).reg() == EAX); |
| 595 ASSERT(locs()->temp(1).reg() == ECX); | 601 ASSERT(locs()->temp(1).reg() == ECX); |
| 596 ASSERT(locs()->temp(2).reg() == EDX); | 602 ASSERT(locs()->temp(2).reg() == EDX); |
| 597 Register result = locs()->out().reg(); | 603 Register result = locs()->out().reg(); |
| 604 | |
| 598 // Push the result place holder initialized to NULL. | 605 // Push the result place holder initialized to NULL. |
| 599 __ PushObject(Object::ZoneHandle()); | 606 __ PushObject(Object::ZoneHandle()); |
| 600 // Pass a pointer to the first argument in EAX. | 607 // Pass a pointer to the first argument in EAX. |
| 601 intptr_t arg_count = argument_count(); | 608 intptr_t arg_count = argument_count(); |
| 602 if (is_native_instance_closure()) { | 609 if (is_native_instance_closure()) { |
| 603 arg_count += 1; | 610 arg_count += 1; |
| 604 } | 611 } |
| 605 if (!has_optional_parameters() && !is_native_instance_closure()) { | 612 if (!has_optional_parameters() && !is_native_instance_closure()) { |
| 606 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); | 613 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); |
| 607 } else { | 614 } else { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 681 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 675 if (receiver_type() == kIllegalObjectKind) { | 682 if (receiver_type() == kIllegalObjectKind) { |
| 676 if (HasICData()) { | 683 if (HasICData()) { |
| 677 EmitLoadIndexedPolymorphic(compiler, this); | 684 EmitLoadIndexedPolymorphic(compiler, this); |
| 678 } else { | 685 } else { |
| 679 compiler->EmitLoadIndexedGeneric(this); | 686 compiler->EmitLoadIndexedGeneric(this); |
| 680 } | 687 } |
| 681 ASSERT(locs()->out().reg() == EAX); | 688 ASSERT(locs()->out().reg() == EAX); |
| 682 return; | 689 return; |
| 683 } | 690 } |
| 691 | |
| 684 Register receiver = locs()->in(0).reg(); | 692 Register receiver = locs()->in(0).reg(); |
| 685 Register index = locs()->in(1).reg(); | 693 Register index = locs()->in(1).reg(); |
| 686 Register result = locs()->out().reg(); | 694 Register result = locs()->out().reg(); |
| 687 Register temp = locs()->temp(0).reg(); | 695 Register temp = locs()->temp(0).reg(); |
| 688 | 696 |
| 689 const Class& receiver_class = | |
| 690 Class::ZoneHandle(Isolate::Current()->class_table()->At( | |
| 691 receiver_type())); | |
| 692 | |
| 693 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 697 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? |
| 694 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 698 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 695 | 699 |
| 696 Label* deopt = compiler->AddDeoptStub(cid(), | 700 Label* deopt = compiler->AddDeoptStub(cid(), |
| 697 token_index(), | 701 token_index(), |
| 698 try_index(), | 702 try_index(), |
| 699 deopt_reason, | 703 deopt_reason, |
| 700 receiver, | 704 receiver, |
| 701 index); | 705 index); |
| 702 | 706 |
| 703 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 707 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 704 __ j(ZERO, deopt); | 708 __ j(ZERO, deopt); |
| 705 __ CompareClassId(receiver, receiver_class.id(), temp); | 709 __ CompareClassId(receiver, receiver_type(), temp); |
| 706 __ j(NOT_EQUAL, deopt); | 710 __ j(NOT_EQUAL, deopt); |
| 707 | 711 |
| 708 __ testl(index, Immediate(kSmiTagMask)); | 712 __ testl(index, Immediate(kSmiTagMask)); |
| 709 __ j(NOT_ZERO, deopt); | 713 __ j(NOT_ZERO, deopt); |
| 710 | 714 |
| 711 switch (receiver_type()) { | 715 switch (receiver_type()) { |
| 712 case kArray: | 716 case kArray: |
| 713 case kImmutableArray: | 717 case kImmutableArray: |
| 714 __ cmpl(index, FieldAddress(receiver, Array::length_offset())); | 718 __ cmpl(index, FieldAddress(receiver, Array::length_offset())); |
| 715 __ j(ABOVE_EQUAL, deopt); | 719 __ j(ABOVE_EQUAL, deopt); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 733 | 737 |
| 734 default: | 738 default: |
| 735 UNREACHABLE(); | 739 UNREACHABLE(); |
| 736 break; | 740 break; |
| 737 } | 741 } |
| 738 } | 742 } |
| 739 | 743 |
| 740 | 744 |
| 741 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { | 745 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { |
| 742 const intptr_t kNumInputs = 3; | 746 const intptr_t kNumInputs = 3; |
| 743 if (receiver_type() == kGrowableObjectArray || receiver_type() == kArray) { | 747 if ((receiver_type() == kGrowableObjectArray) || |
| 748 (receiver_type() == kArray)) { | |
| 744 const intptr_t kNumTemps = 1; | 749 const intptr_t kNumTemps = 1; |
| 745 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 750 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 746 locs->set_in(0, Location::RequiresRegister()); | 751 locs->set_in(0, Location::RequiresRegister()); |
| 747 locs->set_in(1, Location::RequiresRegister()); | 752 locs->set_in(1, Location::RequiresRegister()); |
| 748 locs->set_in(2, Location::RequiresRegister()); | 753 locs->set_in(2, Location::RequiresRegister()); |
| 749 locs->set_temp(0, Location::RequiresRegister()); | 754 locs->set_temp(0, Location::RequiresRegister()); |
| 750 locs->set_out(Location::NoLocation()); | 755 locs->set_out(Location::NoLocation()); |
| 751 return locs; | 756 return locs; |
| 752 } else { | 757 } else { |
| 753 ASSERT(receiver_type() == kIllegalObjectKind); | 758 ASSERT(receiver_type() == kIllegalObjectKind); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 766 comp->token_index(), | 771 comp->token_index(), |
| 767 comp->try_index()); | 772 comp->try_index()); |
| 768 | 773 |
| 769 const intptr_t kNumArguments = 3; | 774 const intptr_t kNumArguments = 3; |
| 770 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 775 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
| 771 compiler->GenerateInstanceCall(comp->cid(), | 776 compiler->GenerateInstanceCall(comp->cid(), |
| 772 comp->token_index(), | 777 comp->token_index(), |
| 773 comp->try_index(), | 778 comp->try_index(), |
| 774 function_name, | 779 function_name, |
| 775 kNumArguments, | 780 kNumArguments, |
| 776 Array::ZoneHandle(), // No named args. | 781 Array::ZoneHandle(), // No named arguments. |
| 777 kNumArgsChecked); | 782 kNumArgsChecked); |
| 778 } | 783 } |
| 779 | 784 |
| 780 | 785 |
| 781 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 786 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 782 StoreIndexedComp* comp) { | 787 StoreIndexedComp* comp) { |
| 783 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 788 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 784 comp->token_index(), | 789 comp->token_index(), |
| 785 comp->try_index(), | 790 comp->try_index(), |
| 786 kDeoptStoreIndexedPolymorphic); | 791 kDeoptStoreIndexedPolymorphic); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1006 locs->set_in(0, Location::RegisterLocation(ECX)); | 1011 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 1007 locs->set_temp(0, Location::RegisterLocation(EDX)); | 1012 locs->set_temp(0, Location::RegisterLocation(EDX)); |
| 1008 locs->set_out(Location::RegisterLocation(EAX)); | 1013 locs->set_out(Location::RegisterLocation(EAX)); |
| 1009 return locs; | 1014 return locs; |
| 1010 } | 1015 } |
| 1011 | 1016 |
| 1012 | 1017 |
| 1013 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1018 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1014 Register temp_reg = locs()->temp(0).reg(); | 1019 Register temp_reg = locs()->temp(0).reg(); |
| 1015 Register result_reg = locs()->out().reg(); | 1020 Register result_reg = locs()->out().reg(); |
| 1021 | |
| 1022 // Allocate the array. EDX = length, ECX = element type. | |
| 1016 ASSERT(temp_reg == EDX); | 1023 ASSERT(temp_reg == EDX); |
| 1017 ASSERT(locs()->in(0).reg() == ECX); | 1024 ASSERT(locs()->in(0).reg() == ECX); |
| 1018 // 1. Allocate the array. EDX = length, ECX = element type. | 1025 __ movl(temp_reg, Immediate(Smi::RawValue(ElementCount()))); |
| 1019 __ movl(EDX, Immediate(Smi::RawValue(ElementCount()))); | |
| 1020 compiler->GenerateCall(token_index(), | 1026 compiler->GenerateCall(token_index(), |
| 1021 try_index(), | 1027 try_index(), |
| 1022 &StubCode::AllocateArrayLabel(), | 1028 &StubCode::AllocateArrayLabel(), |
| 1023 PcDescriptors::kOther); | 1029 PcDescriptors::kOther); |
| 1024 ASSERT(result_reg == EAX); | 1030 ASSERT(result_reg == EAX); |
| 1031 | |
| 1025 // Pop the element values from the stack into the array. | 1032 // Pop the element values from the stack into the array. |
| 1026 __ leal(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 1033 __ leal(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
| 1027 for (int i = ElementCount() - 1; i >= 0; --i) { | 1034 for (int i = ElementCount() - 1; i >= 0; --i) { |
| 1028 ASSERT(ElementAt(i)->IsUse()); | 1035 ASSERT(ElementAt(i)->IsUse()); |
| 1029 __ popl(Address(temp_reg, i * kWordSize)); | 1036 __ popl(Address(temp_reg, i * kWordSize)); |
| 1030 } | 1037 } |
| 1031 } | 1038 } |
| 1032 | 1039 |
| 1033 | 1040 |
| 1034 LocationSummary* | 1041 LocationSummary* |
| 1035 AllocateObjectWithBoundsCheckComp::MakeLocationSummary() const { | 1042 AllocateObjectWithBoundsCheckComp::MakeLocationSummary() const { |
| 1036 return LocationSummary::Make(2, | 1043 return LocationSummary::Make(2, |
| 1037 Location::RequiresRegister(), | 1044 Location::RequiresRegister(), |
| 1038 LocationSummary::kCall); | 1045 LocationSummary::kCall); |
| 1039 } | 1046 } |
| 1040 | 1047 |
| 1041 | 1048 |
| 1042 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 1049 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
| 1043 FlowGraphCompiler* compiler) { | 1050 FlowGraphCompiler* compiler) { |
| 1044 const Class& cls = Class::ZoneHandle(constructor().owner()); | 1051 const Class& cls = Class::ZoneHandle(constructor().owner()); |
| 1045 Register type_arguments = locs()->in(0).reg(); | 1052 Register type_arguments = locs()->in(0).reg(); |
| 1046 Register instantiator_type_arguments = locs()->in(1).reg(); | 1053 Register instantiator_type_arguments = locs()->in(1).reg(); |
| 1047 Register result = locs()->out().reg(); | 1054 Register result = locs()->out().reg(); |
| 1048 | 1055 |
| 1056 // Push the result place holder initialized to NULL. | |
| 1049 __ PushObject(Object::ZoneHandle()); | 1057 __ PushObject(Object::ZoneHandle()); |
| 1050 __ pushl(Immediate(Smi::RawValue(token_index()))); | 1058 __ pushl(Immediate(Smi::RawValue(token_index()))); |
| 1051 __ PushObject(cls); | 1059 __ PushObject(cls); |
| 1052 __ pushl(type_arguments); | 1060 __ pushl(type_arguments); |
| 1053 __ pushl(instantiator_type_arguments); | 1061 __ pushl(instantiator_type_arguments); |
| 1054 compiler->GenerateCallRuntime(cid(), | 1062 compiler->GenerateCallRuntime(cid(), |
| 1055 token_index(), | 1063 token_index(), |
| 1056 try_index(), | 1064 try_index(), |
| 1057 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1065 kAllocateObjectWithBoundsCheckRuntimeEntry); |
| 1058 // Pop instantiator type arguments, type arguments, class, and | 1066 // Pop instantiator type arguments, type arguments, class, and |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1117 if (type_arguments().IsRawInstantiatedRaw(len)) { | 1125 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1118 const Immediate raw_null = | 1126 const Immediate raw_null = |
| 1119 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1127 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1120 __ cmpl(instantiator_reg, raw_null); | 1128 __ cmpl(instantiator_reg, raw_null); |
| 1121 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1129 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1122 } | 1130 } |
| 1123 // Instantiate non-null type arguments. | 1131 // Instantiate non-null type arguments. |
| 1124 if (type_arguments().IsUninstantiatedIdentity()) { | 1132 if (type_arguments().IsUninstantiatedIdentity()) { |
| 1125 // Check if the instantiator type argument vector is a TypeArguments of a | 1133 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1126 // matching length and, if so, use it as the instantiated type_arguments. | 1134 // matching length and, if so, use it as the instantiated type_arguments. |
| 1127 // No need to check instantiator for null (again), because a null instance | 1135 // No need to check the instantiator ('instantiator_reg') for null here, |
| 1128 // will have the wrong class (Null instead of TypeArguments). | 1136 // because a null instantiator will have the wrong class (Null instead of |
| 1137 // TypeArguments). | |
| 1129 Label type_arguments_uninstantiated; | 1138 Label type_arguments_uninstantiated; |
| 1130 __ CompareClassId(instantiator_reg, kTypeArguments, temp); | 1139 __ CompareClassId(instantiator_reg, kTypeArguments, temp); |
| 1131 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1140 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 1132 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1141 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
| 1133 Immediate(Smi::RawValue(len))); | 1142 Immediate(Smi::RawValue(len))); |
| 1134 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1143 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1135 __ Bind(&type_arguments_uninstantiated); | 1144 __ Bind(&type_arguments_uninstantiated); |
| 1136 } | 1145 } |
| 1137 // A runtime call to instantiate the type arguments is required. | 1146 // A runtime call to instantiate the type arguments is required. |
| 1138 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1147 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1139 __ PushObject(type_arguments()); | 1148 __ PushObject(type_arguments()); |
| 1140 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1149 __ pushl(instantiator_reg); // Push instantiator type arguments. |
| 1141 compiler->GenerateCallRuntime(cid(), | 1150 compiler->GenerateCallRuntime(cid(), |
| 1142 token_index(), | 1151 token_index(), |
| 1143 try_index(), | 1152 try_index(), |
| 1144 kInstantiateTypeArgumentsRuntimeEntry); | 1153 kInstantiateTypeArgumentsRuntimeEntry); |
| 1145 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1154 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1146 __ popl(result_reg); // Pop instantiated type arguments. | 1155 __ popl(result_reg); // Pop instantiated type arguments. |
| 1147 __ Bind(&type_arguments_instantiated); | 1156 __ Bind(&type_arguments_instantiated); |
| 1148 ASSERT(instantiator_reg == result_reg); | 1157 ASSERT(instantiator_reg == result_reg); |
| 1158 // 'result_reg': Instantiated type arguments. | |
| 1149 } | 1159 } |
| 1150 | 1160 |
| 1151 | 1161 |
| 1152 LocationSummary* | 1162 LocationSummary* |
| 1153 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { | 1163 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { |
| 1154 const intptr_t kNumInputs = 1; | 1164 const intptr_t kNumInputs = 1; |
| 1155 const intptr_t kNumTemps = 1; | 1165 const intptr_t kNumTemps = 1; |
| 1156 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1166 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 1157 locs->set_in(0, Location::RequiresRegister()); | 1167 locs->set_in(0, Location::RequiresRegister()); |
| 1158 locs->set_out(Location::SameAsFirstInput()); | 1168 locs->set_out(Location::SameAsFirstInput()); |
| 1159 locs->set_temp(0, Location::RequiresRegister()); | 1169 locs->set_temp(0, Location::RequiresRegister()); |
| 1160 return locs; | 1170 return locs; |
| 1161 } | 1171 } |
| 1162 | 1172 |
| 1163 | 1173 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1200 // In the non-factory case, we rely on the allocation stub to | 1210 // In the non-factory case, we rely on the allocation stub to |
| 1201 // instantiate the type arguments. | 1211 // instantiate the type arguments. |
| 1202 __ LoadObject(result_reg, type_arguments()); | 1212 __ LoadObject(result_reg, type_arguments()); |
| 1203 // result_reg: uninstantiated type arguments. | 1213 // result_reg: uninstantiated type arguments. |
| 1204 __ Bind(&type_arguments_instantiated); | 1214 __ Bind(&type_arguments_instantiated); |
| 1205 // result_reg: uninstantiated or instantiated type arguments. | 1215 // result_reg: uninstantiated or instantiated type arguments. |
| 1206 } | 1216 } |
| 1207 | 1217 |
| 1208 | 1218 |
| 1209 LocationSummary* | 1219 LocationSummary* |
| 1210 ExtractConstructorInstantiatorComp::MakeLocationSummary() const { | 1220 ExtractConstructorInstantiatorComp::MakeLocationSummary() const { |
| 1211 const intptr_t kNumInputs = 1; | 1221 const intptr_t kNumInputs = 1; |
| 1212 const intptr_t kNumTemps = 1; | 1222 const intptr_t kNumTemps = 1; |
| 1213 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1223 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 1214 locs->set_in(0, Location::RequiresRegister()); | 1224 locs->set_in(0, Location::RequiresRegister()); |
| 1215 locs->set_out(Location::SameAsFirstInput()); | 1225 locs->set_out(Location::SameAsFirstInput()); |
| 1216 locs->set_temp(0, Location::RequiresRegister()); | 1226 locs->set_temp(0, Location::RequiresRegister()); |
| 1217 return locs; | 1227 return locs; |
| 1218 } | 1228 } |
| 1219 | 1229 |
| 1220 | 1230 |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1812 Register value = locs()->in(0).reg(); | 1822 Register value = locs()->in(0).reg(); |
| 1813 Register result = locs()->out().reg(); | 1823 Register result = locs()->out().reg(); |
| 1814 ASSERT(value == result); | 1824 ASSERT(value == result); |
| 1815 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1825 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1816 instance_call()->token_index(), | 1826 instance_call()->token_index(), |
| 1817 instance_call()->try_index(), | 1827 instance_call()->try_index(), |
| 1818 kDeoptUnaryOp, | 1828 kDeoptUnaryOp, |
| 1819 value); | 1829 value); |
| 1820 if (test_class_id == kDouble) { | 1830 if (test_class_id == kDouble) { |
| 1821 Register temp = locs()->temp(0).reg(); | 1831 Register temp = locs()->temp(0).reg(); |
| 1822 ASSERT(result != temp); | |
| 1823 __ testl(value, Immediate(kSmiTagMask)); | 1832 __ testl(value, Immediate(kSmiTagMask)); |
| 1824 __ j(ZERO, deopt); // Smi. | 1833 __ j(ZERO, deopt); // Smi. |
| 1825 __ CompareClassId(value, kDouble, temp); | 1834 __ CompareClassId(value, kDouble, temp); |
| 1826 __ j(NOT_EQUAL, deopt); | 1835 __ j(NOT_EQUAL, deopt); |
| 1827 // Allocate result object. | 1836 // Allocate result object. |
| 1828 const Class& double_class = compiler->double_class(); | 1837 const Class& double_class = compiler->double_class(); |
| 1829 const Code& stub = | 1838 const Code& stub = |
| 1830 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1839 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1831 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1840 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1832 __ pushl(value); | 1841 __ pushl(value); |
| 1833 compiler->GenerateCall(instance_call()->token_index(), | 1842 compiler->GenerateCall(instance_call()->token_index(), |
| 1834 instance_call()->try_index(), | 1843 instance_call()->try_index(), |
| 1835 &label, | 1844 &label, |
| 1836 PcDescriptors::kOther); | 1845 PcDescriptors::kOther); |
| 1837 // Result is in EAX. | 1846 // Result is in EAX. |
| 1847 ASSERT(result != temp); | |
| 1838 __ movl(result, EAX); | 1848 __ movl(result, EAX); |
| 1839 __ popl(temp); | 1849 __ popl(temp); |
| 1840 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1850 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 1841 __ DoubleNegate(XMM0); | 1851 __ DoubleNegate(XMM0); |
| 1842 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1852 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1843 } else { | 1853 } else { |
| 1844 UNREACHABLE(); | 1854 UNREACHABLE(); |
| 1845 } | 1855 } |
| 1846 } | 1856 } |
| 1847 | 1857 |
| 1848 | 1858 |
| 1849 LocationSummary* ToDoubleComp::MakeLocationSummary() const { | 1859 LocationSummary* ToDoubleComp::MakeLocationSummary() const { |
| 1850 const intptr_t kNumInputs = 1; | 1860 const intptr_t kNumInputs = 1; |
| 1851 if (from() == kDouble) { | 1861 if (from() == kDouble) { |
| 1852 const intptr_t kNumTemps = 1; | 1862 const intptr_t kNumTemps = 1; |
| 1853 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1863 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 1854 locs->set_in(0, Location::RequiresRegister()); | 1864 locs->set_in(0, Location::RequiresRegister()); |
| 1855 locs->set_temp(0, Location::RequiresRegister()); | 1865 locs->set_temp(0, Location::RequiresRegister()); |
| 1856 locs->set_out(Location::SameAsFirstInput()); | 1866 locs->set_out(Location::SameAsFirstInput()); |
| 1857 locs->set_temp(0, Location::RequiresRegister()); | 1867 locs->set_temp(0, Location::RequiresRegister()); |
| 1858 return locs; | 1868 return locs; |
| 1859 } else { | 1869 } else { |
| 1860 ASSERT(from() == kSmi); | 1870 ASSERT(from() == kSmi); |
| 1861 return MakeCallSummary(); // Calls a stub to allocate result. | 1871 return MakeCallSummary(); // Calls a stub to allocate result. |
| 1862 } | 1872 } |
| 1863 } | 1873 } |
| 1864 | 1874 |
| 1865 | 1875 |
| 1866 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1876 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1877 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; | |
| 1867 Register result = locs()->out().reg(); | 1878 Register result = locs()->out().reg(); |
| 1868 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; | |
| 1869 | 1879 |
| 1870 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1880 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
| 1871 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1881 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
| 1872 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1882 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1873 instance_call()->token_index(), | 1883 instance_call()->token_index(), |
| 1874 instance_call()->try_index(), | 1884 instance_call()->try_index(), |
| 1875 deopt_reason, | 1885 deopt_reason, |
| 1876 value); | 1886 value); |
| 1877 | 1887 |
| 1878 if (from() == kDouble) { | 1888 if (from() == kDouble) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1956 instance_call()->argument_names()); | 1966 instance_call()->argument_names()); |
| 1957 } | 1967 } |
| 1958 __ Bind(&done); | 1968 __ Bind(&done); |
| 1959 } | 1969 } |
| 1960 | 1970 |
| 1961 } // namespace dart | 1971 } // namespace dart |
| 1962 | 1972 |
| 1963 #undef __ | 1973 #undef __ |
| 1964 | 1974 |
| 1965 #endif // defined TARGET_ARCH_X64 | 1975 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |