| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 LocationSummary* locs = | 39 LocationSummary* locs = |
| 40 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 40 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 41 locs->set_in(0, Location::AnyOrConstant(value())); | 41 locs->set_in(0, Location::AnyOrConstant(value())); |
| 42 return locs; | 42 return locs; |
| 43 } | 43 } |
| 44 | 44 |
| 45 | 45 |
| 46 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 46 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 47 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 47 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 48 // where PushArgument is handled by BindInstr::EmitNativeCode. | 48 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 49 __ TraceSimMsg("PushArgumentInstr"); |
| 49 if (compiler->is_optimizing()) { | 50 if (compiler->is_optimizing()) { |
| 50 Location value = locs()->in(0); | 51 Location value = locs()->in(0); |
| 51 if (value.IsRegister()) { | 52 if (value.IsRegister()) { |
| 52 __ Push(value.reg()); | 53 __ Push(value.reg()); |
| 53 } else if (value.IsConstant()) { | 54 } else if (value.IsConstant()) { |
| 54 __ PushObject(value.constant()); | 55 __ PushObject(value.constant()); |
| 55 } else { | 56 } else { |
| 56 ASSERT(value.IsStackSlot()); | 57 ASSERT(value.IsStackSlot()); |
| 57 __ lw(TMP, value.ToStackSlotAddress()); | 58 __ lw(TMP, value.ToStackSlotAddress()); |
| 58 __ Push(TMP); | 59 __ Push(TMP); |
| 59 } | 60 } |
| 60 } | 61 } |
| 61 } | 62 } |
| 62 | 63 |
| 63 | 64 |
| 64 LocationSummary* ReturnInstr::MakeLocationSummary() const { | 65 LocationSummary* ReturnInstr::MakeLocationSummary() const { |
| 65 const intptr_t kNumInputs = 1; | 66 const intptr_t kNumInputs = 1; |
| 66 const intptr_t kNumTemps = 0; | 67 const intptr_t kNumTemps = 0; |
| 67 LocationSummary* locs = | 68 LocationSummary* locs = |
| 68 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 69 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 69 locs->set_in(0, Location::RegisterLocation(V0)); | 70 locs->set_in(0, Location::RegisterLocation(V0)); |
| 70 return locs; | 71 return locs; |
| 71 } | 72 } |
| 72 | 73 |
| 73 | 74 |
| 74 // Attempt optimized compilation at return instruction instead of at the entry. | 75 // Attempt optimized compilation at return instruction instead of at the entry. |
| 75 // The entry needs to be patchable, no inlined objects are allowed in the area | 76 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 76 // that will be overwritten by the patch instructions: a branch macro sequence. | 77 // that will be overwritten by the patch instructions: a branch macro sequence. |
| 77 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 78 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 79 __ TraceSimMsg("ReturnInstr"); |
| 78 Register result = locs()->in(0).reg(); | 80 Register result = locs()->in(0).reg(); |
| 79 ASSERT(result == V0); | 81 ASSERT(result == V0); |
| 80 #if defined(DEBUG) | 82 #if defined(DEBUG) |
| 81 // TODO(srdjan): Fix for functions with finally clause. | 83 // TODO(srdjan): Fix for functions with finally clause. |
| 82 // A finally clause may leave a previously pushed return value if it | 84 // A finally clause may leave a previously pushed return value if it |
| 83 // has its own return instruction. Method that have finally are currently | 85 // has its own return instruction. Method that have finally are currently |
| 84 // not optimized. | 86 // not optimized. |
| 85 if (!compiler->HasFinally()) { | 87 if (!compiler->HasFinally()) { |
| 86 Label stack_ok; | 88 Label stack_ok; |
| 87 __ Comment("Stack Check"); | 89 __ Comment("Stack Check"); |
| 90 __ TraceSimMsg("Stack Check"); |
| 88 const intptr_t fp_sp_dist = | 91 const intptr_t fp_sp_dist = |
| 89 (kFirstLocalSlotIndex + 1 - compiler->StackSize()) * kWordSize; | 92 (kFirstLocalSlotIndex + 1 - compiler->StackSize()) * kWordSize; |
| 90 ASSERT(fp_sp_dist <= 0); | 93 ASSERT(fp_sp_dist <= 0); |
| 91 __ subu(T2, SP, FP); | 94 __ subu(T2, SP, FP); |
| 92 | 95 |
| 93 __ BranchEqual(T2, fp_sp_dist, &stack_ok); | 96 __ BranchEqual(T2, fp_sp_dist, &stack_ok); |
| 94 __ break_(0); | 97 __ break_(0); |
| 95 | 98 |
| 96 __ Bind(&stack_ok); | 99 __ Bind(&stack_ok); |
| 97 } | 100 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 127 return NULL; | 130 return NULL; |
| 128 } | 131 } |
| 129 | 132 |
| 130 | 133 |
| 131 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 134 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 132 UNREACHABLE(); | 135 UNREACHABLE(); |
| 133 } | 136 } |
| 134 | 137 |
| 135 | 138 |
| 136 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { | 139 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { |
| 137 UNIMPLEMENTED(); | 140 const intptr_t kNumInputs = 0; |
| 138 return NULL; | 141 const intptr_t kNumTemps = 1; |
| 142 LocationSummary* result = |
| 143 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 144 result->set_out(Location::RegisterLocation(V0)); |
| 145 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor. |
| 146 return result; |
| 147 } |
| 148 |
| 149 |
| 150 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 151 // The arguments to the stub include the closure, as does the arguments |
| 152 // descriptor. |
| 153 Register temp_reg = locs()->temp(0).reg(); |
| 154 int argument_count = ArgumentCount(); |
| 155 const Array& arguments_descriptor = |
| 156 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
| 157 argument_names())); |
| 158 __ LoadObject(temp_reg, arguments_descriptor); |
| 159 compiler->GenerateDartCall(deopt_id(), |
| 160 token_pos(), |
| 161 &StubCode::CallClosureFunctionLabel(), |
| 162 PcDescriptors::kOther, |
| 163 locs()); |
| 164 __ Drop(argument_count); |
| 139 } | 165 } |
| 140 | 166 |
| 141 | 167 |
| 142 LocationSummary* LoadLocalInstr::MakeLocationSummary() const { | 168 LocationSummary* LoadLocalInstr::MakeLocationSummary() const { |
| 143 return LocationSummary::Make(0, | 169 return LocationSummary::Make(0, |
| 144 Location::RequiresRegister(), | 170 Location::RequiresRegister(), |
| 145 LocationSummary::kNoCall); | 171 LocationSummary::kNoCall); |
| 146 } | 172 } |
| 147 | 173 |
| 148 | 174 |
| 149 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 175 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 176 __ TraceSimMsg("LoadLocalInstr"); |
| 150 Register result = locs()->out().reg(); | 177 Register result = locs()->out().reg(); |
| 151 __ lw(result, Address(FP, local().index() * kWordSize)); | 178 __ lw(result, Address(FP, local().index() * kWordSize)); |
| 152 } | 179 } |
| 153 | 180 |
| 154 | 181 |
| 155 LocationSummary* StoreLocalInstr::MakeLocationSummary() const { | 182 LocationSummary* StoreLocalInstr::MakeLocationSummary() const { |
| 156 return LocationSummary::Make(1, | 183 return LocationSummary::Make(1, |
| 157 Location::SameAsFirstInput(), | 184 Location::SameAsFirstInput(), |
| 158 LocationSummary::kNoCall); | 185 LocationSummary::kNoCall); |
| 159 } | 186 } |
| 160 | 187 |
| 161 | 188 |
| 162 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 189 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 190 __ TraceSimMsg("StoreLocalInstr"); |
| 163 Register value = locs()->in(0).reg(); | 191 Register value = locs()->in(0).reg(); |
| 164 Register result = locs()->out().reg(); | 192 Register result = locs()->out().reg(); |
| 165 ASSERT(result == value); // Assert that register assignment is correct. | 193 ASSERT(result == value); // Assert that register assignment is correct. |
| 166 __ sw(value, Address(FP, local().index() * kWordSize)); | 194 __ sw(value, Address(FP, local().index() * kWordSize)); |
| 167 } | 195 } |
| 168 | 196 |
| 169 | 197 |
| 170 LocationSummary* ConstantInstr::MakeLocationSummary() const { | 198 LocationSummary* ConstantInstr::MakeLocationSummary() const { |
| 171 return LocationSummary::Make(0, | 199 return LocationSummary::Make(0, |
| 172 Location::RequiresRegister(), | 200 Location::RequiresRegister(), |
| 173 LocationSummary::kNoCall); | 201 LocationSummary::kNoCall); |
| 174 } | 202 } |
| 175 | 203 |
| 176 | 204 |
| 177 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 205 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 178 // The register allocator drops constant definitions that have no uses. | 206 // The register allocator drops constant definitions that have no uses. |
| 179 if (!locs()->out().IsInvalid()) { | 207 if (!locs()->out().IsInvalid()) { |
| 208 __ TraceSimMsg("ConstantInstr"); |
| 180 Register result = locs()->out().reg(); | 209 Register result = locs()->out().reg(); |
| 181 __ LoadObject(result, value()); | 210 __ LoadObject(result, value()); |
| 182 } | 211 } |
| 183 } | 212 } |
| 184 | 213 |
| 185 | 214 |
| 186 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { | 215 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { |
| 187 const intptr_t kNumInputs = 3; | 216 const intptr_t kNumInputs = 3; |
| 188 const intptr_t kNumTemps = 0; | 217 const intptr_t kNumTemps = 0; |
| 189 LocationSummary* summary = | 218 LocationSummary* summary = |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 // We should never return here. | 256 // We should never return here. |
| 228 __ break_(0); | 257 __ break_(0); |
| 229 __ Bind(&done); | 258 __ Bind(&done); |
| 230 } | 259 } |
| 231 | 260 |
| 232 | 261 |
| 233 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 262 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 234 Register obj = locs()->in(0).reg(); | 263 Register obj = locs()->in(0).reg(); |
| 235 Register result = locs()->out().reg(); | 264 Register result = locs()->out().reg(); |
| 236 | 265 |
| 266 __ TraceSimMsg("AssertBooleanInstr"); |
| 237 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 267 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 238 ASSERT(obj == result); | 268 ASSERT(obj == result); |
| 239 } | 269 } |
| 240 | 270 |
| 241 | 271 |
| 242 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { | 272 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { |
| 243 UNIMPLEMENTED(); | 273 UNIMPLEMENTED(); |
| 244 return NULL; | 274 return NULL; |
| 245 } | 275 } |
| 246 | 276 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 // A1: left. | 347 // A1: left. |
| 318 // A0: right. | 348 // A0: right. |
| 319 // Uses T0 to load ic_call_data. | 349 // Uses T0 to load ic_call_data. |
| 320 // Result in V0. | 350 // Result in V0. |
| 321 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 351 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 322 intptr_t deopt_id, | 352 intptr_t deopt_id, |
| 323 intptr_t token_pos, | 353 intptr_t token_pos, |
| 324 Token::Kind kind, | 354 Token::Kind kind, |
| 325 LocationSummary* locs, | 355 LocationSummary* locs, |
| 326 const ICData& original_ic_data) { | 356 const ICData& original_ic_data) { |
| 357 __ TraceSimMsg("EmitEqualityAsInstanceCall"); |
| 327 if (!compiler->is_optimizing()) { | 358 if (!compiler->is_optimizing()) { |
| 328 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 359 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 329 deopt_id, | 360 deopt_id, |
| 330 token_pos); | 361 token_pos); |
| 331 } | 362 } |
| 332 const int kNumberOfArguments = 2; | 363 const int kNumberOfArguments = 2; |
| 333 const Array& kNoArgumentNames = Array::Handle(); | 364 const Array& kNoArgumentNames = Array::Handle(); |
| 334 const int kNumArgumentsChecked = 2; | 365 const int kNumArgumentsChecked = 2; |
| 335 | 366 |
| 336 Label check_identity; | 367 Label check_identity; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 __ Bind(&done); | 435 __ Bind(&done); |
| 405 } | 436 } |
| 406 __ Bind(&equality_done); | 437 __ Bind(&equality_done); |
| 407 } | 438 } |
| 408 | 439 |
| 409 | 440 |
| 410 static void LoadValueCid(FlowGraphCompiler* compiler, | 441 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 411 Register value_cid_reg, | 442 Register value_cid_reg, |
| 412 Register value_reg, | 443 Register value_reg, |
| 413 Label* value_is_smi = NULL) { | 444 Label* value_is_smi = NULL) { |
| 445 __ TraceSimMsg("LoadValueCid"); |
| 414 Label done; | 446 Label done; |
| 415 if (value_is_smi == NULL) { | 447 if (value_is_smi == NULL) { |
| 416 __ LoadImmediate(value_cid_reg, kSmiCid); | 448 __ LoadImmediate(value_cid_reg, kSmiCid); |
| 417 } | 449 } |
| 418 __ andi(TMP1, value_reg, Immediate(kSmiTagMask)); | 450 __ andi(TMP1, value_reg, Immediate(kSmiTagMask)); |
| 419 if (value_is_smi == NULL) { | 451 if (value_is_smi == NULL) { |
| 420 __ beq(TMP1, ZR, &done); | 452 __ beq(TMP1, ZR, &done); |
| 421 } else { | 453 } else { |
| 422 __ beq(TMP1, ZR, value_is_smi); | 454 __ beq(TMP1, ZR, value_is_smi); |
| 423 } | 455 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 UNREACHABLE(); | 495 UNREACHABLE(); |
| 464 return VS; | 496 return VS; |
| 465 } | 497 } |
| 466 } | 498 } |
| 467 | 499 |
| 468 | 500 |
| 469 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 501 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 470 const LocationSummary& locs, | 502 const LocationSummary& locs, |
| 471 Token::Kind kind, | 503 Token::Kind kind, |
| 472 BranchInstr* branch) { | 504 BranchInstr* branch) { |
| 505 __ TraceSimMsg("EmitSmiComparisonOp"); |
| 473 Location left = locs.in(0); | 506 Location left = locs.in(0); |
| 474 Location right = locs.in(1); | 507 Location right = locs.in(1); |
| 475 ASSERT(!left.IsConstant() || !right.IsConstant()); | 508 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 476 | 509 |
| 477 Condition true_condition = TokenKindToSmiCondition(kind); | 510 Condition true_condition = TokenKindToSmiCondition(kind); |
| 478 | 511 |
| 479 if (left.IsConstant()) { | 512 if (left.IsConstant()) { |
| 480 __ CompareObject(CMPRES, right.reg(), left.constant()); | 513 __ CompareObject(CMPRES, right.reg(), left.constant()); |
| 481 true_condition = FlowGraphCompiler::FlipCondition(true_condition); | 514 true_condition = FlowGraphCompiler::FlipCondition(true_condition); |
| 482 } else if (right.IsConstant()) { | 515 } else if (right.IsConstant()) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 token_pos(), | 603 token_pos(), |
| 571 kind(), | 604 kind(), |
| 572 locs(), | 605 locs(), |
| 573 *ic_data()); | 606 *ic_data()); |
| 574 ASSERT(locs()->out().reg() == V0); | 607 ASSERT(locs()->out().reg() == V0); |
| 575 } | 608 } |
| 576 | 609 |
| 577 | 610 |
| 578 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 611 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 579 BranchInstr* branch) { | 612 BranchInstr* branch) { |
| 613 __ TraceSimMsg("EqualityCompareInstr"); |
| 580 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 614 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 581 if (receiver_class_id() == kSmiCid) { | 615 if (receiver_class_id() == kSmiCid) { |
| 582 // Deoptimizes if both arguments not Smi. | 616 // Deoptimizes if both arguments not Smi. |
| 583 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 617 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 584 return; | 618 return; |
| 585 } | 619 } |
| 586 if (receiver_class_id() == kMintCid) { | 620 if (receiver_class_id() == kMintCid) { |
| 587 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); | 621 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); |
| 588 return; | 622 return; |
| 589 } | 623 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 693 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 660 // Pick arbitrary fixed input registers because this is a call. | 694 // Pick arbitrary fixed input registers because this is a call. |
| 661 locs->set_in(0, Location::RegisterLocation(A0)); | 695 locs->set_in(0, Location::RegisterLocation(A0)); |
| 662 locs->set_in(1, Location::RegisterLocation(A1)); | 696 locs->set_in(1, Location::RegisterLocation(A1)); |
| 663 locs->set_out(Location::RegisterLocation(V0)); | 697 locs->set_out(Location::RegisterLocation(V0)); |
| 664 return locs; | 698 return locs; |
| 665 } | 699 } |
| 666 | 700 |
| 667 | 701 |
| 668 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 702 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 703 __ TraceSimMsg("RelationalOpInstr"); |
| 669 if (operands_class_id() == kSmiCid) { | 704 if (operands_class_id() == kSmiCid) { |
| 670 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 705 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); |
| 671 return; | 706 return; |
| 672 } | 707 } |
| 673 if (operands_class_id() == kMintCid) { | 708 if (operands_class_id() == kMintCid) { |
| 674 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); | 709 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); |
| 675 return; | 710 return; |
| 676 } | 711 } |
| 677 if (operands_class_id() == kDoubleCid) { | 712 if (operands_class_id() == kDoubleCid) { |
| 678 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 713 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 token_pos(), | 765 token_pos(), |
| 731 kNumArguments, | 766 kNumArguments, |
| 732 Array::ZoneHandle(), // No optional arguments. | 767 Array::ZoneHandle(), // No optional arguments. |
| 733 locs(), | 768 locs(), |
| 734 relational_ic_data); | 769 relational_ic_data); |
| 735 } | 770 } |
| 736 | 771 |
| 737 | 772 |
| 738 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 773 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 739 BranchInstr* branch) { | 774 BranchInstr* branch) { |
| 775 __ TraceSimMsg("RelationalOpInstr"); |
| 740 if (operands_class_id() == kSmiCid) { | 776 if (operands_class_id() == kSmiCid) { |
| 741 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 777 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 742 return; | 778 return; |
| 743 } | 779 } |
| 744 if (operands_class_id() == kMintCid) { | 780 if (operands_class_id() == kMintCid) { |
| 745 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); | 781 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); |
| 746 return; | 782 return; |
| 747 } | 783 } |
| 748 if (operands_class_id() == kDoubleCid) { | 784 if (operands_class_id() == kDoubleCid) { |
| 749 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 785 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 762 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 798 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 763 locs->set_temp(0, Location::RegisterLocation(A1)); | 799 locs->set_temp(0, Location::RegisterLocation(A1)); |
| 764 locs->set_temp(1, Location::RegisterLocation(A2)); | 800 locs->set_temp(1, Location::RegisterLocation(A2)); |
| 765 locs->set_temp(2, Location::RegisterLocation(T5)); | 801 locs->set_temp(2, Location::RegisterLocation(T5)); |
| 766 locs->set_out(Location::RegisterLocation(V0)); | 802 locs->set_out(Location::RegisterLocation(V0)); |
| 767 return locs; | 803 return locs; |
| 768 } | 804 } |
| 769 | 805 |
| 770 | 806 |
| 771 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 807 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 808 __ TraceSimMsg("NativeCallInstr"); |
| 772 ASSERT(locs()->temp(0).reg() == A1); | 809 ASSERT(locs()->temp(0).reg() == A1); |
| 773 ASSERT(locs()->temp(1).reg() == A2); | 810 ASSERT(locs()->temp(1).reg() == A2); |
| 774 ASSERT(locs()->temp(2).reg() == T5); | 811 ASSERT(locs()->temp(2).reg() == T5); |
| 775 Register result = locs()->out().reg(); | 812 Register result = locs()->out().reg(); |
| 776 | 813 |
| 777 // Push the result place holder initialized to NULL. | 814 // Push the result place holder initialized to NULL. |
| 778 __ PushObject(Object::ZoneHandle()); | 815 __ PushObject(Object::ZoneHandle()); |
| 779 // Pass a pointer to the first argument in A2. | 816 // Pass a pointer to the first argument in A2. |
| 780 if (!function().HasOptionalParameters()) { | 817 if (!function().HasOptionalParameters()) { |
| 781 __ AddImmediate(A2, FP, (kLastParamSlotIndex + | 818 __ AddImmediate(A2, FP, (kLastParamSlotIndex + |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 | 883 |
| 847 | 884 |
| 848 Representation StoreIndexedInstr::RequiredInputRepresentation( | 885 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 849 intptr_t idx) const { | 886 intptr_t idx) const { |
| 850 UNIMPLEMENTED(); | 887 UNIMPLEMENTED(); |
| 851 return kTagged; | 888 return kTagged; |
| 852 } | 889 } |
| 853 | 890 |
| 854 | 891 |
| 855 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { | 892 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
| 856 UNIMPLEMENTED(); | 893 const intptr_t kNumInputs = 3; |
| 857 return NULL; | 894 const intptr_t kNumTemps = 0; |
| 895 LocationSummary* locs = |
| 896 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 897 locs->set_in(0, Location::RequiresRegister()); |
| 898 // The smi index is either untagged (element size == 1), or it is left smi |
| 899 // tagged (for all element sizes > 1). |
| 900 // TODO(regis): Revisit and see if the index can be immediate. |
| 901 locs->set_in(1, Location::WritableRegister()); |
| 902 switch (class_id()) { |
| 903 case kArrayCid: |
| 904 locs->set_in(2, ShouldEmitStoreBarrier() |
| 905 ? Location::WritableRegister() |
| 906 : Location::RegisterOrConstant(value())); |
| 907 break; |
| 908 case kExternalTypedDataUint8ArrayCid: |
| 909 case kExternalTypedDataUint8ClampedArrayCid: |
| 910 case kTypedDataInt8ArrayCid: |
| 911 case kTypedDataUint8ArrayCid: |
| 912 case kTypedDataUint8ClampedArrayCid: |
| 913 case kTypedDataInt16ArrayCid: |
| 914 case kTypedDataUint16ArrayCid: |
| 915 case kTypedDataInt32ArrayCid: |
| 916 case kTypedDataUint32ArrayCid: |
| 917 case kTypedDataFloat32ArrayCid: |
| 918 case kTypedDataFloat64ArrayCid: |
| 919 case kTypedDataFloat32x4ArrayCid: |
| 920 UNIMPLEMENTED(); |
| 921 break; |
| 922 default: |
| 923 UNREACHABLE(); |
| 924 return NULL; |
| 925 } |
| 926 return locs; |
| 858 } | 927 } |
| 859 | 928 |
| 860 | 929 |
| 861 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 930 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 862 UNIMPLEMENTED(); | 931 __ TraceSimMsg("StoreIndexedInstr"); |
| 932 Register array = locs()->in(0).reg(); |
| 933 Location index = locs()->in(1); |
| 934 |
| 935 Address element_address(kNoRegister, 0); |
| 936 if (IsExternal()) { |
| 937 UNIMPLEMENTED(); |
| 938 } else { |
| 939 ASSERT(this->array()->definition()->representation() == kTagged); |
| 940 ASSERT(index.IsRegister()); // TODO(regis): Revisit. |
| 941 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays |
| 942 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the |
| 943 // index is expected to be untagged before accessing. |
| 944 ASSERT(kSmiTagShift == 1); |
| 945 switch (index_scale()) { |
| 946 case 1: { |
| 947 __ SmiUntag(index.reg()); |
| 948 break; |
| 949 } |
| 950 case 2: { |
| 951 break; |
| 952 } |
| 953 case 4: { |
| 954 __ sll(index.reg(), index.reg(), 1); |
| 955 break; |
| 956 } |
| 957 case 8: { |
| 958 __ sll(index.reg(), index.reg(), 2); |
| 959 break; |
| 960 } |
| 961 case 16: { |
| 962 __ sll(index.reg(), index.reg(), 3); |
| 963 break; |
| 964 } |
| 965 default: |
| 966 UNREACHABLE(); |
| 967 } |
| 968 __ AddImmediate(index.reg(), |
| 969 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 970 __ addu(TMP1, array, index.reg()); |
| 971 element_address = Address(TMP1); |
| 972 } |
| 973 |
| 974 switch (class_id()) { |
| 975 case kArrayCid: |
| 976 if (ShouldEmitStoreBarrier()) { |
| 977 Register value = locs()->in(2).reg(); |
| 978 __ StoreIntoObject(array, element_address, value); |
| 979 } else if (locs()->in(2).IsConstant()) { |
| 980 const Object& constant = locs()->in(2).constant(); |
| 981 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 982 } else { |
| 983 Register value = locs()->in(2).reg(); |
| 984 __ StoreIntoObjectNoBarrier(array, element_address, value); |
| 985 } |
| 986 break; |
| 987 case kTypedDataInt8ArrayCid: |
| 988 case kTypedDataUint8ArrayCid: |
| 989 case kExternalTypedDataUint8ArrayCid: |
| 990 case kTypedDataUint8ClampedArrayCid: |
| 991 case kExternalTypedDataUint8ClampedArrayCid: |
| 992 case kTypedDataInt16ArrayCid: |
| 993 case kTypedDataUint16ArrayCid: |
| 994 case kTypedDataInt32ArrayCid: |
| 995 case kTypedDataUint32ArrayCid: |
| 996 case kTypedDataFloat32ArrayCid: |
| 997 case kTypedDataFloat64ArrayCid: |
| 998 case kTypedDataFloat32x4ArrayCid: |
| 999 UNIMPLEMENTED(); |
| 1000 break; |
| 1001 default: |
| 1002 UNREACHABLE(); |
| 1003 } |
| 863 } | 1004 } |
| 864 | 1005 |
| 865 | 1006 |
| 866 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { | 1007 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { |
| 867 UNIMPLEMENTED(); | 1008 const intptr_t kNumInputs = 1; |
| 868 return NULL; | 1009 LocationSummary* summary = |
| 1010 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); |
| 1011 summary->set_in(0, Location::RequiresRegister()); |
| 1012 if ((value()->Type()->ToCid() == kDynamicCid) && |
| 1013 (field().guarded_cid() != kSmiCid)) { |
| 1014 summary->AddTemp(Location::RequiresRegister()); |
| 1015 } |
| 1016 if (field().guarded_cid() == kIllegalCid) { |
| 1017 summary->AddTemp(Location::RequiresRegister()); |
| 1018 } |
| 1019 return summary; |
| 869 } | 1020 } |
| 870 | 1021 |
| 871 | 1022 |
| 872 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1023 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 873 UNIMPLEMENTED(); | 1024 __ TraceSimMsg("GuardFieldInstr"); |
| 1025 const intptr_t field_cid = field().guarded_cid(); |
| 1026 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1027 |
| 1028 if (field_cid == kDynamicCid) { |
| 1029 ASSERT(!compiler->is_optimizing()); |
| 1030 return; // Nothing to emit. |
| 1031 } |
| 1032 |
| 1033 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1034 |
| 1035 Register value_reg = locs()->in(0).reg(); |
| 1036 |
| 1037 Register value_cid_reg = ((value_cid == kDynamicCid) && |
| 1038 (field_cid != kSmiCid)) ? locs()->temp(0).reg() : kNoRegister; |
| 1039 |
| 1040 Register field_reg = (field_cid == kIllegalCid) ? |
| 1041 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; |
| 1042 |
| 1043 Label ok, fail_label; |
| 1044 |
| 1045 Label* deopt = compiler->is_optimizing() ? |
| 1046 compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL; |
| 1047 |
| 1048 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
| 1049 |
| 1050 const bool ok_is_fall_through = (deopt != NULL); |
| 1051 |
| 1052 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) { |
| 1053 if (!compiler->is_optimizing()) { |
| 1054 // Currently we can't have different location summaries for optimized |
| 1055 // and non-optimized code. So instead we manually pick up a register |
| 1056 // that is known to be free because we know how non-optimizing compiler |
| 1057 // allocates registers. |
| 1058 field_reg = A0; |
| 1059 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg)); |
| 1060 } |
| 1061 |
| 1062 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); |
| 1063 |
| 1064 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
| 1065 FieldAddress field_nullability_operand( |
| 1066 field_reg, Field::is_nullable_offset()); |
| 1067 |
| 1068 if (value_cid == kDynamicCid) { |
| 1069 if (value_cid_reg == kNoRegister) { |
| 1070 ASSERT(!compiler->is_optimizing()); |
| 1071 value_cid_reg = A1; |
| 1072 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); |
| 1073 } |
| 1074 |
| 1075 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1076 |
| 1077 __ lw(TMP1, field_cid_operand); |
| 1078 __ beq(value_cid_reg, TMP1, &ok); |
| 1079 __ lw(TMP1, field_nullability_operand); |
| 1080 __ subu(CMPRES, value_cid_reg, TMP1); |
| 1081 } else if (value_cid == kNullCid) { |
| 1082 // TODO(regis): TMP1 may conflict. Revisit. |
| 1083 __ lw(TMP1, field_nullability_operand); |
| 1084 __ LoadImmediate(TMP2, value_cid); |
| 1085 __ subu(CMPRES, TMP1, TMP2); |
| 1086 } else { |
| 1087 // TODO(regis): TMP1 may conflict. Revisit. |
| 1088 __ lw(TMP1, field_cid_operand); |
| 1089 __ LoadImmediate(TMP2, value_cid); |
| 1090 __ subu(CMPRES, TMP1, TMP2); |
| 1091 } |
| 1092 __ beq(CMPRES, ZR, &ok); |
| 1093 |
| 1094 __ lw(TMP1, field_cid_operand); |
| 1095 __ BranchNotEqual(TMP1, kIllegalCid, fail); |
| 1096 |
| 1097 if (value_cid == kDynamicCid) { |
| 1098 __ sw(value_cid_reg, field_cid_operand); |
| 1099 __ sw(value_cid_reg, field_nullability_operand); |
| 1100 } else { |
| 1101 __ LoadImmediate(TMP1, value_cid); |
| 1102 __ sw(TMP1, field_cid_operand); |
| 1103 __ sw(TMP1, field_nullability_operand); |
| 1104 } |
| 1105 |
| 1106 if (!ok_is_fall_through) { |
| 1107 __ b(&ok); |
| 1108 } |
| 1109 } else { |
| 1110 if (value_cid == kDynamicCid) { |
| 1111 // Field's guarded class id is fixed by value's class id is not known. |
| 1112 __ andi(CMPRES, value_reg, Immediate(kSmiTagMask)); |
| 1113 |
| 1114 if (field_cid != kSmiCid) { |
| 1115 __ beq(CMPRES, ZR, fail); |
| 1116 __ LoadClassId(value_cid_reg, value_reg); |
| 1117 __ LoadImmediate(TMP1, field_cid); |
| 1118 __ subu(CMPRES, value_cid_reg, TMP1); |
| 1119 } |
| 1120 |
| 1121 if (field().is_nullable() && (field_cid != kNullCid)) { |
| 1122 __ beq(CMPRES, ZR, &ok); |
| 1123 __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null())); |
| 1124 __ subu(CMPRES, value_reg, TMP1); |
| 1125 } |
| 1126 |
| 1127 if (ok_is_fall_through) { |
| 1128 __ bne(CMPRES, ZR, fail); |
| 1129 } else { |
| 1130 __ beq(CMPRES, ZR, &ok); |
| 1131 } |
| 1132 } else { |
| 1133 // Both value's and field's class id is known. |
| 1134 if ((value_cid != field_cid) && (value_cid != nullability)) { |
| 1135 if (ok_is_fall_through) { |
| 1136 __ b(fail); |
| 1137 } |
| 1138 } else { |
| 1139 // Nothing to emit. |
| 1140 ASSERT(!compiler->is_optimizing()); |
| 1141 return; |
| 1142 } |
| 1143 } |
| 1144 } |
| 1145 |
| 1146 if (deopt == NULL) { |
| 1147 ASSERT(!compiler->is_optimizing()); |
| 1148 __ Bind(fail); |
| 1149 |
| 1150 __ lw(TMP1, FieldAddress(field_reg, Field::guarded_cid_offset())); |
| 1151 __ BranchEqual(TMP1, kDynamicCid, &ok); |
| 1152 |
| 1153 __ Push(field_reg); |
| 1154 __ Push(value_reg); |
| 1155 __ CallRuntime(kUpdateFieldCidRuntimeEntry); |
| 1156 __ Drop(2); // Drop the field and the value. |
| 1157 } |
| 1158 |
| 1159 __ Bind(&ok); |
| 874 } | 1160 } |
| 875 | 1161 |
| 876 | 1162 |
| 877 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { | 1163 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { |
| 878 UNIMPLEMENTED(); | 1164 const intptr_t kNumInputs = 2; |
| 879 return NULL; | 1165 const intptr_t num_temps = 0; |
| 1166 LocationSummary* summary = |
| 1167 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1168 summary->set_in(0, Location::RequiresRegister()); |
| 1169 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1170 ? Location::WritableRegister() |
| 1171 : Location::RegisterOrConstant(value())); |
| 1172 return summary; |
| 880 } | 1173 } |
| 881 | 1174 |
| 882 | 1175 |
| 883 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1176 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 884 UNIMPLEMENTED(); | 1177 Register instance_reg = locs()->in(0).reg(); |
| 1178 if (ShouldEmitStoreBarrier()) { |
| 1179 Register value_reg = locs()->in(1).reg(); |
| 1180 __ StoreIntoObject(instance_reg, |
| 1181 FieldAddress(instance_reg, field().Offset()), |
| 1182 value_reg, |
| 1183 CanValueBeSmi()); |
| 1184 } else { |
| 1185 if (locs()->in(1).IsConstant()) { |
| 1186 __ StoreIntoObjectNoBarrier( |
| 1187 instance_reg, |
| 1188 FieldAddress(instance_reg, field().Offset()), |
| 1189 locs()->in(1).constant()); |
| 1190 } else { |
| 1191 Register value_reg = locs()->in(1).reg(); |
| 1192 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1193 FieldAddress(instance_reg, field().Offset()), value_reg); |
| 1194 } |
| 1195 } |
| 885 } | 1196 } |
| 886 | 1197 |
| 887 | 1198 |
| 888 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const { | 1199 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const { |
| 889 UNIMPLEMENTED(); | 1200 return LocationSummary::Make(0, |
| 890 return NULL; | 1201 Location::RequiresRegister(), |
| 1202 LocationSummary::kNoCall); |
| 891 } | 1203 } |
| 892 | 1204 |
| 893 | 1205 |
| 894 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1206 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 895 UNIMPLEMENTED(); | 1207 __ TraceSimMsg("LoadStaticFieldInstr"); |
| 1208 Register result = locs()->out().reg(); |
| 1209 __ LoadObject(result, field()); |
| 1210 __ lw(result, Address(result, Field::value_offset() - kHeapObjectTag)); |
| 896 } | 1211 } |
| 897 | 1212 |
| 898 | 1213 |
| 899 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const { | 1214 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const { |
| 900 UNIMPLEMENTED(); | 1215 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); |
| 901 return NULL; | 1216 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 1217 : Location::RequiresRegister()); |
| 1218 locs->set_temp(0, Location::RequiresRegister()); |
| 1219 return locs; |
| 902 } | 1220 } |
| 903 | 1221 |
| 904 | 1222 |
| 905 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1223 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 906 UNIMPLEMENTED(); | 1224 __ TraceSimMsg("StoreStaticFieldInstr"); |
| 907 } | 1225 Register value = locs()->in(0).reg(); |
| 908 | 1226 Register temp = locs()->temp(0).reg(); |
| 909 | 1227 |
| 1228 __ LoadObject(temp, field()); |
| 1229 if (this->value()->NeedsStoreBuffer()) { |
| 1230 __ StoreIntoObject(temp, |
| 1231 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); |
| 1232 } else { |
| 1233 __ StoreIntoObjectNoBarrier( |
| 1234 temp, FieldAddress(temp, Field::value_offset()), value); |
| 1235 } |
| 1236 } |
| 1237 |
| 1238 |
| 910 LocationSummary* InstanceOfInstr::MakeLocationSummary() const { | 1239 LocationSummary* InstanceOfInstr::MakeLocationSummary() const { |
| 911 UNIMPLEMENTED(); | 1240 UNIMPLEMENTED(); |
| 912 return NULL; | 1241 return NULL; |
| 913 } | 1242 } |
| 914 | 1243 |
| 915 | 1244 |
| 916 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1245 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 917 UNIMPLEMENTED(); | 1246 UNIMPLEMENTED(); |
| 918 } | 1247 } |
| 919 | 1248 |
| 920 | 1249 |
| 921 LocationSummary* CreateArrayInstr::MakeLocationSummary() const { | 1250 LocationSummary* CreateArrayInstr::MakeLocationSummary() const { |
| 922 UNIMPLEMENTED(); | 1251 const intptr_t kNumInputs = 1; |
| 923 return NULL; | 1252 const intptr_t kNumTemps = 0; |
| 1253 LocationSummary* locs = |
| 1254 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1255 locs->set_in(0, Location::RegisterLocation(A0)); |
| 1256 locs->set_out(Location::RegisterLocation(V0)); |
| 1257 return locs; |
| 924 } | 1258 } |
| 925 | 1259 |
| 926 | 1260 |
| 927 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1261 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 928 UNIMPLEMENTED(); | 1262 __ TraceSimMsg("CreateArrayInstr"); |
| 1263 // Allocate the array. A1 = length, A0 = element type. |
| 1264 ASSERT(locs()->in(0).reg() == A0); |
| 1265 __ LoadImmediate(A1, Smi::RawValue(num_elements())); |
| 1266 compiler->GenerateCall(token_pos(), |
| 1267 &StubCode::AllocateArrayLabel(), |
| 1268 PcDescriptors::kOther, |
| 1269 locs()); |
| 1270 ASSERT(locs()->out().reg() == V0); |
| 929 } | 1271 } |
| 930 | 1272 |
| 931 | 1273 |
| 932 LocationSummary* | 1274 LocationSummary* |
| 933 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { | 1275 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { |
| 934 UNIMPLEMENTED(); | 1276 UNIMPLEMENTED(); |
| 935 return NULL; | 1277 return NULL; |
| 936 } | 1278 } |
| 937 | 1279 |
| 938 | 1280 |
| 939 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( | 1281 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( |
| 940 FlowGraphCompiler* compiler) { | 1282 FlowGraphCompiler* compiler) { |
| 941 UNIMPLEMENTED(); | 1283 UNIMPLEMENTED(); |
| 942 } | 1284 } |
| 943 | 1285 |
| 944 | 1286 |
| 945 LocationSummary* LoadFieldInstr::MakeLocationSummary() const { | 1287 LocationSummary* LoadFieldInstr::MakeLocationSummary() const { |
| 946 UNIMPLEMENTED(); | 1288 return LocationSummary::Make(1, |
| 947 return NULL; | 1289 Location::RequiresRegister(), |
| 1290 LocationSummary::kNoCall); |
| 948 } | 1291 } |
| 949 | 1292 |
| 950 | 1293 |
| 951 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1294 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 952 UNIMPLEMENTED(); | 1295 Register instance_reg = locs()->in(0).reg(); |
| 1296 Register result_reg = locs()->out().reg(); |
| 1297 |
| 1298 __ lw(result_reg, Address(instance_reg, offset_in_bytes() - kHeapObjectTag)); |
| 953 } | 1299 } |
| 954 | 1300 |
| 955 | 1301 |
| 956 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const { | 1302 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const { |
| 957 UNIMPLEMENTED(); | 1303 const intptr_t kNumInputs = 1; |
| 958 return NULL; | 1304 const intptr_t kNumTemps = 1; |
| 1305 LocationSummary* locs = |
| 1306 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1307 locs->set_in(0, Location::RegisterLocation(T0)); |
| 1308 locs->set_temp(0, Location::RegisterLocation(T1)); |
| 1309 locs->set_out(Location::RegisterLocation(T0)); |
| 1310 return locs; |
| 959 } | 1311 } |
| 960 | 1312 |
| 961 | 1313 |
| 962 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 1314 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 963 FlowGraphCompiler* compiler) { | 1315 FlowGraphCompiler* compiler) { |
| 964 UNIMPLEMENTED(); | 1316 __ TraceSimMsg("InstantiateTypeArgumentsInstr"); |
| 1317 Register instantiator_reg = locs()->in(0).reg(); |
| 1318 Register temp = locs()->temp(0).reg(); |
| 1319 Register result_reg = locs()->out().reg(); |
| 1320 |
| 1321 // 'instantiator_reg' is the instantiator AbstractTypeArguments object |
| 1322 // (or null). |
| 1323 // If the instantiator is null and if the type argument vector |
| 1324 // instantiated from null becomes a vector of dynamic, then use null as |
| 1325 // the type arguments. |
| 1326 Label type_arguments_instantiated; |
| 1327 const intptr_t len = type_arguments().Length(); |
| 1328 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1329 __ BranchEqual(instantiator_reg, reinterpret_cast<intptr_t>(Object::null()), |
| 1330 &type_arguments_instantiated); |
| 1331 } |
| 1332 // Instantiate non-null type arguments. |
| 1333 if (type_arguments().IsUninstantiatedIdentity()) { |
| 1334 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1335 // matching length and, if so, use it as the instantiated type_arguments. |
| 1336 // No need to check the instantiator ('instantiator_reg') for null here, |
| 1337 // because a null instantiator will have the wrong class (Null instead of |
| 1338 // TypeArguments). |
| 1339 Label type_arguments_uninstantiated; |
| 1340 __ LoadClassId(temp, instantiator_reg); |
| 1341 __ BranchNotEqual(temp, kTypeArgumentsCid, &type_arguments_uninstantiated); |
| 1342 __ lw(temp, FieldAddress(instantiator_reg, TypeArguments::length_offset())); |
| 1343 __ BranchEqual(temp, Smi::RawValue(len), &type_arguments_instantiated); |
| 1344 __ Bind(&type_arguments_uninstantiated); |
| 1345 } |
| 1346 // A runtime call to instantiate the type arguments is required. |
| 1347 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1348 __ PushObject(type_arguments()); |
| 1349 __ Push(instantiator_reg); // Push instantiator type arguments. |
| 1350 compiler->GenerateCallRuntime(token_pos(), |
| 1351 deopt_id(), |
| 1352 kInstantiateTypeArgumentsRuntimeEntry, |
| 1353 locs()); |
| 1354 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1355 __ Pop(result_reg); // Pop instantiated type arguments. |
| 1356 __ Bind(&type_arguments_instantiated); |
| 1357 ASSERT(instantiator_reg == result_reg); |
| 1358 // 'result_reg': Instantiated type arguments. |
| 965 } | 1359 } |
| 966 | 1360 |
| 967 | 1361 |
| 968 LocationSummary* | 1362 LocationSummary* |
| 969 ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const { | 1363 ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const { |
| 970 UNIMPLEMENTED(); | 1364 const intptr_t kNumInputs = 1; |
| 971 return NULL; | 1365 const intptr_t kNumTemps = 1; |
| 1366 LocationSummary* locs = |
| 1367 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1368 locs->set_in(0, Location::RequiresRegister()); |
| 1369 locs->set_out(Location::SameAsFirstInput()); |
| 1370 locs->set_temp(0, Location::RequiresRegister()); |
| 1371 return locs; |
| 972 } | 1372 } |
| 973 | 1373 |
| 974 | 1374 |
| 975 void ExtractConstructorTypeArgumentsInstr::EmitNativeCode( | 1375 void ExtractConstructorTypeArgumentsInstr::EmitNativeCode( |
| 976 FlowGraphCompiler* compiler) { | 1376 FlowGraphCompiler* compiler) { |
| 977 UNIMPLEMENTED(); | 1377 Register instantiator_reg = locs()->in(0).reg(); |
| 1378 Register result_reg = locs()->out().reg(); |
| 1379 ASSERT(instantiator_reg == result_reg); |
| 1380 Register temp_reg = locs()->temp(0).reg(); |
| 1381 |
| 1382 // instantiator_reg is the instantiator type argument vector, i.e. an |
| 1383 // AbstractTypeArguments object (or null). |
| 1384 // If the instantiator is null and if the type argument vector |
| 1385 // instantiated from null becomes a vector of dynamic, then use null as |
| 1386 // the type arguments. |
| 1387 Label type_arguments_instantiated; |
| 1388 const intptr_t len = type_arguments().Length(); |
| 1389 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1390 __ BranchEqual(instantiator_reg, reinterpret_cast<intptr_t>(Object::null()), |
| 1391 &type_arguments_instantiated); |
| 1392 } |
| 1393 // Instantiate non-null type arguments. |
| 1394 if (type_arguments().IsUninstantiatedIdentity()) { |
| 1395 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1396 // matching length and, if so, use it as the instantiated type_arguments. |
| 1397 // No need to check instantiator_reg for null here, because a null |
| 1398 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1399 Label type_arguments_uninstantiated; |
| 1400 __ LoadClassId(temp_reg, instantiator_reg); |
| 1401 __ BranchNotEqual(temp_reg, kTypeArgumentsCid, |
| 1402 &type_arguments_uninstantiated); |
| 1403 __ lw(temp_reg, |
| 1404 FieldAddress(instantiator_reg, TypeArguments::length_offset())); |
| 1405 __ BranchEqual(temp_reg, Smi::RawValue(type_arguments().Length()), |
| 1406 &type_arguments_instantiated); |
| 1407 __ Bind(&type_arguments_uninstantiated); |
| 1408 } |
| 1409 // In the non-factory case, we rely on the allocation stub to |
| 1410 // instantiate the type arguments. |
| 1411 __ LoadObject(result_reg, type_arguments()); |
| 1412 // result_reg: uninstantiated type arguments. |
| 1413 __ Bind(&type_arguments_instantiated); |
| 1414 // result_reg: uninstantiated or instantiated type arguments. |
| 978 } | 1415 } |
| 979 | 1416 |
| 980 | 1417 |
| 981 LocationSummary* | 1418 LocationSummary* |
| 982 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { | 1419 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { |
| 983 UNIMPLEMENTED(); | 1420 const intptr_t kNumInputs = 1; |
| 984 return NULL; | 1421 const intptr_t kNumTemps = 1; |
| 1422 LocationSummary* locs = |
| 1423 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1424 locs->set_in(0, Location::RequiresRegister()); |
| 1425 locs->set_out(Location::SameAsFirstInput()); |
| 1426 locs->set_temp(0, Location::RequiresRegister()); |
| 1427 return locs; |
| 985 } | 1428 } |
| 986 | 1429 |
| 987 | 1430 |
| 988 void ExtractConstructorInstantiatorInstr::EmitNativeCode( | 1431 void ExtractConstructorInstantiatorInstr::EmitNativeCode( |
| 989 FlowGraphCompiler* compiler) { | 1432 FlowGraphCompiler* compiler) { |
| 990 UNIMPLEMENTED(); | 1433 Register instantiator_reg = locs()->in(0).reg(); |
| 1434 ASSERT(locs()->out().reg() == instantiator_reg); |
| 1435 Register temp_reg = locs()->temp(0).reg(); |
| 1436 |
| 1437 // instantiator_reg is the instantiator AbstractTypeArguments object |
| 1438 // (or null). If the instantiator is null and if the type argument vector |
| 1439 // instantiated from null becomes a vector of dynamic, then use null as |
| 1440 // the type arguments and do not pass the instantiator. |
| 1441 Label done; |
| 1442 const intptr_t len = type_arguments().Length(); |
| 1443 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1444 Label instantiator_not_null; |
| 1445 __ BranchNotEqual(instantiator_reg, |
| 1446 reinterpret_cast<intptr_t>(Object::null()), &instantiator_not_null); |
| 1447 // Null was used in VisitExtractConstructorTypeArguments as the |
| 1448 // instantiated type arguments, no proper instantiator needed. |
| 1449 __ LoadImmediate(instantiator_reg, |
| 1450 Smi::RawValue(StubCode::kNoInstantiator)); |
| 1451 __ b(&done); |
| 1452 __ Bind(&instantiator_not_null); |
| 1453 } |
| 1454 // Instantiate non-null type arguments. |
| 1455 if (type_arguments().IsUninstantiatedIdentity()) { |
| 1456 // TODO(regis): The following emitted code is duplicated in |
| 1457 // VisitExtractConstructorTypeArguments above. The reason is that the code |
| 1458 // is split between two computations, so that each one produces a |
| 1459 // single value, rather than producing a pair of values. |
| 1460 // If this becomes an issue, we should expose these tests at the IL level. |
| 1461 |
| 1462 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1463 // matching length and, if so, use it as the instantiated type_arguments. |
| 1464 // No need to check the instantiator ('instantiator_reg') for null here, |
| 1465 // because a null instantiator will have the wrong class (Null instead of |
| 1466 // TypeArguments). |
| 1467 __ LoadClassId(temp_reg, instantiator_reg); |
| 1468 __ BranchNotEqual(temp_reg, kTypeArgumentsCid, &done); |
| 1469 __ lw(temp_reg, |
| 1470 FieldAddress(instantiator_reg, TypeArguments::length_offset())); |
| 1471 __ BranchNotEqual(temp_reg, Smi::RawValue(type_arguments().Length()), |
| 1472 &done); |
| 1473 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
| 1474 // instantiated type arguments, no proper instantiator needed. |
| 1475 __ LoadImmediate(instantiator_reg, |
| 1476 Smi::RawValue(StubCode::kNoInstantiator)); |
| 1477 } |
| 1478 __ Bind(&done); |
| 1479 // instantiator_reg: instantiator or kNoInstantiator. |
| 991 } | 1480 } |
| 992 | 1481 |
| 993 | 1482 |
| 994 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { | 1483 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { |
| 995 UNIMPLEMENTED(); | 1484 UNIMPLEMENTED(); |
| 996 return NULL; | 1485 return NULL; |
| 997 } | 1486 } |
| 998 | 1487 |
| 999 | 1488 |
| 1000 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1489 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1034 return summary; | 1523 return summary; |
| 1035 } | 1524 } |
| 1036 | 1525 |
| 1037 | 1526 |
| 1038 class CheckStackOverflowSlowPath : public SlowPathCode { | 1527 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 1039 public: | 1528 public: |
| 1040 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 1529 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 1041 : instruction_(instruction) { } | 1530 : instruction_(instruction) { } |
| 1042 | 1531 |
| 1043 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1532 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1533 __ TraceSimMsg("CheckStackOverflowSlowPath"); |
| 1044 __ Comment("CheckStackOverflowSlowPath"); | 1534 __ Comment("CheckStackOverflowSlowPath"); |
| 1045 __ Bind(entry_label()); | 1535 __ Bind(entry_label()); |
| 1046 compiler->SaveLiveRegisters(instruction_->locs()); | 1536 compiler->SaveLiveRegisters(instruction_->locs()); |
| 1047 // pending_deoptimization_env_ is needed to generate a runtime call that | 1537 // pending_deoptimization_env_ is needed to generate a runtime call that |
| 1048 // may throw an exception. | 1538 // may throw an exception. |
| 1049 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 1539 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
| 1050 compiler->pending_deoptimization_env_ = instruction_->env(); | 1540 compiler->pending_deoptimization_env_ = instruction_->env(); |
| 1051 compiler->GenerateCallRuntime(instruction_->token_pos(), | 1541 compiler->GenerateCallRuntime(instruction_->token_pos(), |
| 1052 instruction_->deopt_id(), | 1542 instruction_->deopt_id(), |
| 1053 kStackOverflowRuntimeEntry, | 1543 kStackOverflowRuntimeEntry, |
| 1054 instruction_->locs()); | 1544 instruction_->locs()); |
| 1055 compiler->pending_deoptimization_env_ = NULL; | 1545 compiler->pending_deoptimization_env_ = NULL; |
| 1056 compiler->RestoreLiveRegisters(instruction_->locs()); | 1546 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 1057 __ b(exit_label()); | 1547 __ b(exit_label()); |
| 1058 } | 1548 } |
| 1059 | 1549 |
| 1060 private: | 1550 private: |
| 1061 CheckStackOverflowInstr* instruction_; | 1551 CheckStackOverflowInstr* instruction_; |
| 1062 }; | 1552 }; |
| 1063 | 1553 |
| 1064 | 1554 |
| 1065 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1555 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1556 __ TraceSimMsg("CheckStackOverflowInstr"); |
| 1066 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 1557 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 1067 compiler->AddSlowPathCode(slow_path); | 1558 compiler->AddSlowPathCode(slow_path); |
| 1068 | 1559 |
| 1069 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address()); | 1560 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address()); |
| 1070 | 1561 |
| 1071 __ lw(TMP1, Address(TMP1)); | 1562 __ lw(TMP1, Address(TMP1)); |
| 1072 __ BranchLessEqual(SP, TMP1, slow_path->entry_label()); | 1563 __ BranchLessEqual(SP, TMP1, slow_path->entry_label()); |
| 1073 | 1564 |
| 1074 __ Bind(slow_path->exit_label()); | 1565 __ Bind(slow_path->exit_label()); |
| 1075 } | 1566 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1088 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 1579 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 1089 // We make use of 3-operand instructions by not requiring result register | 1580 // We make use of 3-operand instructions by not requiring result register |
| 1090 // to be identical to first input register as on Intel. | 1581 // to be identical to first input register as on Intel. |
| 1091 summary->set_out(Location::RequiresRegister()); | 1582 summary->set_out(Location::RequiresRegister()); |
| 1092 return summary; | 1583 return summary; |
| 1093 } | 1584 } |
| 1094 } | 1585 } |
| 1095 | 1586 |
| 1096 | 1587 |
| 1097 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1588 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1589 __ TraceSimMsg("BinarySmiOpInstr"); |
| 1098 if (op_kind() == Token::kSHL) { | 1590 if (op_kind() == Token::kSHL) { |
| 1099 UNIMPLEMENTED(); | 1591 UNIMPLEMENTED(); |
| 1100 return; | 1592 return; |
| 1101 } | 1593 } |
| 1102 | 1594 |
| 1103 ASSERT(!is_truncating()); | 1595 ASSERT(!is_truncating()); |
| 1104 Register left = locs()->in(0).reg(); | 1596 Register left = locs()->in(0).reg(); |
| 1105 Register result = locs()->out().reg(); | 1597 Register result = locs()->out().reg(); |
| 1106 Label* deopt = NULL; | 1598 Label* deopt = NULL; |
| 1107 if (CanDeoptimize()) { | 1599 if (CanDeoptimize()) { |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1422 UNIMPLEMENTED(); | 1914 UNIMPLEMENTED(); |
| 1423 } | 1915 } |
| 1424 | 1916 |
| 1425 | 1917 |
| 1426 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { | 1918 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { |
| 1427 return MakeCallSummary(); | 1919 return MakeCallSummary(); |
| 1428 } | 1920 } |
| 1429 | 1921 |
| 1430 | 1922 |
| 1431 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1923 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1924 __ TraceSimMsg("PolymorphicInstanceCallInstr"); |
| 1432 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1925 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1433 kDeoptPolymorphicInstanceCallTestFail); | 1926 kDeoptPolymorphicInstanceCallTestFail); |
| 1434 if (ic_data().NumberOfChecks() == 0) { | 1927 if (ic_data().NumberOfChecks() == 0) { |
| 1435 __ b(deopt); | 1928 __ b(deopt); |
| 1436 return; | 1929 return; |
| 1437 } | 1930 } |
| 1438 ASSERT(ic_data().num_args_tested() == 1); | 1931 ASSERT(ic_data().num_args_tested() == 1); |
| 1439 if (!with_checks()) { | 1932 if (!with_checks()) { |
| 1440 ASSERT(ic_data().HasOneTarget()); | 1933 ASSERT(ic_data().HasOneTarget()); |
| 1441 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); | 1934 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); |
| 1442 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 1935 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| 1443 instance_call()->token_pos(), | 1936 instance_call()->token_pos(), |
| 1444 target, | 1937 target, |
| 1445 instance_call()->ArgumentCount(), | 1938 instance_call()->ArgumentCount(), |
| 1446 instance_call()->argument_names(), | 1939 instance_call()->argument_names(), |
| 1447 locs()); | 1940 locs()); |
| 1448 return; | 1941 return; |
| 1449 } | 1942 } |
| 1450 | 1943 |
| 1451 // Load receiver into R0. | 1944 // Load receiver into T0. |
| 1452 __ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1945 __ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
| 1453 | 1946 |
| 1454 LoadValueCid(compiler, T2, T0, | 1947 LoadValueCid(compiler, T2, T0, |
| 1455 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); | 1948 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); |
| 1456 | 1949 |
| 1457 compiler->EmitTestAndCall(ic_data(), | 1950 compiler->EmitTestAndCall(ic_data(), |
| 1458 T2, // Class id register. | 1951 T2, // Class id register. |
| 1459 instance_call()->ArgumentCount(), | 1952 instance_call()->ArgumentCount(), |
| 1460 instance_call()->argument_names(), | 1953 instance_call()->argument_names(), |
| 1461 deopt, | 1954 deopt, |
| 1462 instance_call()->deopt_id(), | 1955 instance_call()->deopt_id(), |
| 1463 instance_call()->token_pos(), | 1956 instance_call()->token_pos(), |
| 1464 locs()); | 1957 locs()); |
| 1465 } | 1958 } |
| 1466 | 1959 |
| 1467 | 1960 |
| 1468 LocationSummary* BranchInstr::MakeLocationSummary() const { | 1961 LocationSummary* BranchInstr::MakeLocationSummary() const { |
| 1469 UNREACHABLE(); | 1962 UNREACHABLE(); |
| 1470 return NULL; | 1963 return NULL; |
| 1471 } | 1964 } |
| 1472 | 1965 |
| 1473 | 1966 |
| 1474 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1967 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1968 __ TraceSimMsg("BranchInstr"); |
| 1475 comparison()->EmitBranchCode(compiler, this); | 1969 comparison()->EmitBranchCode(compiler, this); |
| 1476 } | 1970 } |
| 1477 | 1971 |
| 1478 | 1972 |
| 1479 LocationSummary* CheckClassInstr::MakeLocationSummary() const { | 1973 LocationSummary* CheckClassInstr::MakeLocationSummary() const { |
| 1480 UNIMPLEMENTED(); | 1974 UNIMPLEMENTED(); |
| 1481 return NULL; | 1975 return NULL; |
| 1482 } | 1976 } |
| 1483 | 1977 |
| 1484 | 1978 |
| 1485 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1979 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1486 UNIMPLEMENTED(); | 1980 UNIMPLEMENTED(); |
| 1487 } | 1981 } |
| 1488 | 1982 |
| 1489 | 1983 |
| 1490 LocationSummary* CheckSmiInstr::MakeLocationSummary() const { | 1984 LocationSummary* CheckSmiInstr::MakeLocationSummary() const { |
| 1491 const intptr_t kNumInputs = 1; | 1985 const intptr_t kNumInputs = 1; |
| 1492 const intptr_t kNumTemps = 0; | 1986 const intptr_t kNumTemps = 0; |
| 1493 LocationSummary* summary = | 1987 LocationSummary* summary = |
| 1494 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1988 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1495 summary->set_in(0, Location::RequiresRegister()); | 1989 summary->set_in(0, Location::RequiresRegister()); |
| 1496 return summary; | 1990 return summary; |
| 1497 } | 1991 } |
| 1498 | 1992 |
| 1499 | 1993 |
| 1500 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1994 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1995 __ TraceSimMsg("CheckSmiInstr"); |
| 1501 Register value = locs()->in(0).reg(); | 1996 Register value = locs()->in(0).reg(); |
| 1502 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 1997 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 1503 kDeoptCheckSmi); | 1998 kDeoptCheckSmi); |
| 1504 __ andi(TMP1, value, Immediate(kSmiTagMask)); | 1999 __ andi(TMP1, value, Immediate(kSmiTagMask)); |
| 1505 __ bne(TMP1, ZR, deopt); | 2000 __ bne(TMP1, ZR, deopt); |
| 1506 } | 2001 } |
| 1507 | 2002 |
| 1508 | 2003 |
| 1509 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { | 2004 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { |
| 1510 UNIMPLEMENTED(); | 2005 UNIMPLEMENTED(); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1566 return NULL; | 2061 return NULL; |
| 1567 } | 2062 } |
| 1568 | 2063 |
| 1569 | 2064 |
| 1570 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2065 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1571 UNIMPLEMENTED(); | 2066 UNIMPLEMENTED(); |
| 1572 } | 2067 } |
| 1573 | 2068 |
| 1574 | 2069 |
| 1575 LocationSummary* ThrowInstr::MakeLocationSummary() const { | 2070 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 1576 UNIMPLEMENTED(); | 2071 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 1577 return NULL; | |
| 1578 } | 2072 } |
| 1579 | 2073 |
| 1580 | 2074 |
| 1581 | 2075 |
| 1582 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2076 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1583 UNIMPLEMENTED(); | 2077 compiler->GenerateCallRuntime(token_pos(), |
| 2078 deopt_id(), |
| 2079 kThrowRuntimeEntry, |
| 2080 locs()); |
| 2081 __ break_(0); |
| 1584 } | 2082 } |
| 1585 | 2083 |
| 1586 | 2084 |
| 1587 LocationSummary* ReThrowInstr::MakeLocationSummary() const { | 2085 LocationSummary* ReThrowInstr::MakeLocationSummary() const { |
| 1588 UNIMPLEMENTED(); | 2086 UNIMPLEMENTED(); |
| 1589 return NULL; | 2087 return NULL; |
| 1590 } | 2088 } |
| 1591 | 2089 |
| 1592 | 2090 |
| 1593 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2091 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1594 UNIMPLEMENTED(); | 2092 UNIMPLEMENTED(); |
| 1595 } | 2093 } |
| 1596 | 2094 |
| 1597 | 2095 |
| 1598 LocationSummary* GotoInstr::MakeLocationSummary() const { | 2096 LocationSummary* GotoInstr::MakeLocationSummary() const { |
| 1599 return new LocationSummary(0, 0, LocationSummary::kNoCall); | 2097 return new LocationSummary(0, 0, LocationSummary::kNoCall); |
| 1600 } | 2098 } |
| 1601 | 2099 |
| 1602 | 2100 |
| 1603 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2101 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2102 __ TraceSimMsg("GotoInstr"); |
| 1604 // Add deoptimization descriptor for deoptimizing instructions | 2103 // Add deoptimization descriptor for deoptimizing instructions |
| 1605 // that may be inserted before this instruction. | 2104 // that may be inserted before this instruction. |
| 1606 if (!compiler->is_optimizing()) { | 2105 if (!compiler->is_optimizing()) { |
| 1607 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 2106 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 1608 GetDeoptId(), | 2107 GetDeoptId(), |
| 1609 0); // No token position. | 2108 0); // No token position. |
| 1610 } | 2109 } |
| 1611 | 2110 |
| 1612 if (HasParallelMove()) { | 2111 if (HasParallelMove()) { |
| 1613 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2112 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1632 default: | 2131 default: |
| 1633 OS::Print("Error: Condition not recognized: %d\n", condition); | 2132 OS::Print("Error: Condition not recognized: %d\n", condition); |
| 1634 UNIMPLEMENTED(); | 2133 UNIMPLEMENTED(); |
| 1635 return EQ; | 2134 return EQ; |
| 1636 } | 2135 } |
| 1637 } | 2136 } |
| 1638 | 2137 |
| 1639 | 2138 |
| 1640 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, | 2139 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 1641 bool value) { | 2140 bool value) { |
| 2141 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue"); |
| 1642 if (value && !compiler->CanFallThroughTo(true_successor())) { | 2142 if (value && !compiler->CanFallThroughTo(true_successor())) { |
| 1643 __ b(compiler->GetJumpLabel(true_successor())); | 2143 __ b(compiler->GetJumpLabel(true_successor())); |
| 1644 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { | 2144 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { |
| 1645 __ b(compiler->GetJumpLabel(false_successor())); | 2145 __ b(compiler->GetJumpLabel(false_successor())); |
| 1646 } | 2146 } |
| 1647 } | 2147 } |
| 1648 | 2148 |
| 1649 | 2149 |
| 1650 // The comparison result is in CMPRES. | 2150 // The comparison result is in CMPRES. |
| 1651 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, | 2151 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 1652 Condition true_condition) { | 2152 Condition true_condition) { |
| 2153 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); |
| 1653 if (compiler->CanFallThroughTo(false_successor())) { | 2154 if (compiler->CanFallThroughTo(false_successor())) { |
| 1654 // If the next block is the false successor we will fall through to it. | 2155 // If the next block is the false successor we will fall through to it. |
| 1655 Label* label = compiler->GetJumpLabel(true_successor()); | 2156 Label* label = compiler->GetJumpLabel(true_successor()); |
| 1656 switch (true_condition) { | 2157 switch (true_condition) { |
| 1657 case EQ: __ beq(CMPRES, ZR, label); break; | 2158 case EQ: __ beq(CMPRES, ZR, label); break; |
| 1658 case NE: __ bne(CMPRES, ZR, label); break; | 2159 case NE: __ bne(CMPRES, ZR, label); break; |
| 1659 case GT: __ bgtz(CMPRES, label); break; | 2160 case GT: __ bgtz(CMPRES, label); break; |
| 1660 case GE: __ bgez(CMPRES, label); break; | 2161 case GE: __ bgez(CMPRES, label); break; |
| 1661 case LT: __ bltz(CMPRES, label); break; | 2162 case LT: __ bltz(CMPRES, label); break; |
| 1662 case LE: __ blez(CMPRES, label); break; | 2163 case LE: __ blez(CMPRES, label); break; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1682 } | 2183 } |
| 1683 // Fall through or jump to the true successor. | 2184 // Fall through or jump to the true successor. |
| 1684 if (!compiler->CanFallThroughTo(true_successor())) { | 2185 if (!compiler->CanFallThroughTo(true_successor())) { |
| 1685 __ b(compiler->GetJumpLabel(true_successor())); | 2186 __ b(compiler->GetJumpLabel(true_successor())); |
| 1686 } | 2187 } |
| 1687 } | 2188 } |
| 1688 } | 2189 } |
| 1689 | 2190 |
| 1690 | 2191 |
| 1691 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { | 2192 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 1692 UNIMPLEMENTED(); | 2193 return LocationSummary::Make(0, |
| 1693 return NULL; | 2194 Location::RequiresRegister(), |
| 2195 LocationSummary::kNoCall); |
| 1694 } | 2196 } |
| 1695 | 2197 |
| 1696 | 2198 |
| 1697 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2199 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1698 UNIMPLEMENTED(); | 2200 __ mov(locs()->out().reg(), CTX); |
| 1699 } | 2201 } |
| 1700 | 2202 |
| 1701 | 2203 |
| 1702 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { | 2204 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { |
| 1703 const intptr_t kNumInputs = 2; | 2205 const intptr_t kNumInputs = 2; |
| 1704 const intptr_t kNumTemps = 0; | 2206 const intptr_t kNumTemps = 0; |
| 1705 LocationSummary* locs = | 2207 LocationSummary* locs = |
| 1706 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2208 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1707 locs->set_in(0, Location::RegisterOrConstant(left())); | 2209 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 1708 locs->set_in(1, Location::RegisterOrConstant(right())); | 2210 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 1709 locs->set_out(Location::RequiresRegister()); | 2211 locs->set_out(Location::RequiresRegister()); |
| 1710 return locs; | 2212 return locs; |
| 1711 } | 2213 } |
| 1712 | 2214 |
| 1713 | 2215 |
| 1714 // Special code for numbers (compare values instead of references.) | 2216 // Special code for numbers (compare values instead of references.) |
| 1715 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2217 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2218 __ TraceSimMsg("StrictCompareInstr"); |
| 1716 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 2219 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 1717 Location left = locs()->in(0); | 2220 Location left = locs()->in(0); |
| 1718 Location right = locs()->in(1); | 2221 Location right = locs()->in(1); |
| 1719 if (left.IsConstant() && right.IsConstant()) { | 2222 if (left.IsConstant() && right.IsConstant()) { |
| 1720 // TODO(vegorov): should be eliminated earlier by constant propagation. | 2223 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 1721 const bool result = (kind() == Token::kEQ_STRICT) ? | 2224 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 1722 left.constant().raw() == right.constant().raw() : | 2225 left.constant().raw() == right.constant().raw() : |
| 1723 left.constant().raw() != right.constant().raw(); | 2226 left.constant().raw() != right.constant().raw(); |
| 1724 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); | 2227 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); |
| 1725 return; | 2228 return; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1749 __ LoadObject(result, Bool::False()); | 2252 __ LoadObject(result, Bool::False()); |
| 1750 __ b(&done); | 2253 __ b(&done); |
| 1751 __ Bind(&load_true); | 2254 __ Bind(&load_true); |
| 1752 __ LoadObject(result, Bool::True()); | 2255 __ LoadObject(result, Bool::True()); |
| 1753 __ Bind(&done); | 2256 __ Bind(&done); |
| 1754 } | 2257 } |
| 1755 | 2258 |
| 1756 | 2259 |
| 1757 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 2260 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 1758 BranchInstr* branch) { | 2261 BranchInstr* branch) { |
| 2262 __ TraceSimMsg("StrictCompareInstr::EmitBranchCode"); |
| 1759 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 2263 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 1760 Location left = locs()->in(0); | 2264 Location left = locs()->in(0); |
| 1761 Location right = locs()->in(1); | 2265 Location right = locs()->in(1); |
| 1762 if (left.IsConstant() && right.IsConstant()) { | 2266 if (left.IsConstant() && right.IsConstant()) { |
| 1763 // TODO(vegorov): should be eliminated earlier by constant propagation. | 2267 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 1764 const bool result = (kind() == Token::kEQ_STRICT) ? | 2268 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 1765 left.constant().raw() == right.constant().raw() : | 2269 left.constant().raw() == right.constant().raw() : |
| 1766 left.constant().raw() != right.constant().raw(); | 2270 left.constant().raw() != right.constant().raw(); |
| 1767 branch->EmitBranchOnValue(compiler, result); | 2271 branch->EmitBranchOnValue(compiler, result); |
| 1768 return; | 2272 return; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1779 compiler->EmitEqualityRegRegCompare(left.reg(), | 2283 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 1780 right.reg(), | 2284 right.reg(), |
| 1781 needs_number_check()); | 2285 needs_number_check()); |
| 1782 } | 2286 } |
| 1783 | 2287 |
| 1784 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; | 2288 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; |
| 1785 branch->EmitBranchOnCondition(compiler, true_condition); | 2289 branch->EmitBranchOnCondition(compiler, true_condition); |
| 1786 } | 2290 } |
| 1787 | 2291 |
| 1788 | 2292 |
| 1789 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1790 UNIMPLEMENTED(); | |
| 1791 } | |
| 1792 | |
| 1793 | |
| 1794 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | 2293 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 1795 UNIMPLEMENTED(); | 2294 UNIMPLEMENTED(); |
| 1796 return NULL; | 2295 return NULL; |
| 1797 } | 2296 } |
| 1798 | 2297 |
| 1799 | 2298 |
| 1800 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2299 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1801 UNIMPLEMENTED(); | 2300 UNIMPLEMENTED(); |
| 1802 } | 2301 } |
| 1803 | 2302 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1823 UNIMPLEMENTED(); | 2322 UNIMPLEMENTED(); |
| 1824 } | 2323 } |
| 1825 | 2324 |
| 1826 | 2325 |
| 1827 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { | 2326 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { |
| 1828 return MakeCallSummary(); | 2327 return MakeCallSummary(); |
| 1829 } | 2328 } |
| 1830 | 2329 |
| 1831 | 2330 |
| 1832 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2331 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2332 __ TraceSimMsg("AllocateObjectInstr"); |
| 1833 const Class& cls = Class::ZoneHandle(constructor().Owner()); | 2333 const Class& cls = Class::ZoneHandle(constructor().Owner()); |
| 1834 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 2334 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 1835 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 2335 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 1836 compiler->GenerateCall(token_pos(), | 2336 compiler->GenerateCall(token_pos(), |
| 1837 &label, | 2337 &label, |
| 1838 PcDescriptors::kOther, | 2338 PcDescriptors::kOther, |
| 1839 locs()); | 2339 locs()); |
| 1840 __ Drop(ArgumentCount()); // Discard arguments. | 2340 __ Drop(ArgumentCount()); // Discard arguments. |
| 1841 } | 2341 } |
| 1842 | 2342 |
| 1843 | 2343 |
| 1844 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { | 2344 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { |
| 1845 UNIMPLEMENTED(); | 2345 return MakeCallSummary(); |
| 1846 return NULL; | |
| 1847 } | 2346 } |
| 1848 | 2347 |
| 1849 | 2348 |
| 1850 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2349 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1851 UNIMPLEMENTED(); | 2350 const Function& closure_function = function(); |
| 2351 ASSERT(!closure_function.IsImplicitStaticClosureFunction()); |
| 2352 const Code& stub = Code::Handle( |
| 2353 StubCode::GetAllocationStubForClosure(closure_function)); |
| 2354 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); |
| 2355 compiler->GenerateCall(token_pos(), |
| 2356 &label, |
| 2357 PcDescriptors::kOther, |
| 2358 locs()); |
| 2359 __ Drop(2); // Discard type arguments and receiver. |
| 1852 } | 2360 } |
| 1853 | 2361 |
| 1854 } // namespace dart | 2362 } // namespace dart |
| 1855 | 2363 |
| 1856 #endif // defined TARGET_ARCH_MIPS | 2364 #endif // defined TARGET_ARCH_MIPS |
| 1857 | 2365 |
| OLD | NEW |