| 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" | 14 #include "vm/parser.h" |
| 15 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
| 16 #include "vm/symbols.h" | 16 #include "vm/symbols.h" |
| 17 | 17 |
| 18 #define __ compiler->assembler()-> | 18 #define __ compiler->assembler()-> |
| 19 | 19 |
| 20 namespace dart { | 20 namespace dart { |
| 21 | 21 |
| 22 DECLARE_FLAG(int, optimization_counter_threshold); | 22 DECLARE_FLAG(int, optimization_counter_threshold); |
| 23 DECLARE_FLAG(bool, trace_functions); | 23 DECLARE_FLAG(bool, trace_functions); |
| 24 | 24 |
| 25 // Generic summary for call instructions that have all arguments pushed | 25 // Generic summary for call instructions that have all arguments pushed |
| 26 // on the stack and return the result in a fixed register EAX. | 26 // on the stack and return the result in a fixed register EAX. |
| 27 LocationSummary* Computation::MakeCallSummary() { | 27 LocationSummary* Instruction::MakeCallSummary() { |
| 28 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); | 28 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); |
| 29 result->set_out(Location::RegisterLocation(EAX)); | 29 result->set_out(Location::RegisterLocation(EAX)); |
| 30 return result; | 30 return result; |
| 31 } | 31 } |
| 32 | 32 |
| 33 | 33 |
| 34 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 35 computation()->EmitNativeCode(compiler); | |
| 36 if (is_used() && !compiler->is_optimizing()) { | |
| 37 __ pushl(locs()->out().reg()); | |
| 38 } | |
| 39 } | |
| 40 | |
| 41 | |
| 42 LocationSummary* ReturnInstr::MakeLocationSummary() const { | 34 LocationSummary* ReturnInstr::MakeLocationSummary() const { |
| 43 const intptr_t kNumInputs = 1; | 35 const intptr_t kNumInputs = 1; |
| 44 const intptr_t kNumTemps = 1; | 36 const intptr_t kNumTemps = 1; |
| 45 LocationSummary* locs = | 37 LocationSummary* locs = |
| 46 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 38 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 47 locs->set_in(0, Location::RegisterLocation(EAX)); | 39 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 48 locs->set_temp(0, Location::RequiresRegister()); | 40 locs->set_temp(0, Location::RequiresRegister()); |
| 49 return locs; | 41 return locs; |
| 50 } | 42 } |
| 51 | 43 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 | 103 |
| 112 // Generate 1 byte NOP so that the debugger can patch the | 104 // Generate 1 byte NOP so that the debugger can patch the |
| 113 // return pattern with a call to the debug stub. | 105 // return pattern with a call to the debug stub. |
| 114 __ nop(1); | 106 __ nop(1); |
| 115 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 107 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 116 deopt_id(), | 108 deopt_id(), |
| 117 token_pos()); | 109 token_pos()); |
| 118 } | 110 } |
| 119 | 111 |
| 120 | 112 |
| 121 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 113 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
| 122 const intptr_t kNumInputs = 0; | 114 const intptr_t kNumInputs = 0; |
| 123 const intptr_t kNumTemps = 1; | 115 const intptr_t kNumTemps = 1; |
| 124 LocationSummary* result = | 116 LocationSummary* result = |
| 125 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 117 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 126 result->set_out(Location::RegisterLocation(EAX)); | 118 result->set_out(Location::RegisterLocation(EAX)); |
| 127 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. | 119 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. |
| 128 return result; | 120 return result; |
| 129 } | 121 } |
| 130 | 122 |
| 131 | 123 |
| 132 LocationSummary* LoadLocalComp::MakeLocationSummary() const { | 124 LocationSummary* LoadLocalInstr::MakeLocationSummary() const { |
| 133 return LocationSummary::Make(0, | 125 return LocationSummary::Make(0, |
| 134 Location::RequiresRegister(), | 126 Location::RequiresRegister(), |
| 135 LocationSummary::kNoCall); | 127 LocationSummary::kNoCall); |
| 136 } | 128 } |
| 137 | 129 |
| 138 | 130 |
| 139 void LoadLocalComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 131 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 140 Register result = locs()->out().reg(); | 132 Register result = locs()->out().reg(); |
| 141 __ movl(result, Address(EBP, local().index() * kWordSize)); | 133 __ movl(result, Address(EBP, local().index() * kWordSize)); |
| 142 } | 134 } |
| 143 | 135 |
| 144 | 136 |
| 145 LocationSummary* StoreLocalComp::MakeLocationSummary() const { | 137 LocationSummary* StoreLocalInstr::MakeLocationSummary() const { |
| 146 return LocationSummary::Make(1, | 138 return LocationSummary::Make(1, |
| 147 Location::SameAsFirstInput(), | 139 Location::SameAsFirstInput(), |
| 148 LocationSummary::kNoCall); | 140 LocationSummary::kNoCall); |
| 149 } | 141 } |
| 150 | 142 |
| 151 | 143 |
| 152 void StoreLocalComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 144 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 153 Register value = locs()->in(0).reg(); | 145 Register value = locs()->in(0).reg(); |
| 154 Register result = locs()->out().reg(); | 146 Register result = locs()->out().reg(); |
| 155 ASSERT(result == value); // Assert that register assignment is correct. | 147 ASSERT(result == value); // Assert that register assignment is correct. |
| 156 __ movl(Address(EBP, local().index() * kWordSize), value); | 148 __ movl(Address(EBP, local().index() * kWordSize), value); |
| 157 } | 149 } |
| 158 | 150 |
| 159 | 151 |
| 160 LocationSummary* ConstantComp::MakeLocationSummary() const { | 152 LocationSummary* ConstantInstr::MakeLocationSummary() const { |
| 161 return LocationSummary::Make(0, | 153 return LocationSummary::Make(0, |
| 162 Location::RequiresRegister(), | 154 Location::RequiresRegister(), |
| 163 LocationSummary::kNoCall); | 155 LocationSummary::kNoCall); |
| 164 } | 156 } |
| 165 | 157 |
| 166 | 158 |
| 167 void ConstantComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 159 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 168 // Register allocator drops constant definitions that have no uses. | 160 // The register allocator drops constant definitions that have no uses. |
| 169 if (!locs()->out().IsInvalid()) { | 161 if (!locs()->out().IsInvalid()) { |
| 170 Register result = locs()->out().reg(); | 162 Register result = locs()->out().reg(); |
| 171 __ LoadObject(result, value()); | 163 __ LoadObject(result, value()); |
| 172 } | 164 } |
| 173 } | 165 } |
| 174 | 166 |
| 175 | 167 |
| 176 LocationSummary* AssertAssignableComp::MakeLocationSummary() const { | 168 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { |
| 177 const intptr_t kNumInputs = 3; | 169 const intptr_t kNumInputs = 3; |
| 178 const intptr_t kNumTemps = 0; | 170 const intptr_t kNumTemps = 0; |
| 179 LocationSummary* summary = | 171 LocationSummary* summary = |
| 180 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 172 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 181 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. | 173 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. |
| 182 summary->set_in(1, Location::RegisterLocation(ECX)); // Instantiator. | 174 summary->set_in(1, Location::RegisterLocation(ECX)); // Instantiator. |
| 183 summary->set_in(2, Location::RegisterLocation(EDX)); // Type arguments. | 175 summary->set_in(2, Location::RegisterLocation(EDX)); // Type arguments. |
| 184 summary->set_out(Location::RegisterLocation(EAX)); | 176 summary->set_out(Location::RegisterLocation(EAX)); |
| 185 return summary; | 177 return summary; |
| 186 } | 178 } |
| 187 | 179 |
| 188 | 180 |
| 189 LocationSummary* AssertBooleanComp::MakeLocationSummary() const { | 181 LocationSummary* AssertBooleanInstr::MakeLocationSummary() const { |
| 190 const intptr_t kNumInputs = 1; | 182 const intptr_t kNumInputs = 1; |
| 191 const intptr_t kNumTemps = 0; | 183 const intptr_t kNumTemps = 0; |
| 192 LocationSummary* locs = | 184 LocationSummary* locs = |
| 193 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 185 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 194 locs->set_in(0, Location::RegisterLocation(EAX)); | 186 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 195 locs->set_out(Location::RegisterLocation(EAX)); | 187 locs->set_out(Location::RegisterLocation(EAX)); |
| 196 return locs; | 188 return locs; |
| 197 } | 189 } |
| 198 | 190 |
| 199 | 191 |
| 200 void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 192 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 201 Register obj = locs()->in(0).reg(); | 193 Register obj = locs()->in(0).reg(); |
| 202 Register result = locs()->out().reg(); | 194 Register result = locs()->out().reg(); |
| 203 | 195 |
| 204 if (!is_eliminated()) { | 196 if (!is_eliminated()) { |
| 205 // Check that the type of the value is allowed in conditional context. | 197 // Check that the type of the value is allowed in conditional context. |
| 206 // Call the runtime if the object is not bool::true or bool::false. | 198 // Call the runtime if the object is not bool::true or bool::false. |
| 207 Label done; | 199 Label done; |
| 208 __ CompareObject(obj, compiler->bool_true()); | 200 __ CompareObject(obj, compiler->bool_true()); |
| 209 __ j(EQUAL, &done, Assembler::kNearJump); | 201 __ j(EQUAL, &done, Assembler::kNearJump); |
| 210 __ CompareObject(obj, compiler->bool_false()); | 202 __ CompareObject(obj, compiler->bool_false()); |
| 211 __ j(EQUAL, &done, Assembler::kNearJump); | 203 __ j(EQUAL, &done, Assembler::kNearJump); |
| 212 | 204 |
| 213 __ pushl(obj); // Push the source object. | 205 __ pushl(obj); // Push the source object. |
| 214 compiler->GenerateCallRuntime(token_pos(), | 206 compiler->GenerateCallRuntime(token_pos(), |
| 215 kConditionTypeErrorRuntimeEntry, | 207 kConditionTypeErrorRuntimeEntry, |
| 216 locs()); | 208 locs()); |
| 217 // We should never return here. | 209 // We should never return here. |
| 218 __ int3(); | 210 __ int3(); |
| 219 __ Bind(&done); | 211 __ Bind(&done); |
| 220 } | 212 } |
| 221 ASSERT(obj == result); | 213 ASSERT(obj == result); |
| 222 } | 214 } |
| 223 | 215 |
| 224 | 216 |
| 225 LocationSummary* ArgumentDefinitionTestComp::MakeLocationSummary() const { | 217 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { |
| 226 const intptr_t kNumInputs = 1; | 218 const intptr_t kNumInputs = 1; |
| 227 const intptr_t kNumTemps = 0; | 219 const intptr_t kNumTemps = 0; |
| 228 LocationSummary* locs = | 220 LocationSummary* locs = |
| 229 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 221 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 230 locs->set_in(0, Location::RegisterLocation(EAX)); | 222 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 231 locs->set_out(Location::RegisterLocation(EAX)); | 223 locs->set_out(Location::RegisterLocation(EAX)); |
| 232 return locs; | 224 return locs; |
| 233 } | 225 } |
| 234 | 226 |
| 235 | 227 |
| 236 void ArgumentDefinitionTestComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 228 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 237 Register saved_args_desc = locs()->in(0).reg(); | 229 Register saved_args_desc = locs()->in(0).reg(); |
| 238 Register result = locs()->out().reg(); | 230 Register result = locs()->out().reg(); |
| 239 | 231 |
| 240 // Push the result place holder initialized to NULL. | 232 // Push the result place holder initialized to NULL. |
| 241 __ PushObject(Object::ZoneHandle()); | 233 __ PushObject(Object::ZoneHandle()); |
| 242 __ pushl(Immediate(Smi::RawValue(formal_parameter_index()))); | 234 __ pushl(Immediate(Smi::RawValue(formal_parameter_index()))); |
| 243 __ PushObject(formal_parameter_name()); | 235 __ PushObject(formal_parameter_name()); |
| 244 __ pushl(saved_args_desc); | 236 __ pushl(saved_args_desc); |
| 245 compiler->GenerateCallRuntime(token_pos(), | 237 compiler->GenerateCallRuntime(token_pos(), |
| 246 kArgumentDefinitionTestRuntimeEntry, | 238 kArgumentDefinitionTestRuntimeEntry, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 258 case Token::kGT: return GREATER; | 250 case Token::kGT: return GREATER; |
| 259 case Token::kLTE: return LESS_EQUAL; | 251 case Token::kLTE: return LESS_EQUAL; |
| 260 case Token::kGTE: return GREATER_EQUAL; | 252 case Token::kGTE: return GREATER_EQUAL; |
| 261 default: | 253 default: |
| 262 UNREACHABLE(); | 254 UNREACHABLE(); |
| 263 return OVERFLOW; | 255 return OVERFLOW; |
| 264 } | 256 } |
| 265 } | 257 } |
| 266 | 258 |
| 267 | 259 |
| 268 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 260 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { |
| 269 const intptr_t kNumInputs = 2; | 261 const intptr_t kNumInputs = 2; |
| 270 const bool is_checked_strict_equal = | 262 const bool is_checked_strict_equal = |
| 271 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 263 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 272 if (receiver_class_id() == kDoubleCid) { | 264 if (receiver_class_id() == kDoubleCid) { |
| 273 const intptr_t kNumTemps = 0; | 265 const intptr_t kNumTemps = 0; |
| 274 LocationSummary* locs = | 266 LocationSummary* locs = |
| 275 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 267 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 276 locs->set_in(0, Location::RequiresXmmRegister()); | 268 locs->set_in(0, Location::RequiresXmmRegister()); |
| 277 locs->set_in(1, Location::RequiresXmmRegister()); | 269 locs->set_in(1, Location::RequiresXmmRegister()); |
| 278 locs->set_out(Location::RequiresRegister()); | 270 locs->set_out(Location::RequiresRegister()); |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 if (branch != NULL) { | 602 if (branch != NULL) { |
| 611 compiler->EmitDoubleCompareBranch( | 603 compiler->EmitDoubleCompareBranch( |
| 612 true_condition, left, right, branch); | 604 true_condition, left, right, branch); |
| 613 } else { | 605 } else { |
| 614 compiler->EmitDoubleCompareBool( | 606 compiler->EmitDoubleCompareBool( |
| 615 true_condition, left, right, locs.out().reg()); | 607 true_condition, left, right, locs.out().reg()); |
| 616 } | 608 } |
| 617 } | 609 } |
| 618 | 610 |
| 619 | 611 |
| 620 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 612 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 621 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 613 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 622 BranchInstr* kNoBranch = NULL; | 614 BranchInstr* kNoBranch = NULL; |
| 623 if (receiver_class_id() == kSmiCid) { | 615 if (receiver_class_id() == kSmiCid) { |
| 624 // Deoptimizes if both arguments not Smi. | 616 // Deoptimizes if both arguments not Smi. |
| 625 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | 617 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 626 return; | 618 return; |
| 627 } | 619 } |
| 628 if (receiver_class_id() == kDoubleCid) { | 620 if (receiver_class_id() == kDoubleCid) { |
| 629 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); | 621 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 630 return; | 622 return; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 643 } | 635 } |
| 644 Register left = locs()->in(0).reg(); | 636 Register left = locs()->in(0).reg(); |
| 645 Register right = locs()->in(1).reg(); | 637 Register right = locs()->in(1).reg(); |
| 646 __ pushl(left); | 638 __ pushl(left); |
| 647 __ pushl(right); | 639 __ pushl(right); |
| 648 EmitEqualityAsInstanceCall(compiler, deopt_id(), token_pos(), kind(), locs()); | 640 EmitEqualityAsInstanceCall(compiler, deopt_id(), token_pos(), kind(), locs()); |
| 649 ASSERT(locs()->out().reg() == EAX); | 641 ASSERT(locs()->out().reg() == EAX); |
| 650 } | 642 } |
| 651 | 643 |
| 652 | 644 |
| 653 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, | 645 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 654 BranchInstr* branch) { | 646 BranchInstr* branch) { |
| 655 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 647 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 656 if (receiver_class_id() == kSmiCid) { | 648 if (receiver_class_id() == kSmiCid) { |
| 657 // Deoptimizes if both arguments not Smi. | 649 // Deoptimizes if both arguments not Smi. |
| 658 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 650 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 659 return; | 651 return; |
| 660 } | 652 } |
| 661 if (receiver_class_id() == kDoubleCid) { | 653 if (receiver_class_id() == kDoubleCid) { |
| 662 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 654 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 663 return; | 655 return; |
| 664 } | 656 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 682 deopt_id(), | 674 deopt_id(), |
| 683 token_pos(), | 675 token_pos(), |
| 684 Token::kEQ, // kNE reverse occurs at branch. | 676 Token::kEQ, // kNE reverse occurs at branch. |
| 685 locs()); | 677 locs()); |
| 686 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 678 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 687 __ CompareObject(EAX, compiler->bool_true()); | 679 __ CompareObject(EAX, compiler->bool_true()); |
| 688 branch->EmitBranchOnCondition(compiler, branch_condition); | 680 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 689 } | 681 } |
| 690 | 682 |
| 691 | 683 |
| 692 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 684 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 693 const intptr_t kNumInputs = 2; | 685 const intptr_t kNumInputs = 2; |
| 694 if (operands_class_id() == kDoubleCid) { | 686 if (operands_class_id() == kDoubleCid) { |
| 695 const intptr_t kNumTemps = 0; | 687 const intptr_t kNumTemps = 0; |
| 696 LocationSummary* summary = | 688 LocationSummary* summary = |
| 697 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 689 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 698 summary->set_in(0, Location::RequiresXmmRegister()); | 690 summary->set_in(0, Location::RequiresXmmRegister()); |
| 699 summary->set_in(1, Location::RequiresXmmRegister()); | 691 summary->set_in(1, Location::RequiresXmmRegister()); |
| 700 summary->set_out(Location::RequiresRegister()); | 692 summary->set_out(Location::RequiresRegister()); |
| 701 return summary; | 693 return summary; |
| 702 } else if (operands_class_id() == kSmiCid) { | 694 } else if (operands_class_id() == kSmiCid) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 713 LocationSummary* locs = | 705 LocationSummary* locs = |
| 714 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 706 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 715 // Pick arbitrary fixed input registers because this is a call. | 707 // Pick arbitrary fixed input registers because this is a call. |
| 716 locs->set_in(0, Location::RegisterLocation(EAX)); | 708 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 717 locs->set_in(1, Location::RegisterLocation(ECX)); | 709 locs->set_in(1, Location::RegisterLocation(ECX)); |
| 718 locs->set_out(Location::RegisterLocation(EAX)); | 710 locs->set_out(Location::RegisterLocation(EAX)); |
| 719 return locs; | 711 return locs; |
| 720 } | 712 } |
| 721 | 713 |
| 722 | 714 |
| 723 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 715 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 724 if (operands_class_id() == kSmiCid) { | 716 if (operands_class_id() == kSmiCid) { |
| 725 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 717 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); |
| 726 return; | 718 return; |
| 727 } | 719 } |
| 728 if (operands_class_id() == kDoubleCid) { | 720 if (operands_class_id() == kDoubleCid) { |
| 729 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 721 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); |
| 730 return; | 722 return; |
| 731 } | 723 } |
| 732 | 724 |
| 733 // Push arguments for the call. | 725 // Push arguments for the call. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 compiler->GenerateInstanceCall(deopt_id(), | 761 compiler->GenerateInstanceCall(deopt_id(), |
| 770 token_pos(), | 762 token_pos(), |
| 771 function_name, | 763 function_name, |
| 772 kNumArguments, | 764 kNumArguments, |
| 773 Array::ZoneHandle(), // No optional arguments. | 765 Array::ZoneHandle(), // No optional arguments. |
| 774 kNumArgsChecked, | 766 kNumArgsChecked, |
| 775 locs()); | 767 locs()); |
| 776 } | 768 } |
| 777 | 769 |
| 778 | 770 |
| 779 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, | 771 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 780 BranchInstr* branch) { | 772 BranchInstr* branch) { |
| 781 if (operands_class_id() == kSmiCid) { | 773 if (operands_class_id() == kSmiCid) { |
| 782 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 774 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 783 return; | 775 return; |
| 784 } | 776 } |
| 785 if (operands_class_id() == kDoubleCid) { | 777 if (operands_class_id() == kDoubleCid) { |
| 786 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 778 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 787 return; | 779 return; |
| 788 } | 780 } |
| 789 EmitNativeCode(compiler); | 781 EmitNativeCode(compiler); |
| 790 __ CompareObject(EAX, compiler->bool_true()); | 782 __ CompareObject(EAX, compiler->bool_true()); |
| 791 branch->EmitBranchOnCondition(compiler, EQUAL); | 783 branch->EmitBranchOnCondition(compiler, EQUAL); |
| 792 } | 784 } |
| 793 | 785 |
| 794 | 786 |
| 795 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 787 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 796 const intptr_t kNumInputs = 0; | 788 const intptr_t kNumInputs = 0; |
| 797 const intptr_t kNumTemps = 3; | 789 const intptr_t kNumTemps = 3; |
| 798 LocationSummary* locs = | 790 LocationSummary* locs = |
| 799 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 791 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 800 locs->set_temp(0, Location::RegisterLocation(EAX)); | 792 locs->set_temp(0, Location::RegisterLocation(EAX)); |
| 801 locs->set_temp(1, Location::RegisterLocation(ECX)); | 793 locs->set_temp(1, Location::RegisterLocation(ECX)); |
| 802 locs->set_temp(2, Location::RegisterLocation(EDX)); | 794 locs->set_temp(2, Location::RegisterLocation(EDX)); |
| 803 locs->set_out(Location::RegisterLocation(EAX)); | 795 locs->set_out(Location::RegisterLocation(EAX)); |
| 804 return locs; | 796 return locs; |
| 805 } | 797 } |
| 806 | 798 |
| 807 | 799 |
| 808 void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 800 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 809 ASSERT(locs()->temp(0).reg() == EAX); | 801 ASSERT(locs()->temp(0).reg() == EAX); |
| 810 ASSERT(locs()->temp(1).reg() == ECX); | 802 ASSERT(locs()->temp(1).reg() == ECX); |
| 811 ASSERT(locs()->temp(2).reg() == EDX); | 803 ASSERT(locs()->temp(2).reg() == EDX); |
| 812 Register result = locs()->out().reg(); | 804 Register result = locs()->out().reg(); |
| 813 | 805 |
| 814 // Push the result place holder initialized to NULL. | 806 // Push the result place holder initialized to NULL. |
| 815 __ PushObject(Object::ZoneHandle()); | 807 __ PushObject(Object::ZoneHandle()); |
| 816 // Pass a pointer to the first argument in EAX. | 808 // Pass a pointer to the first argument in EAX. |
| 817 intptr_t arg_count = argument_count(); | 809 intptr_t arg_count = argument_count(); |
| 818 if (is_native_instance_closure()) { | 810 if (is_native_instance_closure()) { |
| 819 arg_count += 1; | 811 arg_count += 1; |
| 820 } | 812 } |
| 821 if (!has_optional_parameters() && !is_native_instance_closure()) { | 813 if (!has_optional_parameters() && !is_native_instance_closure()) { |
| 822 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); | 814 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); |
| 823 } else { | 815 } else { |
| 824 __ leal(EAX, | 816 __ leal(EAX, |
| 825 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 817 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
| 826 } | 818 } |
| 827 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 819 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
| 828 __ movl(EDX, Immediate(arg_count)); | 820 __ movl(EDX, Immediate(arg_count)); |
| 829 compiler->GenerateCall(token_pos(), | 821 compiler->GenerateCall(token_pos(), |
| 830 &StubCode::CallNativeCFunctionLabel(), | 822 &StubCode::CallNativeCFunctionLabel(), |
| 831 PcDescriptors::kOther, | 823 PcDescriptors::kOther, |
| 832 locs()); | 824 locs()); |
| 833 __ popl(result); | 825 __ popl(result); |
| 834 } | 826 } |
| 835 | 827 |
| 836 | 828 |
| 837 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 829 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { |
| 838 ASSERT((receiver_type() == kGrowableObjectArrayCid) || | 830 ASSERT((receiver_type() == kGrowableObjectArrayCid) || |
| 839 (receiver_type() == kArrayCid) || | 831 (receiver_type() == kArrayCid) || |
| 840 (receiver_type() == kImmutableArrayCid)); | 832 (receiver_type() == kImmutableArrayCid)); |
| 841 const intptr_t kNumInputs = 2; | 833 const intptr_t kNumInputs = 2; |
| 842 const intptr_t kNumTemps = receiver_type() == kGrowableObjectArrayCid ? 1 : 0; | 834 const intptr_t kNumTemps = receiver_type() == kGrowableObjectArrayCid ? 1 : 0; |
| 843 LocationSummary* locs = | 835 LocationSummary* locs = |
| 844 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 836 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 845 locs->set_in(0, Location::RequiresRegister()); | 837 locs->set_in(0, Location::RequiresRegister()); |
| 846 locs->set_in(1, Location::RequiresRegister()); | 838 locs->set_in(1, Location::RequiresRegister()); |
| 847 if (receiver_type() == kGrowableObjectArrayCid) { | 839 if (receiver_type() == kGrowableObjectArrayCid) { |
| 848 locs->set_temp(0, Location::RequiresRegister()); | 840 locs->set_temp(0, Location::RequiresRegister()); |
| 849 } | 841 } |
| 850 locs->set_out(Location::RequiresRegister()); | 842 locs->set_out(Location::RequiresRegister()); |
| 851 return locs; | 843 return locs; |
| 852 } | 844 } |
| 853 | 845 |
| 854 | 846 |
| 855 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 847 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 856 Register receiver = locs()->in(0).reg(); | 848 Register receiver = locs()->in(0).reg(); |
| 857 Register index = locs()->in(1).reg(); | 849 Register index = locs()->in(1).reg(); |
| 858 Register result = locs()->out().reg(); | 850 Register result = locs()->out().reg(); |
| 859 | 851 |
| 860 switch (receiver_type()) { | 852 switch (receiver_type()) { |
| 861 case kArrayCid: | 853 case kArrayCid: |
| 862 case kImmutableArrayCid: | 854 case kImmutableArrayCid: |
| 863 // Note that index is Smi, i.e, times 2. | 855 // Note that index is Smi, i.e, times 2. |
| 864 ASSERT(kSmiTagShift == 1); | 856 ASSERT(kSmiTagShift == 1); |
| 865 __ movl(result, FieldAddress(receiver, index, TIMES_2, sizeof(RawArray))); | 857 __ movl(result, FieldAddress(receiver, index, TIMES_2, sizeof(RawArray))); |
| 866 break; | 858 break; |
| 867 | 859 |
| 868 case kGrowableObjectArrayCid: { | 860 case kGrowableObjectArrayCid: { |
| 869 Register temp = locs()->temp(0).reg(); | 861 Register temp = locs()->temp(0).reg(); |
| 870 __ movl(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); | 862 __ movl(temp, FieldAddress(receiver, GrowableObjectArray::data_offset())); |
| 871 // Note that index is Smi, i.e, times 2. | 863 // Note that index is Smi, i.e, times 2. |
| 872 ASSERT(kSmiTagShift == 1); | 864 ASSERT(kSmiTagShift == 1); |
| 873 __ movl(result, FieldAddress(temp, index, TIMES_2, sizeof(RawArray))); | 865 __ movl(result, FieldAddress(temp, index, TIMES_2, sizeof(RawArray))); |
| 874 break; | 866 break; |
| 875 } | 867 } |
| 876 | 868 |
| 877 default: | 869 default: |
| 878 UNREACHABLE(); | 870 UNREACHABLE(); |
| 879 break; | 871 break; |
| 880 } | 872 } |
| 881 } | 873 } |
| 882 | 874 |
| 883 | 875 |
| 884 LocationSummary* StoreIndexedComp::MakeLocationSummary() const { | 876 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
| 885 ASSERT((receiver_type() == kGrowableObjectArrayCid) || | 877 ASSERT((receiver_type() == kGrowableObjectArrayCid) || |
| 886 (receiver_type() == kArrayCid)); | 878 (receiver_type() == kArrayCid)); |
| 887 const intptr_t kNumInputs = 3; | 879 const intptr_t kNumInputs = 3; |
| 888 const intptr_t kNumTemps = receiver_type() == kGrowableObjectArrayCid ? 1 : 0; | 880 const intptr_t kNumTemps = receiver_type() == kGrowableObjectArrayCid ? 1 : 0; |
| 889 LocationSummary* locs = | 881 LocationSummary* locs = |
| 890 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 882 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 891 locs->set_in(0, Location::RequiresRegister()); | 883 locs->set_in(0, Location::RequiresRegister()); |
| 892 locs->set_in(1, Location::RequiresRegister()); | 884 locs->set_in(1, Location::RequiresRegister()); |
| 893 locs->set_in(2, Location::RequiresRegister()); | 885 locs->set_in(2, Location::RequiresRegister()); |
| 894 if (receiver_type() == kGrowableObjectArrayCid) { | 886 if (receiver_type() == kGrowableObjectArrayCid) { |
| 895 locs->set_temp(0, Location::RequiresRegister()); | 887 locs->set_temp(0, Location::RequiresRegister()); |
| 896 } | 888 } |
| 897 return locs; | 889 return locs; |
| 898 } | 890 } |
| 899 | 891 |
| 900 | 892 |
| 901 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 893 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 902 Register receiver = locs()->in(0).reg(); | 894 Register receiver = locs()->in(0).reg(); |
| 903 Register index = locs()->in(1).reg(); | 895 Register index = locs()->in(1).reg(); |
| 904 Register value = locs()->in(2).reg(); | 896 Register value = locs()->in(2).reg(); |
| 905 | 897 |
| 906 switch (receiver_type()) { | 898 switch (receiver_type()) { |
| 907 case kArrayCid: | 899 case kArrayCid: |
| 908 case kImmutableArrayCid: | 900 case kImmutableArrayCid: |
| 909 // Note that index is Smi, i.e, times 2. | 901 // Note that index is Smi, i.e, times 2. |
| 910 ASSERT(kSmiTagShift == 1); | 902 ASSERT(kSmiTagShift == 1); |
| 911 if (this->value()->NeedsStoreBuffer()) { | 903 if (this->value()->NeedsStoreBuffer()) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 936 break; | 928 break; |
| 937 } | 929 } |
| 938 | 930 |
| 939 default: | 931 default: |
| 940 UNREACHABLE(); | 932 UNREACHABLE(); |
| 941 break; | 933 break; |
| 942 } | 934 } |
| 943 } | 935 } |
| 944 | 936 |
| 945 | 937 |
| 946 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { | 938 LocationSummary* LoadInstanceFieldInstr::MakeLocationSummary() const { |
| 947 // TODO(fschneider): For this instruction the input register may be | 939 // TODO(fschneider): For this instruction the input register may be |
| 948 // reused for the result (but is not required to) because the input | 940 // reused for the result (but is not required to) because the input |
| 949 // is not used after the result is defined. We should consider adding | 941 // is not used after the result is defined. We should consider adding |
| 950 // this information to the input policy. | 942 // this information to the input policy. |
| 951 return LocationSummary::Make(1, | 943 return LocationSummary::Make(1, |
| 952 Location::RequiresRegister(), | 944 Location::RequiresRegister(), |
| 953 LocationSummary::kNoCall); | 945 LocationSummary::kNoCall); |
| 954 } | 946 } |
| 955 | 947 |
| 956 | 948 |
| 957 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 949 void LoadInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 958 Register instance_reg = locs()->in(0).reg(); | 950 Register instance_reg = locs()->in(0).reg(); |
| 959 Register result_reg = locs()->out().reg(); | 951 Register result_reg = locs()->out().reg(); |
| 960 __ movl(result_reg, FieldAddress(instance_reg, field().Offset())); | 952 __ movl(result_reg, FieldAddress(instance_reg, field().Offset())); |
| 961 } | 953 } |
| 962 | 954 |
| 963 | 955 |
| 964 LocationSummary* StoreInstanceFieldComp::MakeLocationSummary() const { | 956 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
| 965 const intptr_t kNumInputs = 2; | 957 const intptr_t kNumInputs = 2; |
| 966 const intptr_t num_temps = 0; | 958 const intptr_t num_temps = 0; |
| 967 LocationSummary* summary = | 959 LocationSummary* summary = |
| 968 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); | 960 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); |
| 969 summary->set_in(0, Location::RequiresRegister()); | 961 summary->set_in(0, Location::RequiresRegister()); |
| 970 summary->set_in(1, Location::RequiresRegister()); | 962 summary->set_in(1, Location::RequiresRegister()); |
| 971 return summary; | 963 return summary; |
| 972 } | 964 } |
| 973 | 965 |
| 974 | 966 |
| 975 void StoreInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 967 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 976 Register instance_reg = locs()->in(0).reg(); | 968 Register instance_reg = locs()->in(0).reg(); |
| 977 Register value_reg = locs()->in(1).reg(); | 969 Register value_reg = locs()->in(1).reg(); |
| 978 if (this->value()->NeedsStoreBuffer()) { | 970 if (this->value()->NeedsStoreBuffer()) { |
| 979 __ StoreIntoObject(instance_reg, | 971 __ StoreIntoObject(instance_reg, |
| 980 FieldAddress(instance_reg, field().Offset()), value_reg); | 972 FieldAddress(instance_reg, field().Offset()), value_reg); |
| 981 } else { | 973 } else { |
| 982 __ StoreIntoObjectNoBarrier(instance_reg, | 974 __ StoreIntoObjectNoBarrier(instance_reg, |
| 983 FieldAddress(instance_reg, field().Offset()), value_reg); | 975 FieldAddress(instance_reg, field().Offset()), value_reg); |
| 984 } | 976 } |
| 985 } | 977 } |
| 986 | 978 |
| 987 | 979 |
| 988 LocationSummary* LoadStaticFieldComp::MakeLocationSummary() const { | 980 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const { |
| 989 return LocationSummary::Make(0, | 981 return LocationSummary::Make(0, |
| 990 Location::RequiresRegister(), | 982 Location::RequiresRegister(), |
| 991 LocationSummary::kNoCall); | 983 LocationSummary::kNoCall); |
| 992 } | 984 } |
| 993 | 985 |
| 994 | 986 |
| 995 void LoadStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 987 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 996 Register result = locs()->out().reg(); | 988 Register result = locs()->out().reg(); |
| 997 __ LoadObject(result, field()); | 989 __ LoadObject(result, field()); |
| 998 __ movl(result, FieldAddress(result, Field::value_offset())); | 990 __ movl(result, FieldAddress(result, Field::value_offset())); |
| 999 } | 991 } |
| 1000 | 992 |
| 1001 | 993 |
| 1002 LocationSummary* StoreStaticFieldComp::MakeLocationSummary() const { | 994 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const { |
| 1003 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); | 995 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); |
| 1004 locs->set_in(0, Location::RequiresRegister()); | 996 locs->set_in(0, Location::RequiresRegister()); |
| 1005 locs->set_temp(0, Location::RequiresRegister()); | 997 locs->set_temp(0, Location::RequiresRegister()); |
| 1006 locs->set_out(Location::SameAsFirstInput()); | 998 locs->set_out(Location::SameAsFirstInput()); |
| 1007 return locs; | 999 return locs; |
| 1008 } | 1000 } |
| 1009 | 1001 |
| 1010 | 1002 |
| 1011 void StoreStaticFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1003 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1012 Register value = locs()->in(0).reg(); | 1004 Register value = locs()->in(0).reg(); |
| 1013 Register temp = locs()->temp(0).reg(); | 1005 Register temp = locs()->temp(0).reg(); |
| 1014 ASSERT(locs()->out().reg() == value); | 1006 ASSERT(locs()->out().reg() == value); |
| 1015 | 1007 |
| 1016 __ LoadObject(temp, field()); | 1008 __ LoadObject(temp, field()); |
| 1017 if (this->value()->NeedsStoreBuffer()) { | 1009 if (this->value()->NeedsStoreBuffer()) { |
| 1018 __ StoreIntoObject(temp, FieldAddress(temp, Field::value_offset()), value); | 1010 __ StoreIntoObject(temp, FieldAddress(temp, Field::value_offset()), value); |
| 1019 } else { | 1011 } else { |
| 1020 __ StoreIntoObjectNoBarrier( | 1012 __ StoreIntoObjectNoBarrier( |
| 1021 temp, FieldAddress(temp, Field::value_offset()), value); | 1013 temp, FieldAddress(temp, Field::value_offset()), value); |
| 1022 } | 1014 } |
| 1023 } | 1015 } |
| 1024 | 1016 |
| 1025 | 1017 |
| 1026 LocationSummary* InstanceOfComp::MakeLocationSummary() const { | 1018 LocationSummary* InstanceOfInstr::MakeLocationSummary() const { |
| 1027 const intptr_t kNumInputs = 3; | 1019 const intptr_t kNumInputs = 3; |
| 1028 const intptr_t kNumTemps = 0; | 1020 const intptr_t kNumTemps = 0; |
| 1029 LocationSummary* summary = | 1021 LocationSummary* summary = |
| 1030 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1022 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1031 summary->set_in(0, Location::RegisterLocation(EAX)); | 1023 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 1032 summary->set_in(1, Location::RegisterLocation(ECX)); | 1024 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 1033 summary->set_in(2, Location::RegisterLocation(EDX)); | 1025 summary->set_in(2, Location::RegisterLocation(EDX)); |
| 1034 summary->set_out(Location::RegisterLocation(EAX)); | 1026 summary->set_out(Location::RegisterLocation(EAX)); |
| 1035 return summary; | 1027 return summary; |
| 1036 } | 1028 } |
| 1037 | 1029 |
| 1038 | 1030 |
| 1039 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1031 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1040 ASSERT(locs()->in(0).reg() == EAX); // Value. | 1032 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 1041 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 1033 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
| 1042 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 1034 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
| 1043 | 1035 |
| 1044 compiler->GenerateInstanceOf(token_pos(), | 1036 compiler->GenerateInstanceOf(token_pos(), |
| 1045 type(), | 1037 type(), |
| 1046 negate_result(), | 1038 negate_result(), |
| 1047 locs()); | 1039 locs()); |
| 1048 ASSERT(locs()->out().reg() == EAX); | 1040 ASSERT(locs()->out().reg() == EAX); |
| 1049 } | 1041 } |
| 1050 | 1042 |
| 1051 | 1043 |
| 1052 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1044 LocationSummary* CreateArrayInstr::MakeLocationSummary() const { |
| 1053 const intptr_t kNumInputs = 1; | 1045 const intptr_t kNumInputs = 1; |
| 1054 const intptr_t kNumTemps = 0; | 1046 const intptr_t kNumTemps = 0; |
| 1055 LocationSummary* locs = | 1047 LocationSummary* locs = |
| 1056 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1048 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1057 locs->set_in(0, Location::RegisterLocation(ECX)); | 1049 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 1058 locs->set_out(Location::RegisterLocation(EAX)); | 1050 locs->set_out(Location::RegisterLocation(EAX)); |
| 1059 return locs; | 1051 return locs; |
| 1060 } | 1052 } |
| 1061 | 1053 |
| 1062 | 1054 |
| 1063 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1055 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1064 // Allocate the array. EDX = length, ECX = element type. | 1056 // Allocate the array. EDX = length, ECX = element type. |
| 1065 ASSERT(locs()->in(0).reg() == ECX); | 1057 ASSERT(locs()->in(0).reg() == ECX); |
| 1066 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount()))); | 1058 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount()))); |
| 1067 compiler->GenerateCall(token_pos(), | 1059 compiler->GenerateCall(token_pos(), |
| 1068 &StubCode::AllocateArrayLabel(), | 1060 &StubCode::AllocateArrayLabel(), |
| 1069 PcDescriptors::kOther, | 1061 PcDescriptors::kOther, |
| 1070 locs()); | 1062 locs()); |
| 1071 ASSERT(locs()->out().reg() == EAX); | 1063 ASSERT(locs()->out().reg() == EAX); |
| 1072 | 1064 |
| 1073 // Pop the element values from the stack into the array. | 1065 // Pop the element values from the stack into the array. |
| 1074 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); | 1066 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); |
| 1075 for (int i = ArgumentCount() - 1; i >= 0; --i) { | 1067 for (int i = ArgumentCount() - 1; i >= 0; --i) { |
| 1076 __ popl(Address(EDX, i * kWordSize)); | 1068 __ popl(Address(EDX, i * kWordSize)); |
| 1077 } | 1069 } |
| 1078 } | 1070 } |
| 1079 | 1071 |
| 1080 | 1072 |
| 1081 LocationSummary* | 1073 LocationSummary* |
| 1082 AllocateObjectWithBoundsCheckComp::MakeLocationSummary() const { | 1074 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { |
| 1083 const intptr_t kNumInputs = 2; | 1075 const intptr_t kNumInputs = 2; |
| 1084 const intptr_t kNumTemps = 0; | 1076 const intptr_t kNumTemps = 0; |
| 1085 LocationSummary* locs = | 1077 LocationSummary* locs = |
| 1086 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1078 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1087 locs->set_in(0, Location::RegisterLocation(EAX)); | 1079 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 1088 locs->set_in(1, Location::RegisterLocation(ECX)); | 1080 locs->set_in(1, Location::RegisterLocation(ECX)); |
| 1089 locs->set_out(Location::RegisterLocation(EAX)); | 1081 locs->set_out(Location::RegisterLocation(EAX)); |
| 1090 return locs; | 1082 return locs; |
| 1091 } | 1083 } |
| 1092 | 1084 |
| 1093 | 1085 |
| 1094 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 1086 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( |
| 1095 FlowGraphCompiler* compiler) { | 1087 FlowGraphCompiler* compiler) { |
| 1096 const Class& cls = Class::ZoneHandle(constructor().Owner()); | 1088 const Class& cls = Class::ZoneHandle(constructor().Owner()); |
| 1097 Register type_arguments = locs()->in(0).reg(); | 1089 Register type_arguments = locs()->in(0).reg(); |
| 1098 Register instantiator_type_arguments = locs()->in(1).reg(); | 1090 Register instantiator_type_arguments = locs()->in(1).reg(); |
| 1099 Register result = locs()->out().reg(); | 1091 Register result = locs()->out().reg(); |
| 1100 | 1092 |
| 1101 // Push the result place holder initialized to NULL. | 1093 // Push the result place holder initialized to NULL. |
| 1102 __ PushObject(Object::ZoneHandle()); | 1094 __ PushObject(Object::ZoneHandle()); |
| 1103 __ PushObject(cls); | 1095 __ PushObject(cls); |
| 1104 __ pushl(type_arguments); | 1096 __ pushl(type_arguments); |
| 1105 __ pushl(instantiator_type_arguments); | 1097 __ pushl(instantiator_type_arguments); |
| 1106 compiler->GenerateCallRuntime(token_pos(), | 1098 compiler->GenerateCallRuntime(token_pos(), |
| 1107 kAllocateObjectWithBoundsCheckRuntimeEntry, | 1099 kAllocateObjectWithBoundsCheckRuntimeEntry, |
| 1108 locs()); | 1100 locs()); |
| 1109 // Pop instantiator type arguments, type arguments, and class. | 1101 // Pop instantiator type arguments, type arguments, and class. |
| 1110 // source location. | 1102 // source location. |
| 1111 __ Drop(3); | 1103 __ Drop(3); |
| 1112 __ popl(result); // Pop new instance. | 1104 __ popl(result); // Pop new instance. |
| 1113 } | 1105 } |
| 1114 | 1106 |
| 1115 | 1107 |
| 1116 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1108 LocationSummary* LoadVMFieldInstr::MakeLocationSummary() const { |
| 1117 return LocationSummary::Make(1, | 1109 return LocationSummary::Make(1, |
| 1118 Location::RequiresRegister(), | 1110 Location::RequiresRegister(), |
| 1119 LocationSummary::kNoCall); | 1111 LocationSummary::kNoCall); |
| 1120 } | 1112 } |
| 1121 | 1113 |
| 1122 | 1114 |
| 1123 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1115 void LoadVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1124 Register instance_reg = locs()->in(0).reg(); | 1116 Register instance_reg = locs()->in(0).reg(); |
| 1125 Register result_reg = locs()->out().reg(); | 1117 Register result_reg = locs()->out().reg(); |
| 1126 | 1118 |
| 1127 __ movl(result_reg, FieldAddress(instance_reg, offset_in_bytes())); | 1119 __ movl(result_reg, FieldAddress(instance_reg, offset_in_bytes())); |
| 1128 } | 1120 } |
| 1129 | 1121 |
| 1130 | 1122 |
| 1131 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { | 1123 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const { |
| 1132 const intptr_t kNumInputs = 1; | 1124 const intptr_t kNumInputs = 1; |
| 1133 const intptr_t kNumTemps = 1; | 1125 const intptr_t kNumTemps = 1; |
| 1134 LocationSummary* locs = | 1126 LocationSummary* locs = |
| 1135 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1127 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1136 locs->set_in(0, Location::RegisterLocation(EAX)); | 1128 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 1137 locs->set_temp(0, Location::RegisterLocation(ECX)); | 1129 locs->set_temp(0, Location::RegisterLocation(ECX)); |
| 1138 locs->set_out(Location::RegisterLocation(EAX)); | 1130 locs->set_out(Location::RegisterLocation(EAX)); |
| 1139 return locs; | 1131 return locs; |
| 1140 } | 1132 } |
| 1141 | 1133 |
| 1142 | 1134 |
| 1143 void InstantiateTypeArgumentsComp::EmitNativeCode( | 1135 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 1144 FlowGraphCompiler* compiler) { | 1136 FlowGraphCompiler* compiler) { |
| 1145 Register instantiator_reg = locs()->in(0).reg(); | 1137 Register instantiator_reg = locs()->in(0).reg(); |
| 1146 Register temp = locs()->temp(0).reg(); | 1138 Register temp = locs()->temp(0).reg(); |
| 1147 Register result_reg = locs()->out().reg(); | 1139 Register result_reg = locs()->out().reg(); |
| 1148 | 1140 |
| 1149 // 'instantiator_reg' is the instantiator AbstractTypeArguments object | 1141 // 'instantiator_reg' is the instantiator AbstractTypeArguments object |
| 1150 // (or null). | 1142 // (or null). |
| 1151 // If the instantiator is null and if the type argument vector | 1143 // If the instantiator is null and if the type argument vector |
| 1152 // instantiated from null becomes a vector of Dynamic, then use null as | 1144 // instantiated from null becomes a vector of Dynamic, then use null as |
| 1153 // the type arguments. | 1145 // the type arguments. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1183 locs()); | 1175 locs()); |
| 1184 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1176 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1185 __ popl(result_reg); // Pop instantiated type arguments. | 1177 __ popl(result_reg); // Pop instantiated type arguments. |
| 1186 __ Bind(&type_arguments_instantiated); | 1178 __ Bind(&type_arguments_instantiated); |
| 1187 ASSERT(instantiator_reg == result_reg); | 1179 ASSERT(instantiator_reg == result_reg); |
| 1188 // 'result_reg': Instantiated type arguments. | 1180 // 'result_reg': Instantiated type arguments. |
| 1189 } | 1181 } |
| 1190 | 1182 |
| 1191 | 1183 |
| 1192 LocationSummary* | 1184 LocationSummary* |
| 1193 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { | 1185 ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const { |
| 1194 const intptr_t kNumInputs = 1; | 1186 const intptr_t kNumInputs = 1; |
| 1195 const intptr_t kNumTemps = 1; | 1187 const intptr_t kNumTemps = 1; |
| 1196 LocationSummary* locs = | 1188 LocationSummary* locs = |
| 1197 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1189 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1198 locs->set_in(0, Location::RequiresRegister()); | 1190 locs->set_in(0, Location::RequiresRegister()); |
| 1199 locs->set_out(Location::SameAsFirstInput()); | 1191 locs->set_out(Location::SameAsFirstInput()); |
| 1200 locs->set_temp(0, Location::RequiresRegister()); | 1192 locs->set_temp(0, Location::RequiresRegister()); |
| 1201 return locs; | 1193 return locs; |
| 1202 } | 1194 } |
| 1203 | 1195 |
| 1204 | 1196 |
| 1205 void ExtractConstructorTypeArgumentsComp::EmitNativeCode( | 1197 void ExtractConstructorTypeArgumentsInstr::EmitNativeCode( |
| 1206 FlowGraphCompiler* compiler) { | 1198 FlowGraphCompiler* compiler) { |
| 1207 Register instantiator_reg = locs()->in(0).reg(); | 1199 Register instantiator_reg = locs()->in(0).reg(); |
| 1208 Register result_reg = locs()->out().reg(); | 1200 Register result_reg = locs()->out().reg(); |
| 1209 ASSERT(instantiator_reg == result_reg); | 1201 ASSERT(instantiator_reg == result_reg); |
| 1210 Register temp_reg = locs()->temp(0).reg(); | 1202 Register temp_reg = locs()->temp(0).reg(); |
| 1211 | 1203 |
| 1212 // instantiator_reg is the instantiator type argument vector, i.e. an | 1204 // instantiator_reg is the instantiator type argument vector, i.e. an |
| 1213 // AbstractTypeArguments object (or null). | 1205 // AbstractTypeArguments object (or null). |
| 1214 // If the instantiator is null and if the type argument vector | 1206 // If the instantiator is null and if the type argument vector |
| 1215 // instantiated from null becomes a vector of Dynamic, then use null as | 1207 // instantiated from null becomes a vector of Dynamic, then use null as |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1241 // In the non-factory case, we rely on the allocation stub to | 1233 // In the non-factory case, we rely on the allocation stub to |
| 1242 // instantiate the type arguments. | 1234 // instantiate the type arguments. |
| 1243 __ LoadObject(result_reg, type_arguments()); | 1235 __ LoadObject(result_reg, type_arguments()); |
| 1244 // result_reg: uninstantiated type arguments. | 1236 // result_reg: uninstantiated type arguments. |
| 1245 __ Bind(&type_arguments_instantiated); | 1237 __ Bind(&type_arguments_instantiated); |
| 1246 // result_reg: uninstantiated or instantiated type arguments. | 1238 // result_reg: uninstantiated or instantiated type arguments. |
| 1247 } | 1239 } |
| 1248 | 1240 |
| 1249 | 1241 |
| 1250 LocationSummary* | 1242 LocationSummary* |
| 1251 ExtractConstructorInstantiatorComp::MakeLocationSummary() const { | 1243 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { |
| 1252 const intptr_t kNumInputs = 1; | 1244 const intptr_t kNumInputs = 1; |
| 1253 const intptr_t kNumTemps = 1; | 1245 const intptr_t kNumTemps = 1; |
| 1254 LocationSummary* locs = | 1246 LocationSummary* locs = |
| 1255 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1247 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1256 locs->set_in(0, Location::RequiresRegister()); | 1248 locs->set_in(0, Location::RequiresRegister()); |
| 1257 locs->set_out(Location::SameAsFirstInput()); | 1249 locs->set_out(Location::SameAsFirstInput()); |
| 1258 locs->set_temp(0, Location::RequiresRegister()); | 1250 locs->set_temp(0, Location::RequiresRegister()); |
| 1259 return locs; | 1251 return locs; |
| 1260 } | 1252 } |
| 1261 | 1253 |
| 1262 | 1254 |
| 1263 void ExtractConstructorInstantiatorComp::EmitNativeCode( | 1255 void ExtractConstructorInstantiatorInstr::EmitNativeCode( |
| 1264 FlowGraphCompiler* compiler) { | 1256 FlowGraphCompiler* compiler) { |
| 1265 Register instantiator_reg = locs()->in(0).reg(); | 1257 Register instantiator_reg = locs()->in(0).reg(); |
| 1266 ASSERT(locs()->out().reg() == instantiator_reg); | 1258 ASSERT(locs()->out().reg() == instantiator_reg); |
| 1267 Register temp_reg = locs()->temp(0).reg(); | 1259 Register temp_reg = locs()->temp(0).reg(); |
| 1268 | 1260 |
| 1269 // instantiator_reg is the instantiator AbstractTypeArguments object | 1261 // instantiator_reg is the instantiator AbstractTypeArguments object |
| 1270 // (or null). If the instantiator is null and if the type argument vector | 1262 // (or null). If the instantiator is null and if the type argument vector |
| 1271 // instantiated from null becomes a vector of Dynamic, then use null as | 1263 // instantiated from null becomes a vector of Dynamic, then use null as |
| 1272 // the type arguments and do not pass the instantiator. | 1264 // the type arguments and do not pass the instantiator. |
| 1273 Label done; | 1265 Label done; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1307 // The instantiator was used in VisitExtractConstructorTypeArguments as the | 1299 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
| 1308 // instantiated type arguments, no proper instantiator needed. | 1300 // instantiated type arguments, no proper instantiator needed. |
| 1309 __ movl(instantiator_reg, | 1301 __ movl(instantiator_reg, |
| 1310 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1302 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 1311 } | 1303 } |
| 1312 __ Bind(&done); | 1304 __ Bind(&done); |
| 1313 // instantiator_reg: instantiator or kNoInstantiator. | 1305 // instantiator_reg: instantiator or kNoInstantiator. |
| 1314 } | 1306 } |
| 1315 | 1307 |
| 1316 | 1308 |
| 1317 LocationSummary* AllocateContextComp::MakeLocationSummary() const { | 1309 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { |
| 1318 const intptr_t kNumInputs = 0; | 1310 const intptr_t kNumInputs = 0; |
| 1319 const intptr_t kNumTemps = 1; | 1311 const intptr_t kNumTemps = 1; |
| 1320 LocationSummary* locs = | 1312 LocationSummary* locs = |
| 1321 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1313 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1322 locs->set_temp(0, Location::RegisterLocation(EDX)); | 1314 locs->set_temp(0, Location::RegisterLocation(EDX)); |
| 1323 locs->set_out(Location::RegisterLocation(EAX)); | 1315 locs->set_out(Location::RegisterLocation(EAX)); |
| 1324 return locs; | 1316 return locs; |
| 1325 } | 1317 } |
| 1326 | 1318 |
| 1327 | 1319 |
| 1328 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1320 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1329 ASSERT(locs()->temp(0).reg() == EDX); | 1321 ASSERT(locs()->temp(0).reg() == EDX); |
| 1330 ASSERT(locs()->out().reg() == EAX); | 1322 ASSERT(locs()->out().reg() == EAX); |
| 1331 | 1323 |
| 1332 __ movl(EDX, Immediate(num_context_variables())); | 1324 __ movl(EDX, Immediate(num_context_variables())); |
| 1333 const ExternalLabel label("alloc_context", | 1325 const ExternalLabel label("alloc_context", |
| 1334 StubCode::AllocateContextEntryPoint()); | 1326 StubCode::AllocateContextEntryPoint()); |
| 1335 compiler->GenerateCall(token_pos(), | 1327 compiler->GenerateCall(token_pos(), |
| 1336 &label, | 1328 &label, |
| 1337 PcDescriptors::kOther, | 1329 PcDescriptors::kOther, |
| 1338 locs()); | 1330 locs()); |
| 1339 } | 1331 } |
| 1340 | 1332 |
| 1341 | 1333 |
| 1342 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1334 LocationSummary* CloneContextInstr::MakeLocationSummary() const { |
| 1343 const intptr_t kNumInputs = 1; | 1335 const intptr_t kNumInputs = 1; |
| 1344 const intptr_t kNumTemps = 0; | 1336 const intptr_t kNumTemps = 0; |
| 1345 LocationSummary* locs = | 1337 LocationSummary* locs = |
| 1346 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1338 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1347 locs->set_in(0, Location::RegisterLocation(EAX)); | 1339 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 1348 locs->set_out(Location::RegisterLocation(EAX)); | 1340 locs->set_out(Location::RegisterLocation(EAX)); |
| 1349 return locs; | 1341 return locs; |
| 1350 } | 1342 } |
| 1351 | 1343 |
| 1352 | 1344 |
| 1353 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1345 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1354 Register context_value = locs()->in(0).reg(); | 1346 Register context_value = locs()->in(0).reg(); |
| 1355 Register result = locs()->out().reg(); | 1347 Register result = locs()->out().reg(); |
| 1356 | 1348 |
| 1357 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1349 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1358 __ pushl(context_value); | 1350 __ pushl(context_value); |
| 1359 compiler->GenerateCallRuntime(token_pos(), | 1351 compiler->GenerateCallRuntime(token_pos(), |
| 1360 kCloneContextRuntimeEntry, | 1352 kCloneContextRuntimeEntry, |
| 1361 locs()); | 1353 locs()); |
| 1362 __ popl(result); // Remove argument. | 1354 __ popl(result); // Remove argument. |
| 1363 __ popl(result); // Get result (cloned context). | 1355 __ popl(result); // Get result (cloned context). |
| 1364 } | 1356 } |
| 1365 | 1357 |
| 1366 | 1358 |
| 1367 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1359 LocationSummary* CatchEntryInstr::MakeLocationSummary() const { |
| 1368 return LocationSummary::Make(0, | 1360 return LocationSummary::Make(0, |
| 1369 Location::NoLocation(), | 1361 Location::NoLocation(), |
| 1370 LocationSummary::kNoCall); | 1362 LocationSummary::kNoCall); |
| 1371 } | 1363 } |
| 1372 | 1364 |
| 1373 | 1365 |
| 1374 // Restore stack and initialize the two exception variables: | 1366 // Restore stack and initialize the two exception variables: |
| 1375 // exception and stack trace variables. | 1367 // exception and stack trace variables. |
| 1376 void CatchEntryComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1368 void CatchEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1377 // Restore RSP from RBP as we are coming from a throw and the code for | 1369 // Restore RSP from RBP as we are coming from a throw and the code for |
| 1378 // popping arguments has not been run. | 1370 // popping arguments has not been run. |
| 1379 const intptr_t locals_space_size = compiler->StackSize() * kWordSize; | 1371 const intptr_t locals_space_size = compiler->StackSize() * kWordSize; |
| 1380 ASSERT(locals_space_size >= 0); | 1372 ASSERT(locals_space_size >= 0); |
| 1381 const intptr_t offset_size = | 1373 const intptr_t offset_size = |
| 1382 -locals_space_size + FlowGraphCompiler::kLocalsOffsetFromFP; | 1374 -locals_space_size + FlowGraphCompiler::kLocalsOffsetFromFP; |
| 1383 __ leal(ESP, Address(EBP, offset_size)); | 1375 __ leal(ESP, Address(EBP, offset_size)); |
| 1384 | 1376 |
| 1385 ASSERT(!exception_var().is_captured()); | 1377 ASSERT(!exception_var().is_captured()); |
| 1386 ASSERT(!stacktrace_var().is_captured()); | 1378 ASSERT(!stacktrace_var().is_captured()); |
| 1387 __ movl(Address(EBP, exception_var().index() * kWordSize), | 1379 __ movl(Address(EBP, exception_var().index() * kWordSize), |
| 1388 kExceptionObjectReg); | 1380 kExceptionObjectReg); |
| 1389 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), | 1381 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), |
| 1390 kStackTraceObjectReg); | 1382 kStackTraceObjectReg); |
| 1391 } | 1383 } |
| 1392 | 1384 |
| 1393 | 1385 |
| 1394 LocationSummary* CheckStackOverflowComp::MakeLocationSummary() const { | 1386 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const { |
| 1395 const intptr_t kNumInputs = 0; | 1387 const intptr_t kNumInputs = 0; |
| 1396 const intptr_t kNumTemps = 0; | 1388 const intptr_t kNumTemps = 0; |
| 1397 LocationSummary* summary = | 1389 LocationSummary* summary = |
| 1398 new LocationSummary(kNumInputs, | 1390 new LocationSummary(kNumInputs, |
| 1399 kNumTemps, | 1391 kNumTemps, |
| 1400 LocationSummary::kCallOnSlowPath); | 1392 LocationSummary::kCallOnSlowPath); |
| 1401 return summary; | 1393 return summary; |
| 1402 } | 1394 } |
| 1403 | 1395 |
| 1404 | 1396 |
| 1405 class CheckStackOverflowSlowPath : public SlowPathCode { | 1397 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 1406 public: | 1398 public: |
| 1407 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) | 1399 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 1408 : computation_(computation) { } | 1400 : instruction_(instruction) { } |
| 1409 | 1401 |
| 1410 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1402 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1411 __ Bind(entry_label()); | 1403 __ Bind(entry_label()); |
| 1412 compiler->SaveLiveRegisters(computation_->locs()); | 1404 compiler->SaveLiveRegisters(instruction_->locs()); |
| 1413 compiler->GenerateCallRuntime(computation_->token_pos(), | 1405 compiler->GenerateCallRuntime(instruction_->token_pos(), |
| 1414 kStackOverflowRuntimeEntry, | 1406 kStackOverflowRuntimeEntry, |
| 1415 computation_->locs()); | 1407 instruction_->locs()); |
| 1416 compiler->RestoreLiveRegisters(computation_->locs()); | 1408 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 1417 __ jmp(exit_label()); | 1409 __ jmp(exit_label()); |
| 1418 } | 1410 } |
| 1419 | 1411 |
| 1420 private: | 1412 private: |
| 1421 CheckStackOverflowComp* computation_; | 1413 CheckStackOverflowInstr* instruction_; |
| 1422 }; | 1414 }; |
| 1423 | 1415 |
| 1424 | 1416 |
| 1425 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1417 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1426 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 1418 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 1427 compiler->AddSlowPathCode(slow_path); | 1419 compiler->AddSlowPathCode(slow_path); |
| 1428 | 1420 |
| 1429 __ cmpl(ESP, | 1421 __ cmpl(ESP, |
| 1430 Address::Absolute(Isolate::Current()->stack_limit_address())); | 1422 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 1431 __ j(BELOW_EQUAL, slow_path->entry_label()); | 1423 __ j(BELOW_EQUAL, slow_path->entry_label()); |
| 1432 __ Bind(slow_path->exit_label()); | 1424 __ Bind(slow_path->exit_label()); |
| 1433 } | 1425 } |
| 1434 | 1426 |
| 1435 | 1427 |
| 1436 LocationSummary* BinarySmiOpComp::MakeLocationSummary() const { | 1428 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { |
| 1437 const intptr_t kNumInputs = 2; | 1429 const intptr_t kNumInputs = 2; |
| 1438 if (op_kind() == Token::kTRUNCDIV) { | 1430 if (op_kind() == Token::kTRUNCDIV) { |
| 1439 const intptr_t kNumTemps = 3; | 1431 const intptr_t kNumTemps = 3; |
| 1440 LocationSummary* summary = | 1432 LocationSummary* summary = |
| 1441 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1433 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1442 summary->set_in(0, Location::RegisterLocation(EAX)); | 1434 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 1443 summary->set_in(1, Location::RegisterLocation(ECX)); | 1435 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 1444 summary->set_out(Location::SameAsFirstInput()); | 1436 summary->set_out(Location::SameAsFirstInput()); |
| 1445 summary->set_temp(0, Location::RegisterLocation(EBX)); | 1437 summary->set_temp(0, Location::RegisterLocation(EBX)); |
| 1446 // Will be used for for sign extension. | 1438 // Will be used for for sign extension. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1471 LocationSummary* summary = | 1463 LocationSummary* summary = |
| 1472 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1464 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1473 summary->set_in(0, Location::RequiresRegister()); | 1465 summary->set_in(0, Location::RequiresRegister()); |
| 1474 summary->set_in(1, Location::RegisterOrConstant(right())); | 1466 summary->set_in(1, Location::RegisterOrConstant(right())); |
| 1475 summary->set_out(Location::SameAsFirstInput()); | 1467 summary->set_out(Location::SameAsFirstInput()); |
| 1476 return summary; | 1468 return summary; |
| 1477 } | 1469 } |
| 1478 } | 1470 } |
| 1479 | 1471 |
| 1480 | 1472 |
| 1481 void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1473 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1482 Register left = locs()->in(0).reg(); | 1474 Register left = locs()->in(0).reg(); |
| 1483 Register result = locs()->out().reg(); | 1475 Register result = locs()->out().reg(); |
| 1484 ASSERT(left == result); | 1476 ASSERT(left == result); |
| 1485 Label* deopt = NULL; | 1477 Label* deopt = NULL; |
| 1486 switch (op_kind()) { | 1478 switch (op_kind()) { |
| 1487 case Token::kBIT_AND: | 1479 case Token::kBIT_AND: |
| 1488 case Token::kBIT_OR: | 1480 case Token::kBIT_OR: |
| 1489 case Token::kBIT_XOR: | 1481 case Token::kBIT_XOR: |
| 1490 // Can't deoptimize. Arguments are already checked for smi. | 1482 // Can't deoptimize. Arguments are already checked for smi. |
| 1491 break; | 1483 break; |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1692 UNREACHABLE(); | 1684 UNREACHABLE(); |
| 1693 break; | 1685 break; |
| 1694 } | 1686 } |
| 1695 default: | 1687 default: |
| 1696 UNREACHABLE(); | 1688 UNREACHABLE(); |
| 1697 break; | 1689 break; |
| 1698 } | 1690 } |
| 1699 } | 1691 } |
| 1700 | 1692 |
| 1701 | 1693 |
| 1702 LocationSummary* BinaryMintOpComp::MakeLocationSummary() const { | 1694 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { |
| 1703 const intptr_t kNumInputs = 2; | 1695 const intptr_t kNumInputs = 2; |
| 1704 ASSERT(op_kind() == Token::kBIT_AND); | 1696 ASSERT(op_kind() == Token::kBIT_AND); |
| 1705 const intptr_t kNumTemps = 1; | 1697 const intptr_t kNumTemps = 1; |
| 1706 LocationSummary* summary = | 1698 LocationSummary* summary = |
| 1707 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1699 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1708 summary->set_in(0, Location::RegisterLocation(EAX)); | 1700 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 1709 summary->set_in(1, Location::RegisterLocation(ECX)); | 1701 summary->set_in(1, Location::RegisterLocation(ECX)); |
| 1710 summary->set_temp(0, Location::RegisterLocation(EDX)); | 1702 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 1711 summary->set_out(Location::RegisterLocation(EAX)); | 1703 summary->set_out(Location::RegisterLocation(EAX)); |
| 1712 return summary; | 1704 return summary; |
| 1713 } | 1705 } |
| 1714 | 1706 |
| 1715 | 1707 |
| 1716 void BinaryMintOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1708 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1717 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1709 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1718 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1710 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1719 // both receiver and argument are Mint or if one of them is Mint and the other | 1711 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1720 // is a negative Smi. | 1712 // is a negative Smi. |
| 1721 Register left = locs()->in(0).reg(); | 1713 Register left = locs()->in(0).reg(); |
| 1722 Register right = locs()->in(1).reg(); | 1714 Register right = locs()->in(1).reg(); |
| 1723 Register result = locs()->out().reg(); | 1715 Register result = locs()->out().reg(); |
| 1724 Register temp = locs()->temp(0).reg(); | 1716 Register temp = locs()->temp(0).reg(); |
| 1725 ASSERT(left == result); | 1717 ASSERT(left == result); |
| 1726 ASSERT(op_kind() == Token::kBIT_AND); | 1718 ASSERT(op_kind() == Token::kBIT_AND); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1796 instance_call()->ArgumentCount(), | 1788 instance_call()->ArgumentCount(), |
| 1797 instance_call()->argument_names(), | 1789 instance_call()->argument_names(), |
| 1798 locs()); | 1790 locs()); |
| 1799 ASSERT(result == EAX); | 1791 ASSERT(result == EAX); |
| 1800 } | 1792 } |
| 1801 } | 1793 } |
| 1802 __ Bind(&done); | 1794 __ Bind(&done); |
| 1803 } | 1795 } |
| 1804 | 1796 |
| 1805 | 1797 |
| 1806 LocationSummary* CheckEitherNonSmiComp::MakeLocationSummary() const { | 1798 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { |
| 1807 ASSERT((left()->ResultCid() != kDoubleCid) && | 1799 ASSERT((left()->ResultCid() != kDoubleCid) && |
| 1808 (right()->ResultCid() != kDoubleCid)); | 1800 (right()->ResultCid() != kDoubleCid)); |
| 1809 const intptr_t kNumInputs = 2; | 1801 const intptr_t kNumInputs = 2; |
| 1810 const intptr_t kNumTemps = 1; | 1802 const intptr_t kNumTemps = 1; |
| 1811 LocationSummary* summary = | 1803 LocationSummary* summary = |
| 1812 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1804 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1813 summary->set_in(0, Location::RequiresRegister()); | 1805 summary->set_in(0, Location::RequiresRegister()); |
| 1814 summary->set_in(1, Location::RequiresRegister()); | 1806 summary->set_in(1, Location::RequiresRegister()); |
| 1815 summary->set_temp(0, Location::RequiresRegister()); | 1807 summary->set_temp(0, Location::RequiresRegister()); |
| 1816 return summary; | 1808 return summary; |
| 1817 } | 1809 } |
| 1818 | 1810 |
| 1819 | 1811 |
| 1820 void CheckEitherNonSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1812 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1821 Label* deopt = compiler->AddDeoptStub(instance_call_->deopt_id(), | 1813 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp); |
| 1822 kDeoptBinaryDoubleOp); | |
| 1823 | |
| 1824 Register temp = locs()->temp(0).reg(); | 1814 Register temp = locs()->temp(0).reg(); |
| 1825 __ movl(temp, locs()->in(0).reg()); | 1815 __ movl(temp, locs()->in(0).reg()); |
| 1826 __ orl(temp, locs()->in(1).reg()); | 1816 __ orl(temp, locs()->in(1).reg()); |
| 1827 __ testl(temp, Immediate(kSmiTagMask)); | 1817 __ testl(temp, Immediate(kSmiTagMask)); |
| 1828 __ j(ZERO, deopt); | 1818 __ j(ZERO, deopt); |
| 1829 } | 1819 } |
| 1830 | 1820 |
| 1831 | 1821 |
| 1832 LocationSummary* BoxDoubleComp::MakeLocationSummary() const { | 1822 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { |
| 1833 const intptr_t kNumInputs = 1; | 1823 const intptr_t kNumInputs = 1; |
| 1834 const intptr_t kNumTemps = 0; | 1824 const intptr_t kNumTemps = 0; |
| 1835 LocationSummary* summary = | 1825 LocationSummary* summary = |
| 1836 new LocationSummary(kNumInputs, | 1826 new LocationSummary(kNumInputs, |
| 1837 kNumTemps, | 1827 kNumTemps, |
| 1838 LocationSummary::kCallOnSlowPath); | 1828 LocationSummary::kCallOnSlowPath); |
| 1839 summary->set_in(0, Location::RequiresXmmRegister()); | 1829 summary->set_in(0, Location::RequiresXmmRegister()); |
| 1840 summary->set_out(Location::RequiresRegister()); | 1830 summary->set_out(Location::RequiresRegister()); |
| 1841 return summary; | 1831 return summary; |
| 1842 } | 1832 } |
| 1843 | 1833 |
| 1844 | 1834 |
| 1845 class BoxDoubleSlowPath : public SlowPathCode { | 1835 class BoxDoubleSlowPath : public SlowPathCode { |
| 1846 public: | 1836 public: |
| 1847 explicit BoxDoubleSlowPath(BoxDoubleComp* computation) | 1837 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) |
| 1848 : computation_(computation) { } | 1838 : instruction_(instruction) { } |
| 1849 | 1839 |
| 1850 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1840 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1851 __ Bind(entry_label()); | 1841 __ Bind(entry_label()); |
| 1852 const Class& double_class = compiler->double_class(); | 1842 const Class& double_class = compiler->double_class(); |
| 1853 const Code& stub = | 1843 const Code& stub = |
| 1854 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1844 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1855 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1845 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1856 | 1846 |
| 1857 LocationSummary* locs = computation_->locs(); | 1847 LocationSummary* locs = instruction_->locs(); |
| 1858 locs->live_registers()->Remove(locs->out()); | 1848 locs->live_registers()->Remove(locs->out()); |
| 1859 | 1849 |
| 1860 compiler->SaveLiveRegisters(locs); | 1850 compiler->SaveLiveRegisters(locs); |
| 1861 compiler->GenerateCall(computation_->token_pos(), | 1851 compiler->GenerateCall(instruction_->token_pos(), |
| 1862 &label, | 1852 &label, |
| 1863 PcDescriptors::kOther, | 1853 PcDescriptors::kOther, |
| 1864 locs); | 1854 locs); |
| 1865 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX); | 1855 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX); |
| 1866 compiler->RestoreLiveRegisters(locs); | 1856 compiler->RestoreLiveRegisters(locs); |
| 1867 | 1857 |
| 1868 __ jmp(exit_label()); | 1858 __ jmp(exit_label()); |
| 1869 } | 1859 } |
| 1870 | 1860 |
| 1871 private: | 1861 private: |
| 1872 BoxDoubleComp* computation_; | 1862 BoxDoubleInstr* instruction_; |
| 1873 }; | 1863 }; |
| 1874 | 1864 |
| 1875 | 1865 |
| 1876 void BoxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1866 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1877 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 1867 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
| 1878 compiler->AddSlowPathCode(slow_path); | 1868 compiler->AddSlowPathCode(slow_path); |
| 1879 | 1869 |
| 1880 Register out_reg = locs()->out().reg(); | 1870 Register out_reg = locs()->out().reg(); |
| 1881 XmmRegister value = locs()->in(0).xmm_reg(); | 1871 XmmRegister value = locs()->in(0).xmm_reg(); |
| 1882 | 1872 |
| 1883 AssemblerMacros::TryAllocate(compiler->assembler(), | 1873 AssemblerMacros::TryAllocate(compiler->assembler(), |
| 1884 compiler->double_class(), | 1874 compiler->double_class(), |
| 1885 slow_path->entry_label(), | 1875 slow_path->entry_label(), |
| 1886 Assembler::kFarJump, | 1876 Assembler::kFarJump, |
| 1887 out_reg); | 1877 out_reg); |
| 1888 __ Bind(slow_path->exit_label()); | 1878 __ Bind(slow_path->exit_label()); |
| 1889 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 1879 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
| 1890 } | 1880 } |
| 1891 | 1881 |
| 1892 | 1882 |
| 1893 LocationSummary* UnboxDoubleComp::MakeLocationSummary() const { | 1883 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { |
| 1894 const intptr_t v_cid = value()->ResultCid(); | 1884 const intptr_t v_cid = value()->ResultCid(); |
| 1895 | 1885 |
| 1896 const intptr_t kNumInputs = 1; | 1886 const intptr_t kNumInputs = 1; |
| 1897 const intptr_t kNumTemps = (v_cid != kDoubleCid) ? 1 : 0; | 1887 const intptr_t kNumTemps = (v_cid != kDoubleCid) ? 1 : 0; |
| 1898 LocationSummary* summary = | 1888 LocationSummary* summary = |
| 1899 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1889 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1900 summary->set_in(0, Location::RequiresRegister()); | 1890 summary->set_in(0, Location::RequiresRegister()); |
| 1901 if (v_cid != kDoubleCid) summary->set_temp(0, Location::RequiresRegister()); | 1891 if (v_cid != kDoubleCid) summary->set_temp(0, Location::RequiresRegister()); |
| 1902 summary->set_out(Location::RequiresXmmRegister()); | 1892 summary->set_out(Location::RequiresXmmRegister()); |
| 1903 return summary; | 1893 return summary; |
| 1904 } | 1894 } |
| 1905 | 1895 |
| 1906 | 1896 |
| 1907 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1897 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1908 const intptr_t v_cid = value()->ResultCid(); | 1898 const intptr_t v_cid = value()->ResultCid(); |
| 1909 | 1899 |
| 1910 const Register value = locs()->in(0).reg(); | 1900 const Register value = locs()->in(0).reg(); |
| 1911 const XmmRegister result = locs()->out().xmm_reg(); | 1901 const XmmRegister result = locs()->out().xmm_reg(); |
| 1912 if (v_cid != kDoubleCid) { | 1902 if (v_cid != kDoubleCid) { |
| 1913 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 1903 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
| 1914 compiler->LoadDoubleOrSmiToXmm(result, | 1904 compiler->LoadDoubleOrSmiToXmm(result, |
| 1915 value, | 1905 value, |
| 1916 locs()->temp(0).reg(), | 1906 locs()->temp(0).reg(), |
| 1917 deopt); | 1907 deopt); |
| 1918 } else { | 1908 } else { |
| 1919 __ movsd(result, FieldAddress(value, Double::value_offset())); | 1909 __ movsd(result, FieldAddress(value, Double::value_offset())); |
| 1920 } | 1910 } |
| 1921 } | 1911 } |
| 1922 | 1912 |
| 1923 | 1913 |
| 1924 LocationSummary* UnboxedDoubleBinaryOpComp::MakeLocationSummary() const { | 1914 LocationSummary* UnboxedDoubleBinaryOpInstr::MakeLocationSummary() const { |
| 1925 const intptr_t kNumInputs = 2; | 1915 const intptr_t kNumInputs = 2; |
| 1926 const intptr_t kNumTemps = 0; | 1916 const intptr_t kNumTemps = 0; |
| 1927 LocationSummary* summary = | 1917 LocationSummary* summary = |
| 1928 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1918 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1929 summary->set_in(0, Location::RequiresXmmRegister()); | 1919 summary->set_in(0, Location::RequiresXmmRegister()); |
| 1930 summary->set_in(1, Location::RequiresXmmRegister()); | 1920 summary->set_in(1, Location::RequiresXmmRegister()); |
| 1931 summary->set_out(Location::SameAsFirstInput()); | 1921 summary->set_out(Location::SameAsFirstInput()); |
| 1932 return summary; | 1922 return summary; |
| 1933 } | 1923 } |
| 1934 | 1924 |
| 1935 | 1925 |
| 1936 void UnboxedDoubleBinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1926 void UnboxedDoubleBinaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1937 XmmRegister left = locs()->in(0).xmm_reg(); | 1927 XmmRegister left = locs()->in(0).xmm_reg(); |
| 1938 XmmRegister right = locs()->in(1).xmm_reg(); | 1928 XmmRegister right = locs()->in(1).xmm_reg(); |
| 1939 | 1929 |
| 1940 ASSERT(locs()->out().xmm_reg() == left); | 1930 ASSERT(locs()->out().xmm_reg() == left); |
| 1941 | 1931 |
| 1942 switch (op_kind()) { | 1932 switch (op_kind()) { |
| 1943 case Token::kADD: __ addsd(left, right); break; | 1933 case Token::kADD: __ addsd(left, right); break; |
| 1944 case Token::kSUB: __ subsd(left, right); break; | 1934 case Token::kSUB: __ subsd(left, right); break; |
| 1945 case Token::kMUL: __ mulsd(left, right); break; | 1935 case Token::kMUL: __ mulsd(left, right); break; |
| 1946 case Token::kDIV: __ divsd(left, right); break; | 1936 case Token::kDIV: __ divsd(left, right); break; |
| 1947 default: UNREACHABLE(); | 1937 default: UNREACHABLE(); |
| 1948 } | 1938 } |
| 1949 } | 1939 } |
| 1950 | 1940 |
| 1951 | 1941 |
| 1952 LocationSummary* UnarySmiOpComp::MakeLocationSummary() const { | 1942 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { |
| 1953 const intptr_t kNumInputs = 1; | 1943 const intptr_t kNumInputs = 1; |
| 1954 const intptr_t kNumTemps = 0; | 1944 const intptr_t kNumTemps = 0; |
| 1955 LocationSummary* summary = | 1945 LocationSummary* summary = |
| 1956 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1946 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1957 summary->set_in(0, Location::RequiresRegister()); | 1947 summary->set_in(0, Location::RequiresRegister()); |
| 1958 summary->set_out(Location::SameAsFirstInput()); | 1948 summary->set_out(Location::SameAsFirstInput()); |
| 1959 return summary; | 1949 return summary; |
| 1960 } | 1950 } |
| 1961 | 1951 |
| 1962 | 1952 |
| 1963 void UnarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1953 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1964 Register value = locs()->in(0).reg(); | 1954 Register value = locs()->in(0).reg(); |
| 1965 ASSERT(value == locs()->out().reg()); | 1955 ASSERT(value == locs()->out().reg()); |
| 1966 switch (op_kind()) { | 1956 switch (op_kind()) { |
| 1967 case Token::kNEGATE: { | 1957 case Token::kNEGATE: { |
| 1968 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1958 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1969 kDeoptUnaryOp); | 1959 kDeoptUnaryOp); |
| 1970 __ negl(value); | 1960 __ negl(value); |
| 1971 __ j(OVERFLOW, deopt); | 1961 __ j(OVERFLOW, deopt); |
| 1972 break; | 1962 break; |
| 1973 } | 1963 } |
| 1974 case Token::kBIT_NOT: | 1964 case Token::kBIT_NOT: |
| 1975 __ notl(value); | 1965 __ notl(value); |
| 1976 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 1966 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| 1977 break; | 1967 break; |
| 1978 default: | 1968 default: |
| 1979 UNREACHABLE(); | 1969 UNREACHABLE(); |
| 1980 } | 1970 } |
| 1981 } | 1971 } |
| 1982 | 1972 |
| 1983 | 1973 |
| 1984 LocationSummary* NumberNegateComp::MakeLocationSummary() const { | 1974 LocationSummary* NumberNegateInstr::MakeLocationSummary() const { |
| 1985 const intptr_t kNumInputs = 1; | 1975 const intptr_t kNumInputs = 1; |
| 1986 const intptr_t kNumTemps = 1; // Needed for doubles. | 1976 const intptr_t kNumTemps = 1; // Needed for doubles. |
| 1987 LocationSummary* summary = | 1977 LocationSummary* summary = |
| 1988 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1978 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1989 summary->set_in(0, Location::RegisterLocation(EAX)); | 1979 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 1990 summary->set_temp(0, Location::RegisterLocation(ECX)); | 1980 summary->set_temp(0, Location::RegisterLocation(ECX)); |
| 1991 summary->set_out(Location::RegisterLocation(EAX)); | 1981 summary->set_out(Location::RegisterLocation(EAX)); |
| 1992 return summary; | 1982 return summary; |
| 1993 } | 1983 } |
| 1994 | 1984 |
| 1995 | 1985 |
| 1996 void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1986 void NumberNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1997 const ICData& ic_data = *instance_call()->ic_data(); | 1987 const ICData& ic_data = *instance_call()->ic_data(); |
| 1998 ASSERT(!ic_data.IsNull()); | 1988 ASSERT(!ic_data.IsNull()); |
| 1999 ASSERT(ic_data.num_args_tested() == 1); | 1989 ASSERT(ic_data.num_args_tested() == 1); |
| 2000 | 1990 |
| 2001 // TODO(srdjan): Implement for more checks. | 1991 // TODO(srdjan): Implement for more checks. |
| 2002 ASSERT(ic_data.NumberOfChecks() == 1); | 1992 ASSERT(ic_data.NumberOfChecks() == 1); |
| 2003 intptr_t test_class_id; | 1993 intptr_t test_class_id; |
| 2004 Function& target = Function::Handle(); | 1994 Function& target = Function::Handle(); |
| 2005 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1995 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 2006 | 1996 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2032 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 2022 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 2033 __ DoubleNegate(XMM0); | 2023 __ DoubleNegate(XMM0); |
| 2034 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 2024 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 2035 } else { | 2025 } else { |
| 2036 UNREACHABLE(); | 2026 UNREACHABLE(); |
| 2037 } | 2027 } |
| 2038 ASSERT(ResultCid() == kDoubleCid); | 2028 ASSERT(ResultCid() == kDoubleCid); |
| 2039 } | 2029 } |
| 2040 | 2030 |
| 2041 | 2031 |
| 2042 LocationSummary* DoubleToDoubleComp::MakeLocationSummary() const { | 2032 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { |
| 2043 const intptr_t kNumInputs = 1; | 2033 const intptr_t kNumInputs = 1; |
| 2044 const intptr_t kNumTemps = 1; | 2034 const intptr_t kNumTemps = 1; |
| 2045 LocationSummary* locs = | 2035 LocationSummary* locs = |
| 2046 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2036 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2047 locs->set_in(0, Location::RequiresRegister()); | 2037 locs->set_in(0, Location::RequiresRegister()); |
| 2048 locs->set_temp(0, Location::RequiresRegister()); | 2038 locs->set_temp(0, Location::RequiresRegister()); |
| 2049 locs->set_out(Location::SameAsFirstInput()); | 2039 locs->set_out(Location::SameAsFirstInput()); |
| 2050 return locs; | 2040 return locs; |
| 2051 } | 2041 } |
| 2052 | 2042 |
| 2053 | 2043 |
| 2054 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2044 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2055 Register value = locs()->in(0).reg(); | 2045 Register value = locs()->in(0).reg(); |
| 2056 Register result = locs()->out().reg(); | 2046 Register result = locs()->out().reg(); |
| 2057 | 2047 |
| 2058 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2048 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2059 kDeoptDoubleToDouble); | 2049 kDeoptDoubleToDouble); |
| 2060 Register temp = locs()->temp(0).reg(); | 2050 Register temp = locs()->temp(0).reg(); |
| 2061 __ testl(value, Immediate(kSmiTagMask)); | 2051 __ testl(value, Immediate(kSmiTagMask)); |
| 2062 __ j(ZERO, deopt); // Deoptimize if Smi. | 2052 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 2063 __ CompareClassId(value, kDoubleCid, temp); | 2053 __ CompareClassId(value, kDoubleCid, temp); |
| 2064 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 2054 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
| 2065 ASSERT(value == result); | 2055 ASSERT(value == result); |
| 2066 } | 2056 } |
| 2067 | 2057 |
| 2068 | 2058 |
| 2069 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const { | 2059 LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const { |
| 2070 return MakeCallSummary(); // Calls a stub to allocate result. | 2060 return MakeCallSummary(); // Calls a stub to allocate result. |
| 2071 } | 2061 } |
| 2072 | 2062 |
| 2073 | 2063 |
| 2074 void SmiToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2064 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2075 Register result = locs()->out().reg(); | 2065 Register result = locs()->out().reg(); |
| 2076 | 2066 |
| 2077 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2067 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2078 kDeoptIntegerToDouble); | 2068 kDeoptIntegerToDouble); |
| 2079 | 2069 |
| 2080 const Class& double_class = compiler->double_class(); | 2070 const Class& double_class = compiler->double_class(); |
| 2081 const Code& stub = | 2071 const Code& stub = |
| 2082 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2072 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 2083 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2073 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 2084 | 2074 |
| 2085 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 2075 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
| 2086 compiler->GenerateCall(instance_call()->token_pos(), | 2076 compiler->GenerateCall(instance_call()->token_pos(), |
| 2087 &label, | 2077 &label, |
| 2088 PcDescriptors::kOther, | 2078 PcDescriptors::kOther, |
| 2089 locs()); | 2079 locs()); |
| 2090 ASSERT(result == EAX); | 2080 ASSERT(result == EAX); |
| 2091 Register value = EBX; | 2081 Register value = EBX; |
| 2092 // Preserve argument on the stack until after the deoptimization point. | 2082 // Preserve argument on the stack until after the deoptimization point. |
| 2093 __ movl(value, Address(ESP, 0)); | 2083 __ movl(value, Address(ESP, 0)); |
| 2094 | 2084 |
| 2095 __ testl(value, Immediate(kSmiTagMask)); | 2085 __ testl(value, Immediate(kSmiTagMask)); |
| 2096 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 2086 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
| 2097 __ SmiUntag(value); | 2087 __ SmiUntag(value); |
| 2098 __ cvtsi2sd(XMM0, value); | 2088 __ cvtsi2sd(XMM0, value); |
| 2099 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 2089 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 2100 __ Drop(1); | 2090 __ Drop(1); |
| 2101 } | 2091 } |
| 2102 | 2092 |
| 2103 | 2093 |
| 2104 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 2094 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { |
| 2105 return MakeCallSummary(); | 2095 return MakeCallSummary(); |
| 2106 } | 2096 } |
| 2107 | 2097 |
| 2108 | 2098 |
| 2109 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2099 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2110 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2100 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2111 kDeoptPolymorphicInstanceCallTestFail); | 2101 kDeoptPolymorphicInstanceCallTestFail); |
| 2112 if (ic_data().NumberOfChecks() == 0) { | 2102 if (ic_data().NumberOfChecks() == 0) { |
| 2113 __ jmp(deopt); | 2103 __ jmp(deopt); |
| 2114 return; | 2104 return; |
| 2115 } | 2105 } |
| 2116 ASSERT(ic_data().num_args_tested() == 1); | 2106 ASSERT(ic_data().num_args_tested() == 1); |
| 2117 if (!with_checks()) { | 2107 if (!with_checks()) { |
| 2118 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); | 2108 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); |
| 2119 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 2109 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2140 EDI, // Class id register. | 2130 EDI, // Class id register. |
| 2141 instance_call()->ArgumentCount(), | 2131 instance_call()->ArgumentCount(), |
| 2142 instance_call()->argument_names(), | 2132 instance_call()->argument_names(), |
| 2143 deopt, | 2133 deopt, |
| 2144 instance_call()->deopt_id(), | 2134 instance_call()->deopt_id(), |
| 2145 instance_call()->token_pos(), | 2135 instance_call()->token_pos(), |
| 2146 locs()); | 2136 locs()); |
| 2147 } | 2137 } |
| 2148 | 2138 |
| 2149 | 2139 |
| 2140 LocationSummary* BranchInstr::MakeLocationSummary() const { |
| 2141 UNREACHABLE(); |
| 2142 return NULL; |
| 2143 } |
| 2144 |
| 2145 |
| 2150 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2146 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2151 computation()->EmitBranchCode(compiler, this); | 2147 comparison()->EmitBranchCode(compiler, this); |
| 2152 } | 2148 } |
| 2153 | 2149 |
| 2154 | 2150 |
| 2155 LocationSummary* CheckClassComp::MakeLocationSummary() const { | 2151 LocationSummary* CheckClassInstr::MakeLocationSummary() const { |
| 2156 const intptr_t kNumInputs = 1; | 2152 const intptr_t kNumInputs = 1; |
| 2157 const intptr_t kNumTemps = 1; | 2153 const intptr_t kNumTemps = 1; |
| 2158 LocationSummary* summary = | 2154 LocationSummary* summary = |
| 2159 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2155 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2160 summary->set_in(0, Location::RequiresRegister()); | 2156 summary->set_in(0, Location::RequiresRegister()); |
| 2161 summary->set_temp(0, Location::RequiresRegister()); | 2157 summary->set_temp(0, Location::RequiresRegister()); |
| 2162 return summary; | 2158 return summary; |
| 2163 } | 2159 } |
| 2164 | 2160 |
| 2165 | 2161 |
| 2166 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2162 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2167 Register value = locs()->in(0).reg(); | 2163 Register value = locs()->in(0).reg(); |
| 2168 Register temp = locs()->temp(0).reg(); | 2164 Register temp = locs()->temp(0).reg(); |
| 2169 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2165 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2170 kDeoptCheckClass); | 2166 kDeoptCheckClass); |
| 2171 ASSERT(unary_checks().GetReceiverClassIdAt(0) != kSmiCid); | 2167 ASSERT(unary_checks().GetReceiverClassIdAt(0) != kSmiCid); |
| 2172 __ testl(value, Immediate(kSmiTagMask)); | 2168 __ testl(value, Immediate(kSmiTagMask)); |
| 2173 __ j(ZERO, deopt); | 2169 __ j(ZERO, deopt); |
| 2174 __ LoadClassId(temp, value); | 2170 __ LoadClassId(temp, value); |
| 2175 Label is_ok; | 2171 Label is_ok; |
| 2176 const intptr_t num_checks = unary_checks().NumberOfChecks(); | 2172 const intptr_t num_checks = unary_checks().NumberOfChecks(); |
| 2177 const bool use_near_jump = num_checks < 5; | 2173 const bool use_near_jump = num_checks < 5; |
| 2178 for (intptr_t i = 0; i < num_checks; i++) { | 2174 for (intptr_t i = 0; i < num_checks; i++) { |
| 2179 __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i))); | 2175 __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i))); |
| 2180 if (i == (num_checks - 1)) { | 2176 if (i == (num_checks - 1)) { |
| 2181 __ j(NOT_EQUAL, deopt); | 2177 __ j(NOT_EQUAL, deopt); |
| 2182 } else { | 2178 } else { |
| 2183 if (use_near_jump) { | 2179 if (use_near_jump) { |
| 2184 __ j(EQUAL, &is_ok, Assembler::kNearJump); | 2180 __ j(EQUAL, &is_ok, Assembler::kNearJump); |
| 2185 } else { | 2181 } else { |
| 2186 __ j(EQUAL, &is_ok); | 2182 __ j(EQUAL, &is_ok); |
| 2187 } | 2183 } |
| 2188 } | 2184 } |
| 2189 } | 2185 } |
| 2190 __ Bind(&is_ok); | 2186 __ Bind(&is_ok); |
| 2191 } | 2187 } |
| 2192 | 2188 |
| 2193 | 2189 |
| 2194 LocationSummary* CheckSmiComp::MakeLocationSummary() const { | 2190 LocationSummary* CheckSmiInstr::MakeLocationSummary() const { |
| 2195 const intptr_t kNumInputs = 1; | 2191 const intptr_t kNumInputs = 1; |
| 2196 const intptr_t kNumTemps = 0; | 2192 const intptr_t kNumTemps = 0; |
| 2197 LocationSummary* summary = | 2193 LocationSummary* summary = |
| 2198 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2194 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2199 summary->set_in(0, Location::RequiresRegister()); | 2195 summary->set_in(0, Location::RequiresRegister()); |
| 2200 return summary; | 2196 return summary; |
| 2201 } | 2197 } |
| 2202 | 2198 |
| 2203 | 2199 |
| 2204 void CheckSmiComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2200 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2205 Register value = locs()->in(0).reg(); | 2201 Register value = locs()->in(0).reg(); |
| 2206 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2202 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2207 kDeoptCheckSmi); | 2203 kDeoptCheckSmi); |
| 2208 __ testl(value, Immediate(kSmiTagMask)); | 2204 __ testl(value, Immediate(kSmiTagMask)); |
| 2209 __ j(NOT_ZERO, deopt); | 2205 __ j(NOT_ZERO, deopt); |
| 2210 } | 2206 } |
| 2211 | 2207 |
| 2212 | 2208 |
| 2213 LocationSummary* CheckArrayBoundComp::MakeLocationSummary() const { | 2209 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { |
| 2214 const intptr_t kNumInputs = 2; | 2210 const intptr_t kNumInputs = 2; |
| 2215 const intptr_t kNumTemps = 0; | 2211 const intptr_t kNumTemps = 0; |
| 2216 LocationSummary* locs = | 2212 LocationSummary* locs = |
| 2217 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2213 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2218 locs->set_in(0, Location::RequiresRegister()); | 2214 locs->set_in(0, Location::RequiresRegister()); |
| 2219 locs->set_in(1, Location::RegisterOrConstant(index())); | 2215 locs->set_in(1, Location::RegisterOrConstant(index())); |
| 2220 return locs; | 2216 return locs; |
| 2221 } | 2217 } |
| 2222 | 2218 |
| 2223 | 2219 |
| 2224 void CheckArrayBoundComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2220 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2225 Register receiver = locs()->in(0).reg(); | 2221 Register receiver = locs()->in(0).reg(); |
| 2226 | 2222 |
| 2227 const DeoptReasonId deopt_reason = | 2223 const DeoptReasonId deopt_reason = |
| 2228 (array_type() == kGrowableObjectArrayCid) ? | 2224 (array_type() == kGrowableObjectArrayCid) ? |
| 2229 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 2225 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 2230 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2226 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2231 deopt_reason); | 2227 deopt_reason); |
| 2232 ASSERT(array_type() == kArrayCid || | 2228 ASSERT(array_type() == kArrayCid || |
| 2233 array_type() == kImmutableArrayCid || | 2229 array_type() == kImmutableArrayCid || |
| 2234 array_type() == kGrowableObjectArrayCid); | 2230 array_type() == kGrowableObjectArrayCid); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2249 __ j(ABOVE_EQUAL, deopt); | 2245 __ j(ABOVE_EQUAL, deopt); |
| 2250 } | 2246 } |
| 2251 } | 2247 } |
| 2252 | 2248 |
| 2253 | 2249 |
| 2254 } // namespace dart | 2250 } // namespace dart |
| 2255 | 2251 |
| 2256 #undef __ | 2252 #undef __ |
| 2257 | 2253 |
| 2258 #endif // defined TARGET_ARCH_X64 | 2254 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |