| 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 // A finally clause may leave a previously pushed return value if it | 85 // A finally clause may leave a previously pushed return value if it |
| 86 // has its own return instruction. Method that have finally are currently | 86 // has its own return instruction. Method that have finally are currently |
| 87 // not optimized. | 87 // not optimized. |
| 88 if (!compiler->HasFinally()) { | 88 if (!compiler->HasFinally()) { |
| 89 Label stack_ok; | 89 Label stack_ok; |
| 90 __ Comment("Stack Check"); | 90 __ Comment("Stack Check"); |
| 91 __ TraceSimMsg("Stack Check"); | 91 __ TraceSimMsg("Stack Check"); |
| 92 const intptr_t fp_sp_dist = | 92 const intptr_t fp_sp_dist = |
| 93 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 93 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 94 ASSERT(fp_sp_dist <= 0); | 94 ASSERT(fp_sp_dist <= 0); |
| 95 __ subu(T2, SP, FP); | 95 __ subu(TMP1, SP, FP); |
| 96 | 96 |
| 97 __ BranchEqual(T2, fp_sp_dist, &stack_ok); | 97 __ BranchEqual(TMP1, fp_sp_dist, &stack_ok); |
| 98 __ break_(0); | 98 __ break_(0); |
| 99 | 99 |
| 100 __ Bind(&stack_ok); | 100 __ Bind(&stack_ok); |
| 101 } | 101 } |
| 102 #endif | 102 #endif |
| 103 // This sequence is patched by a debugger breakpoint. There is no need for | 103 // This sequence is patched by a debugger breakpoint. There is no need for |
| 104 // extra NOP instructions here because the sequence patched in for a | 104 // extra NOP instructions here because the sequence patched in for a |
| 105 // breakpoint is shorter than the sequence here. | 105 // breakpoint is shorter than the sequence here. |
| 106 __ LeaveDartFrameAndReturn(); | 106 __ LeaveDartFrameAndReturn(); |
| 107 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 107 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 locs->set_in(0, Location::RequiresRegister()); | 321 locs->set_in(0, Location::RequiresRegister()); |
| 322 locs->set_in(1, Location::RequiresRegister()); | 322 locs->set_in(1, Location::RequiresRegister()); |
| 323 locs->set_temp(0, Location::RequiresRegister()); | 323 locs->set_temp(0, Location::RequiresRegister()); |
| 324 locs->set_out(Location::RequiresRegister()); | 324 locs->set_out(Location::RequiresRegister()); |
| 325 return locs; | 325 return locs; |
| 326 } | 326 } |
| 327 if (IsPolymorphic()) { | 327 if (IsPolymorphic()) { |
| 328 const intptr_t kNumTemps = 1; | 328 const intptr_t kNumTemps = 1; |
| 329 LocationSummary* locs = | 329 LocationSummary* locs = |
| 330 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 330 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 331 UNIMPLEMENTED(); // TODO(regis): Verify register allocation. | 331 locs->set_in(0, Location::RegisterLocation(A1)); |
| 332 locs->set_in(1, Location::RegisterLocation(A0)); |
| 333 locs->set_temp(0, Location::RegisterLocation(T0)); |
| 334 locs->set_out(Location::RegisterLocation(V0)); |
| 332 return locs; | 335 return locs; |
| 333 } | 336 } |
| 334 const intptr_t kNumTemps = 1; | 337 const intptr_t kNumTemps = 1; |
| 335 LocationSummary* locs = | 338 LocationSummary* locs = |
| 336 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 339 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 337 locs->set_in(0, Location::RegisterLocation(A1)); | 340 locs->set_in(0, Location::RegisterLocation(A1)); |
| 338 locs->set_in(1, Location::RegisterLocation(A0)); | 341 locs->set_in(1, Location::RegisterLocation(A0)); |
| 339 locs->set_temp(0, Location::RegisterLocation(T0)); | 342 locs->set_temp(0, Location::RegisterLocation(T0)); |
| 340 locs->set_out(Location::RegisterLocation(V0)); | 343 locs->set_out(Location::RegisterLocation(V0)); |
| 341 return locs; | 344 return locs; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 356 if (!compiler->is_optimizing()) { | 359 if (!compiler->is_optimizing()) { |
| 357 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 360 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 358 deopt_id, | 361 deopt_id, |
| 359 token_pos); | 362 token_pos); |
| 360 } | 363 } |
| 361 const int kNumberOfArguments = 2; | 364 const int kNumberOfArguments = 2; |
| 362 const Array& kNoArgumentNames = Array::Handle(); | 365 const Array& kNoArgumentNames = Array::Handle(); |
| 363 const int kNumArgumentsChecked = 2; | 366 const int kNumArgumentsChecked = 2; |
| 364 | 367 |
| 365 Label check_identity; | 368 Label check_identity; |
| 366 __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null())); | 369 __ beq(A1, NULLREG, &check_identity); |
| 367 __ beq(A1, TMP1, &check_identity); | 370 __ beq(A0, NULLREG, &check_identity); |
| 368 __ beq(A0, TMP1, &check_identity); | |
| 369 | 371 |
| 370 ICData& equality_ic_data = ICData::ZoneHandle(); | 372 ICData& equality_ic_data = ICData::ZoneHandle(); |
| 371 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 373 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
| 372 ASSERT(!original_ic_data.IsNull()); | 374 ASSERT(!original_ic_data.IsNull()); |
| 373 if (original_ic_data.NumberOfChecks() == 0) { | 375 if (original_ic_data.NumberOfChecks() == 0) { |
| 374 // IC call for reoptimization populates original ICData. | 376 // IC call for reoptimization populates original ICData. |
| 375 equality_ic_data = original_ic_data.raw(); | 377 equality_ic_data = original_ic_data.raw(); |
| 376 } else { | 378 } else { |
| 377 // Megamorphic call. | 379 // Megamorphic call. |
| 378 equality_ic_data = original_ic_data.AsUnaryClassChecks(); | 380 equality_ic_data = original_ic_data.AsUnaryClassChecks(); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 case Token::kGT: return GT; | 491 case Token::kGT: return GT; |
| 490 case Token::kLTE: return LE; | 492 case Token::kLTE: return LE; |
| 491 case Token::kGTE: return GE; | 493 case Token::kGTE: return GE; |
| 492 default: | 494 default: |
| 493 UNREACHABLE(); | 495 UNREACHABLE(); |
| 494 return VS; | 496 return VS; |
| 495 } | 497 } |
| 496 } | 498 } |
| 497 | 499 |
| 498 | 500 |
| 501 // Branches on condition c assuming comparison results in CMPRES and TMP1. |
| 502 static void EmitBranchAfterCompare( |
| 503 FlowGraphCompiler* compiler, Condition c, Label* is_true) { |
| 504 switch (c) { |
| 505 case EQ: __ beq(CMPRES, TMP1, is_true); break; |
| 506 case NE: __ bne(CMPRES, TMP1, is_true); break; |
| 507 case GT: __ bne(TMP1, ZR, is_true); break; |
| 508 case GE: __ beq(CMPRES, ZR, is_true); break; |
| 509 case LT: __ bne(CMPRES, ZR, is_true); break; |
| 510 case LE: __ beq(TMP1, ZR, is_true); break; |
| 511 default: |
| 512 UNREACHABLE(); |
| 513 break; |
| 514 } |
| 515 } |
| 516 |
| 517 |
| 499 static Condition FlipCondition(Condition condition) { | 518 static Condition FlipCondition(Condition condition) { |
| 500 UNIMPLEMENTED(); | 519 UNIMPLEMENTED(); |
| 501 return condition; | 520 return condition; |
| 502 } | 521 } |
| 503 | 522 |
| 504 | 523 |
| 505 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 524 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 506 const LocationSummary& locs, | 525 const LocationSummary& locs, |
| 507 Token::Kind kind, | 526 Token::Kind kind, |
| 508 BranchInstr* branch) { | 527 BranchInstr* branch) { |
| 509 __ TraceSimMsg("EmitSmiComparisonOp"); | 528 __ TraceSimMsg("EmitSmiComparisonOp"); |
| 510 Location left = locs.in(0); | 529 Location left = locs.in(0); |
| 511 Location right = locs.in(1); | 530 Location right = locs.in(1); |
| 512 ASSERT(!left.IsConstant() || !right.IsConstant()); | 531 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 513 | 532 |
| 514 Condition true_condition = TokenKindToSmiCondition(kind); | 533 Condition true_condition = TokenKindToSmiCondition(kind); |
| 515 | 534 |
| 516 if (left.IsConstant()) { | 535 if (left.IsConstant()) { |
| 517 __ CompareObject(CMPRES, right.reg(), left.constant()); | 536 __ CompareObject(CMPRES, TMP1, right.reg(), left.constant()); |
| 518 true_condition = FlipCondition(true_condition); | 537 true_condition = FlipCondition(true_condition); |
| 519 } else if (right.IsConstant()) { | 538 } else if (right.IsConstant()) { |
| 520 __ CompareObject(CMPRES, left.reg(), right.constant()); | 539 __ CompareObject(CMPRES, TMP1, left.reg(), right.constant()); |
| 521 } else { | 540 } else { |
| 522 __ subu(CMPRES, left.reg(), right.reg()); | 541 __ slt(CMPRES, left.reg(), right.reg()); |
| 542 __ slt(TMP1, right.reg(), left.reg()); |
| 523 } | 543 } |
| 524 | 544 |
| 525 if (branch != NULL) { | 545 if (branch != NULL) { |
| 526 branch->EmitBranchOnCondition(compiler, true_condition); | 546 branch->EmitBranchOnCondition(compiler, true_condition); |
| 527 } else { | 547 } else { |
| 528 Register result = locs.out().reg(); | 548 Register result = locs.out().reg(); |
| 529 Label done, is_true; | 549 Label done, is_true; |
| 530 switch (true_condition) { | 550 EmitBranchAfterCompare(compiler, true_condition, &is_true); |
| 531 case EQ: __ beq(CMPRES, ZR, &is_true); break; | |
| 532 case NE: __ bne(CMPRES, ZR, &is_true); break; | |
| 533 case GT: __ bgtz(CMPRES, &is_true); break; | |
| 534 case GE: __ bgez(CMPRES, &is_true); break; | |
| 535 case LT: __ bltz(CMPRES, &is_true); break; | |
| 536 case LE: __ blez(CMPRES, &is_true); break; | |
| 537 default: | |
| 538 UNREACHABLE(); | |
| 539 break; | |
| 540 } | |
| 541 __ LoadObject(result, Bool::False()); | 551 __ LoadObject(result, Bool::False()); |
| 542 __ b(&done); | 552 __ b(&done); |
| 543 __ Bind(&is_true); | 553 __ Bind(&is_true); |
| 544 __ LoadObject(result, Bool::True()); | 554 __ LoadObject(result, Bool::True()); |
| 545 __ Bind(&done); | 555 __ Bind(&done); |
| 546 } | 556 } |
| 547 } | 557 } |
| 548 | 558 |
| 549 | 559 |
| 550 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 560 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 EmitEqualityAsInstanceCall(compiler, | 658 EmitEqualityAsInstanceCall(compiler, |
| 649 deopt_id(), | 659 deopt_id(), |
| 650 token_pos(), | 660 token_pos(), |
| 651 Token::kEQ, // kNE reverse occurs at branch. | 661 Token::kEQ, // kNE reverse occurs at branch. |
| 652 locs(), | 662 locs(), |
| 653 *ic_data()); | 663 *ic_data()); |
| 654 if (branch->is_checked()) { | 664 if (branch->is_checked()) { |
| 655 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler); | 665 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler); |
| 656 } | 666 } |
| 657 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; | 667 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; |
| 658 __ CompareObject(CMPRES, V0, Bool::True()); | 668 __ CompareObject(CMPRES, TMP1, V0, Bool::True()); |
| 659 branch->EmitBranchOnCondition(compiler, branch_condition); | 669 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 660 } | 670 } |
| 661 | 671 |
| 662 | 672 |
| 663 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 673 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 664 const intptr_t kNumInputs = 2; | 674 const intptr_t kNumInputs = 2; |
| 665 const intptr_t kNumTemps = 0; | 675 const intptr_t kNumTemps = 0; |
| 666 if (operands_class_id() == kMintCid) { | 676 if (operands_class_id() == kMintCid) { |
| 667 const intptr_t kNumTemps = 2; | 677 const intptr_t kNumTemps = 2; |
| 668 LocationSummary* locs = | 678 LocationSummary* locs = |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 } | 794 } |
| 785 if (operands_class_id() == kMintCid) { | 795 if (operands_class_id() == kMintCid) { |
| 786 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); | 796 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); |
| 787 return; | 797 return; |
| 788 } | 798 } |
| 789 if (operands_class_id() == kDoubleCid) { | 799 if (operands_class_id() == kDoubleCid) { |
| 790 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 800 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 791 return; | 801 return; |
| 792 } | 802 } |
| 793 EmitNativeCode(compiler); | 803 EmitNativeCode(compiler); |
| 794 __ CompareObject(CMPRES, V0, Bool::True()); | 804 __ CompareObject(CMPRES, TMP1, V0, Bool::True()); |
| 795 branch->EmitBranchOnCondition(compiler, EQ); | 805 branch->EmitBranchOnCondition(compiler, EQ); |
| 796 } | 806 } |
| 797 | 807 |
| 798 | 808 |
| 799 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 809 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 800 const intptr_t kNumInputs = 0; | 810 const intptr_t kNumInputs = 0; |
| 801 const intptr_t kNumTemps = 3; | 811 const intptr_t kNumTemps = 3; |
| 802 LocationSummary* locs = | 812 LocationSummary* locs = |
| 803 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 813 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 804 locs->set_temp(0, Location::RegisterLocation(A1)); | 814 locs->set_temp(0, Location::RegisterLocation(A1)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 858 return NULL; | 868 return NULL; |
| 859 } | 869 } |
| 860 | 870 |
| 861 | 871 |
| 862 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 872 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 863 UNIMPLEMENTED(); | 873 UNIMPLEMENTED(); |
| 864 } | 874 } |
| 865 | 875 |
| 866 | 876 |
| 867 LocationSummary* LoadClassIdInstr::MakeLocationSummary() const { | 877 LocationSummary* LoadClassIdInstr::MakeLocationSummary() const { |
| 868 UNIMPLEMENTED(); | 878 const intptr_t kNumInputs = 1; |
| 869 return NULL; | 879 return LocationSummary::Make(kNumInputs, |
| 880 Location::RequiresRegister(), |
| 881 LocationSummary::kNoCall); |
| 870 } | 882 } |
| 871 | 883 |
| 872 | 884 |
| 873 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 885 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 874 UNIMPLEMENTED(); | 886 Register object = locs()->in(0).reg(); |
| 887 Register result = locs()->out().reg(); |
| 888 Label load, done; |
| 889 __ andi(CMPRES, object, Immediate(kSmiTagMask)); |
| 890 __ bne(CMPRES, ZR, &load); |
| 891 __ LoadImmediate(result, Smi::RawValue(kSmiCid)); |
| 892 __ b(&done); |
| 893 __ Bind(&load); |
| 894 __ LoadClassId(result, object); |
| 895 __ SmiTag(result); |
| 896 __ Bind(&done); |
| 875 } | 897 } |
| 876 | 898 |
| 877 | 899 |
| 878 CompileType LoadIndexedInstr::ComputeType() const { | 900 CompileType LoadIndexedInstr::ComputeType() const { |
| 879 switch (class_id_) { | 901 switch (class_id_) { |
| 880 case kArrayCid: | 902 case kArrayCid: |
| 881 case kImmutableArrayCid: | 903 case kImmutableArrayCid: |
| 882 return CompileType::Dynamic(); | 904 return CompileType::Dynamic(); |
| 883 | 905 |
| 884 case kTypedDataFloat32ArrayCid: | 906 case kTypedDataFloat32ArrayCid: |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 __ sll(index.reg(), index.reg(), 2); | 1015 __ sll(index.reg(), index.reg(), 2); |
| 994 break; | 1016 break; |
| 995 } | 1017 } |
| 996 case 16: { | 1018 case 16: { |
| 997 __ sll(index.reg(), index.reg(), 3); | 1019 __ sll(index.reg(), index.reg(), 3); |
| 998 break; | 1020 break; |
| 999 } | 1021 } |
| 1000 default: | 1022 default: |
| 1001 UNREACHABLE(); | 1023 UNREACHABLE(); |
| 1002 } | 1024 } |
| 1003 __ AddImmediate(index.reg(), | 1025 __ addu(index.reg(), array, index.reg()); |
| 1026 element_address = Address(index.reg(), |
| 1004 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1027 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 1005 element_address = Address(array, index.reg()); | |
| 1006 } | 1028 } |
| 1007 | 1029 |
| 1008 if ((representation() == kUnboxedDouble) || | 1030 if ((representation() == kUnboxedDouble) || |
| 1009 (representation() == kUnboxedMint) || | 1031 (representation() == kUnboxedMint) || |
| 1010 (representation() == kUnboxedFloat32x4)) { | 1032 (representation() == kUnboxedFloat32x4)) { |
| 1011 UNIMPLEMENTED(); | 1033 UNIMPLEMENTED(); |
| 1012 } | 1034 } |
| 1013 | 1035 |
| 1014 Register result = locs()->out().reg(); | 1036 Register result = locs()->out().reg(); |
| 1015 if ((index_scale() == 1) && index.IsRegister()) { | |
| 1016 __ SmiUntag(index.reg()); | |
| 1017 } | |
| 1018 switch (class_id()) { | 1037 switch (class_id()) { |
| 1019 case kTypedDataInt8ArrayCid: | 1038 case kTypedDataInt8ArrayCid: |
| 1020 ASSERT(index_scale() == 1); | 1039 ASSERT(index_scale() == 1); |
| 1021 __ lb(result, element_address); | 1040 __ lb(result, element_address); |
| 1022 __ SmiTag(result); | 1041 __ SmiTag(result); |
| 1023 break; | 1042 break; |
| 1024 case kTypedDataUint8ArrayCid: | 1043 case kTypedDataUint8ArrayCid: |
| 1025 case kTypedDataUint8ClampedArrayCid: | 1044 case kTypedDataUint8ClampedArrayCid: |
| 1026 case kExternalTypedDataUint8ArrayCid: | 1045 case kExternalTypedDataUint8ArrayCid: |
| 1027 case kExternalTypedDataUint8ClampedArrayCid: | 1046 case kExternalTypedDataUint8ClampedArrayCid: |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 default: | 1079 default: |
| 1061 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1080 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1062 __ lw(result, element_address); | 1081 __ lw(result, element_address); |
| 1063 break; | 1082 break; |
| 1064 } | 1083 } |
| 1065 } | 1084 } |
| 1066 | 1085 |
| 1067 | 1086 |
| 1068 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1087 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1069 intptr_t idx) const { | 1088 intptr_t idx) const { |
| 1070 UNIMPLEMENTED(); | 1089 // Array can be a Dart object or a pointer to external data. |
| 1071 return kTagged; | 1090 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
| 1091 if (idx == 1) return kTagged; // Index is a smi. |
| 1092 ASSERT(idx == 2); |
| 1093 switch (class_id_) { |
| 1094 case kArrayCid: |
| 1095 case kOneByteStringCid: |
| 1096 case kTypedDataInt8ArrayCid: |
| 1097 case kTypedDataUint8ArrayCid: |
| 1098 case kExternalTypedDataUint8ArrayCid: |
| 1099 case kTypedDataUint8ClampedArrayCid: |
| 1100 case kExternalTypedDataUint8ClampedArrayCid: |
| 1101 case kTypedDataInt16ArrayCid: |
| 1102 case kTypedDataUint16ArrayCid: |
| 1103 return kTagged; |
| 1104 case kTypedDataInt32ArrayCid: |
| 1105 case kTypedDataUint32ArrayCid: |
| 1106 return value()->IsSmiValue() ? kTagged : kUnboxedMint; |
| 1107 case kTypedDataFloat32ArrayCid: |
| 1108 case kTypedDataFloat64ArrayCid: |
| 1109 return kUnboxedDouble; |
| 1110 case kTypedDataFloat32x4ArrayCid: |
| 1111 return kUnboxedFloat32x4; |
| 1112 default: |
| 1113 UNIMPLEMENTED(); |
| 1114 return kTagged; |
| 1115 } |
| 1072 } | 1116 } |
| 1073 | 1117 |
| 1074 | 1118 |
| 1075 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { | 1119 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
| 1076 const intptr_t kNumInputs = 3; | 1120 const intptr_t kNumInputs = 3; |
| 1077 const intptr_t kNumTemps = 0; | 1121 const intptr_t kNumTemps = 0; |
| 1078 LocationSummary* locs = | 1122 LocationSummary* locs = |
| 1079 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1123 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1080 locs->set_in(0, Location::RequiresRegister()); | 1124 locs->set_in(0, Location::RequiresRegister()); |
| 1081 // The smi index is either untagged (element size == 1), or it is left smi | 1125 // The smi index is either untagged (element size == 1), or it is left smi |
| 1082 // tagged (for all element sizes > 1). | 1126 // tagged (for all element sizes > 1). |
| 1083 // TODO(regis): Revisit and see if the index can be immediate. | 1127 // TODO(regis): Revisit and see if the index can be immediate. |
| 1084 locs->set_in(1, Location::WritableRegister()); | 1128 locs->set_in(1, Location::WritableRegister()); |
| 1085 switch (class_id()) { | 1129 switch (class_id()) { |
| 1086 case kArrayCid: | 1130 case kArrayCid: |
| 1087 locs->set_in(2, ShouldEmitStoreBarrier() | 1131 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1088 ? Location::WritableRegister() | 1132 ? Location::WritableRegister() |
| 1089 : Location::RegisterOrConstant(value())); | 1133 : Location::RegisterOrConstant(value())); |
| 1090 break; | 1134 break; |
| 1091 case kExternalTypedDataUint8ArrayCid: | 1135 case kExternalTypedDataUint8ArrayCid: |
| 1092 case kExternalTypedDataUint8ClampedArrayCid: | 1136 case kExternalTypedDataUint8ClampedArrayCid: |
| 1093 case kTypedDataInt8ArrayCid: | 1137 case kTypedDataInt8ArrayCid: |
| 1094 case kTypedDataUint8ArrayCid: | 1138 case kTypedDataUint8ArrayCid: |
| 1095 case kTypedDataUint8ClampedArrayCid: | 1139 case kTypedDataUint8ClampedArrayCid: |
| 1096 case kOneByteStringCid: | 1140 case kOneByteStringCid: |
| 1141 locs->set_in(2, Location::RegisterOrSmiConstant(value())); |
| 1142 break; |
| 1097 case kTypedDataInt16ArrayCid: | 1143 case kTypedDataInt16ArrayCid: |
| 1098 case kTypedDataUint16ArrayCid: | 1144 case kTypedDataUint16ArrayCid: |
| 1099 case kTypedDataInt32ArrayCid: | 1145 case kTypedDataInt32ArrayCid: |
| 1100 case kTypedDataUint32ArrayCid: | 1146 case kTypedDataUint32ArrayCid: |
| 1147 locs->set_in(2, Location::WritableRegister()); |
| 1148 break; |
| 1101 case kTypedDataFloat32ArrayCid: | 1149 case kTypedDataFloat32ArrayCid: |
| 1102 case kTypedDataFloat64ArrayCid: | 1150 // TODO(regis): Verify. |
| 1151 // Need temp register for float-to-double conversion. |
| 1152 locs->AddTemp(Location::RequiresFpuRegister()); |
| 1153 // Fall through. |
| 1154 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. |
| 1103 case kTypedDataFloat32x4ArrayCid: | 1155 case kTypedDataFloat32x4ArrayCid: |
| 1104 UNIMPLEMENTED(); | 1156 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1105 break; | 1157 break; |
| 1106 default: | 1158 default: |
| 1107 UNREACHABLE(); | 1159 UNREACHABLE(); |
| 1108 return NULL; | 1160 return NULL; |
| 1109 } | 1161 } |
| 1110 return locs; | 1162 return locs; |
| 1111 } | 1163 } |
| 1112 | 1164 |
| 1113 | 1165 |
| 1114 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1166 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1142 __ sll(index.reg(), index.reg(), 2); | 1194 __ sll(index.reg(), index.reg(), 2); |
| 1143 break; | 1195 break; |
| 1144 } | 1196 } |
| 1145 case 16: { | 1197 case 16: { |
| 1146 __ sll(index.reg(), index.reg(), 3); | 1198 __ sll(index.reg(), index.reg(), 3); |
| 1147 break; | 1199 break; |
| 1148 } | 1200 } |
| 1149 default: | 1201 default: |
| 1150 UNREACHABLE(); | 1202 UNREACHABLE(); |
| 1151 } | 1203 } |
| 1152 __ AddImmediate(index.reg(), | 1204 __ addu(index.reg(), array, index.reg()); |
| 1205 element_address = Address(index.reg(), |
| 1153 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1206 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 1154 __ addu(TMP1, array, index.reg()); | |
| 1155 element_address = Address(TMP1); | |
| 1156 } | 1207 } |
| 1157 | 1208 |
| 1158 switch (class_id()) { | 1209 switch (class_id()) { |
| 1159 case kArrayCid: | 1210 case kArrayCid: |
| 1160 if (ShouldEmitStoreBarrier()) { | 1211 if (ShouldEmitStoreBarrier()) { |
| 1161 Register value = locs()->in(2).reg(); | 1212 Register value = locs()->in(2).reg(); |
| 1162 __ StoreIntoObject(array, element_address, value); | 1213 __ StoreIntoObject(array, element_address, value); |
| 1163 } else if (locs()->in(2).IsConstant()) { | 1214 } else if (locs()->in(2).IsConstant()) { |
| 1164 const Object& constant = locs()->in(2).constant(); | 1215 const Object& constant = locs()->in(2).constant(); |
| 1165 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1216 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 1166 } else { | 1217 } else { |
| 1167 Register value = locs()->in(2).reg(); | 1218 Register value = locs()->in(2).reg(); |
| 1168 __ StoreIntoObjectNoBarrier(array, element_address, value); | 1219 __ StoreIntoObjectNoBarrier(array, element_address, value); |
| 1169 } | 1220 } |
| 1170 break; | 1221 break; |
| 1171 case kTypedDataInt8ArrayCid: | 1222 case kTypedDataInt8ArrayCid: |
| 1172 case kTypedDataUint8ArrayCid: | 1223 case kTypedDataUint8ArrayCid: |
| 1173 case kExternalTypedDataUint8ArrayCid: | 1224 case kExternalTypedDataUint8ArrayCid: |
| 1225 case kOneByteStringCid: { |
| 1226 if (locs()->in(2).IsConstant()) { |
| 1227 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1228 __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value())); |
| 1229 __ sb(TMP, element_address); |
| 1230 } else { |
| 1231 Register value = locs()->in(2).reg(); |
| 1232 __ SmiUntag(value); |
| 1233 __ sb(value, element_address); |
| 1234 } |
| 1235 break; |
| 1236 } |
| 1174 case kTypedDataUint8ClampedArrayCid: | 1237 case kTypedDataUint8ClampedArrayCid: |
| 1175 case kExternalTypedDataUint8ClampedArrayCid: | 1238 case kExternalTypedDataUint8ClampedArrayCid: { |
| 1176 case kOneByteStringCid: | 1239 if (locs()->in(2).IsConstant()) { |
| 1240 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1241 intptr_t value = constant.Value(); |
| 1242 // Clamp to 0x0 or 0xFF respectively. |
| 1243 if (value > 0xFF) { |
| 1244 value = 0xFF; |
| 1245 } else if (value < 0) { |
| 1246 value = 0; |
| 1247 } |
| 1248 __ LoadImmediate(TMP, static_cast<int8_t>(value)); |
| 1249 __ sb(TMP, element_address); |
| 1250 } else { |
| 1251 Register value = locs()->in(2).reg(); |
| 1252 Label store_value, bigger, smaller; |
| 1253 __ SmiUntag(value); |
| 1254 __ BranchUnsignedLess(value, 0xFF + 1, &store_value); |
| 1255 __ LoadImmediate(TMP, 0xFF); |
| 1256 __ slti(CMPRES, value, Immediate(1)); |
| 1257 __ movn(TMP, ZR, CMPRES); |
| 1258 __ mov(value, TMP); |
| 1259 __ Bind(&store_value); |
| 1260 __ sb(value, element_address); |
| 1261 } |
| 1262 break; |
| 1263 } |
| 1177 case kTypedDataInt16ArrayCid: | 1264 case kTypedDataInt16ArrayCid: |
| 1178 case kTypedDataUint16ArrayCid: | 1265 case kTypedDataUint16ArrayCid: { |
| 1266 Register value = locs()->in(2).reg(); |
| 1267 __ SmiUntag(value); |
| 1268 __ sh(value, element_address); |
| 1269 break; |
| 1270 } |
| 1179 case kTypedDataInt32ArrayCid: | 1271 case kTypedDataInt32ArrayCid: |
| 1180 case kTypedDataUint32ArrayCid: | 1272 case kTypedDataUint32ArrayCid: { |
| 1273 if (value()->IsSmiValue()) { |
| 1274 ASSERT(RequiredInputRepresentation(2) == kTagged); |
| 1275 Register value = locs()->in(2).reg(); |
| 1276 __ SmiUntag(value); |
| 1277 __ sw(value, element_address); |
| 1278 } else { |
| 1279 UNIMPLEMENTED(); |
| 1280 } |
| 1281 break; |
| 1282 } |
| 1181 case kTypedDataFloat32ArrayCid: | 1283 case kTypedDataFloat32ArrayCid: |
| 1182 case kTypedDataFloat64ArrayCid: | 1284 case kTypedDataFloat64ArrayCid: |
| 1183 case kTypedDataFloat32x4ArrayCid: | 1285 case kTypedDataFloat32x4ArrayCid: |
| 1184 UNIMPLEMENTED(); | 1286 UNIMPLEMENTED(); |
| 1185 break; | 1287 break; |
| 1186 default: | 1288 default: |
| 1187 UNREACHABLE(); | 1289 UNREACHABLE(); |
| 1188 } | 1290 } |
| 1189 } | 1291 } |
| 1190 | 1292 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 | 1400 |
| 1299 if (field_cid != kSmiCid) { | 1401 if (field_cid != kSmiCid) { |
| 1300 __ beq(CMPRES, ZR, fail); | 1402 __ beq(CMPRES, ZR, fail); |
| 1301 __ LoadClassId(value_cid_reg, value_reg); | 1403 __ LoadClassId(value_cid_reg, value_reg); |
| 1302 __ LoadImmediate(TMP1, field_cid); | 1404 __ LoadImmediate(TMP1, field_cid); |
| 1303 __ subu(CMPRES, value_cid_reg, TMP1); | 1405 __ subu(CMPRES, value_cid_reg, TMP1); |
| 1304 } | 1406 } |
| 1305 | 1407 |
| 1306 if (field().is_nullable() && (field_cid != kNullCid)) { | 1408 if (field().is_nullable() && (field_cid != kNullCid)) { |
| 1307 __ beq(CMPRES, ZR, &ok); | 1409 __ beq(CMPRES, ZR, &ok); |
| 1308 __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null())); | 1410 __ subu(CMPRES, value_reg, NULLREG); |
| 1309 __ subu(CMPRES, value_reg, TMP1); | |
| 1310 } | 1411 } |
| 1311 | 1412 |
| 1312 if (ok_is_fall_through) { | 1413 if (ok_is_fall_through) { |
| 1313 __ bne(CMPRES, ZR, fail); | 1414 __ bne(CMPRES, ZR, fail); |
| 1314 } else { | 1415 } else { |
| 1315 __ beq(CMPRES, ZR, &ok); | 1416 __ beq(CMPRES, ZR, &ok); |
| 1316 } | 1417 } |
| 1317 } else { | 1418 } else { |
| 1318 // Both value's and field's class id is known. | 1419 // Both value's and field's class id is known. |
| 1319 if ((value_cid != field_cid) && (value_cid != nullability)) { | 1420 if ((value_cid != field_cid) && (value_cid != nullability)) { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1506 // (or null). | 1607 // (or null). |
| 1507 if (!type_arguments().IsUninstantiatedIdentity() && | 1608 if (!type_arguments().IsUninstantiatedIdentity() && |
| 1508 !type_arguments().CanShareInstantiatorTypeArguments( | 1609 !type_arguments().CanShareInstantiatorTypeArguments( |
| 1509 instantiator_class())) { | 1610 instantiator_class())) { |
| 1510 // If the instantiator is null and if the type argument vector | 1611 // If the instantiator is null and if the type argument vector |
| 1511 // instantiated from null becomes a vector of dynamic, then use null as | 1612 // instantiated from null becomes a vector of dynamic, then use null as |
| 1512 // the type arguments. | 1613 // the type arguments. |
| 1513 Label type_arguments_instantiated; | 1614 Label type_arguments_instantiated; |
| 1514 const intptr_t len = type_arguments().Length(); | 1615 const intptr_t len = type_arguments().Length(); |
| 1515 if (type_arguments().IsRawInstantiatedRaw(len)) { | 1616 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1516 __ BranchEqual(instantiator_reg, | 1617 __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated); |
| 1517 reinterpret_cast<intptr_t>(Object::null()), | |
| 1518 &type_arguments_instantiated); | |
| 1519 } | 1618 } |
| 1520 // Instantiate non-null type arguments. | 1619 // Instantiate non-null type arguments. |
| 1521 // A runtime call to instantiate the type arguments is required. | 1620 // A runtime call to instantiate the type arguments is required. |
| 1522 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1621 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 1523 __ LoadObject(TMP1, Object::ZoneHandle()); | 1622 __ LoadObject(TMP1, Object::ZoneHandle()); |
| 1524 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Make room for the result. | 1623 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Make room for the result. |
| 1525 __ LoadObject(TMP1, type_arguments()); | 1624 __ LoadObject(TMP1, type_arguments()); |
| 1526 __ sw(TMP1, Address(SP, 1 * kWordSize)); | 1625 __ sw(TMP1, Address(SP, 1 * kWordSize)); |
| 1527 // Push instantiator type arguments. | 1626 // Push instantiator type arguments. |
| 1528 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); | 1627 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1563 // instantiator_reg is the instantiator type argument vector, i.e. an | 1662 // instantiator_reg is the instantiator type argument vector, i.e. an |
| 1564 // AbstractTypeArguments object (or null). | 1663 // AbstractTypeArguments object (or null). |
| 1565 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 1664 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 1566 !type_arguments().CanShareInstantiatorTypeArguments( | 1665 !type_arguments().CanShareInstantiatorTypeArguments( |
| 1567 instantiator_class())); | 1666 instantiator_class())); |
| 1568 // If the instantiator is null and if the type argument vector | 1667 // If the instantiator is null and if the type argument vector |
| 1569 // instantiated from null becomes a vector of dynamic, then use null as | 1668 // instantiated from null becomes a vector of dynamic, then use null as |
| 1570 // the type arguments. | 1669 // the type arguments. |
| 1571 Label type_arguments_instantiated; | 1670 Label type_arguments_instantiated; |
| 1572 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); | 1671 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); |
| 1573 __ BranchEqual(instantiator_reg, | 1672 __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated); |
| 1574 reinterpret_cast<intptr_t>(Object::null()), | |
| 1575 &type_arguments_instantiated); | |
| 1576 // Instantiate non-null type arguments. | 1673 // Instantiate non-null type arguments. |
| 1577 // In the non-factory case, we rely on the allocation stub to | 1674 // In the non-factory case, we rely on the allocation stub to |
| 1578 // instantiate the type arguments. | 1675 // instantiate the type arguments. |
| 1579 __ LoadObject(result_reg, type_arguments()); | 1676 __ LoadObject(result_reg, type_arguments()); |
| 1580 // result_reg: uninstantiated type arguments. | 1677 // result_reg: uninstantiated type arguments. |
| 1581 __ Bind(&type_arguments_instantiated); | 1678 __ Bind(&type_arguments_instantiated); |
| 1582 | 1679 |
| 1583 // result_reg: uninstantiated or instantiated type arguments. | 1680 // result_reg: uninstantiated or instantiated type arguments. |
| 1584 } | 1681 } |
| 1585 | 1682 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1605 // (or null). | 1702 // (or null). |
| 1606 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 1703 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 1607 !type_arguments().CanShareInstantiatorTypeArguments( | 1704 !type_arguments().CanShareInstantiatorTypeArguments( |
| 1608 instantiator_class())); | 1705 instantiator_class())); |
| 1609 | 1706 |
| 1610 // If the instantiator is null and if the type argument vector | 1707 // If the instantiator is null and if the type argument vector |
| 1611 // instantiated from null becomes a vector of dynamic, then use null as | 1708 // instantiated from null becomes a vector of dynamic, then use null as |
| 1612 // the type arguments and do not pass the instantiator. | 1709 // the type arguments and do not pass the instantiator. |
| 1613 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); | 1710 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); |
| 1614 Label instantiator_not_null; | 1711 Label instantiator_not_null; |
| 1615 __ BranchNotEqual(instantiator_reg, | 1712 __ bne(instantiator_reg, NULLREG, &instantiator_not_null); |
| 1616 reinterpret_cast<intptr_t>(Object::null()), &instantiator_not_null); | |
| 1617 // Null was used in VisitExtractConstructorTypeArguments as the | 1713 // Null was used in VisitExtractConstructorTypeArguments as the |
| 1618 // instantiated type arguments, no proper instantiator needed. | 1714 // instantiated type arguments, no proper instantiator needed. |
| 1619 __ LoadImmediate(instantiator_reg, | 1715 __ LoadImmediate(instantiator_reg, |
| 1620 Smi::RawValue(StubCode::kNoInstantiator)); | 1716 Smi::RawValue(StubCode::kNoInstantiator)); |
| 1621 __ Bind(&instantiator_not_null); | 1717 __ Bind(&instantiator_not_null); |
| 1622 // instantiator_reg: instantiator or kNoInstantiator. | 1718 // instantiator_reg: instantiator or kNoInstantiator. |
| 1623 } | 1719 } |
| 1624 | 1720 |
| 1625 | 1721 |
| 1626 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { | 1722 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1680 | 1776 |
| 1681 ASSERT(!exception_var().is_captured()); | 1777 ASSERT(!exception_var().is_captured()); |
| 1682 ASSERT(!stacktrace_var().is_captured()); | 1778 ASSERT(!stacktrace_var().is_captured()); |
| 1683 | 1779 |
| 1684 __ sw(kExceptionObjectReg, | 1780 __ sw(kExceptionObjectReg, |
| 1685 Address(FP, exception_var().index() * kWordSize)); | 1781 Address(FP, exception_var().index() * kWordSize)); |
| 1686 __ sw(kStackTraceObjectReg, | 1782 __ sw(kStackTraceObjectReg, |
| 1687 Address(FP, stacktrace_var().index() * kWordSize)); | 1783 Address(FP, stacktrace_var().index() * kWordSize)); |
| 1688 | 1784 |
| 1689 Label next; | 1785 Label next; |
| 1690 __ mov(T0, RA); // Save return adress. | 1786 __ mov(TMP, RA); // Save return adress. |
| 1691 // Restore the pool pointer. | 1787 // Restore the pool pointer. |
| 1692 __ bal(&next); // Branch and link to next instruction to get PC in RA. | 1788 __ bal(&next); // Branch and link to next instruction to get PC in RA. |
| 1693 __ delay_slot()->mov(T1, RA); // Save PC of the following mov. | 1789 __ delay_slot()->mov(CMPRES, RA); // Save PC of the following mov. |
| 1694 | 1790 |
| 1695 // Calculate offset of pool pointer from the PC. | 1791 // Calculate offset of pool pointer from the PC. |
| 1696 const intptr_t object_pool_pc_dist = | 1792 const intptr_t object_pool_pc_dist = |
| 1697 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 1793 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 1698 compiler->assembler()->CodeSize(); | 1794 compiler->assembler()->CodeSize(); |
| 1699 | 1795 |
| 1700 __ Bind(&next); | 1796 __ Bind(&next); |
| 1701 __ mov(RA, T0); // Restore return address. | 1797 __ mov(RA, TMP); // Restore return address. |
| 1702 __ lw(PP, Address(T1, -object_pool_pc_dist)); | 1798 __ lw(PP, Address(CMPRES, -object_pool_pc_dist)); |
| 1703 } | 1799 } |
| 1704 | 1800 |
| 1705 | 1801 |
| 1706 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const { | 1802 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const { |
| 1707 const intptr_t kNumInputs = 0; | 1803 const intptr_t kNumInputs = 0; |
| 1708 const intptr_t kNumTemps = 0; | 1804 const intptr_t kNumTemps = 0; |
| 1709 LocationSummary* summary = | 1805 LocationSummary* summary = |
| 1710 new LocationSummary(kNumInputs, | 1806 new LocationSummary(kNumInputs, |
| 1711 kNumTemps, | 1807 kNumTemps, |
| 1712 LocationSummary::kCallOnSlowPath); | 1808 LocationSummary::kCallOnSlowPath); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1755 __ Bind(slow_path->exit_label()); | 1851 __ Bind(slow_path->exit_label()); |
| 1756 } | 1852 } |
| 1757 | 1853 |
| 1758 | 1854 |
| 1759 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { | 1855 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { |
| 1760 const intptr_t kNumInputs = 2; | 1856 const intptr_t kNumInputs = 2; |
| 1761 if (op_kind() == Token::kTRUNCDIV) { | 1857 if (op_kind() == Token::kTRUNCDIV) { |
| 1762 UNIMPLEMENTED(); | 1858 UNIMPLEMENTED(); |
| 1763 return NULL; | 1859 return NULL; |
| 1764 } else { | 1860 } else { |
| 1765 const intptr_t kNumTemps = 0; | 1861 const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0; |
| 1766 LocationSummary* summary = | 1862 LocationSummary* summary = |
| 1767 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1863 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1768 summary->set_in(0, Location::RequiresRegister()); | 1864 summary->set_in(0, Location::RequiresRegister()); |
| 1769 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 1865 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 1770 if (op_kind() == Token::kADD) { | 1866 if (op_kind() == Token::kADD) { |
| 1771 // Need an extra temp for the overflow detection code. | 1867 // Need an extra temp for the overflow detection code. |
| 1772 summary->set_temp(0, Location::RequiresRegister()); | 1868 summary->set_temp(0, Location::RequiresRegister()); |
| 1773 } | 1869 } |
| 1774 // We make use of 3-operand instructions by not requiring result register | 1870 // We make use of 3-operand instructions by not requiring result register |
| 1775 // to be identical to first input register as on Intel. | 1871 // to be identical to first input register as on Intel. |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2407 summary->AddTemp(Location::RequiresRegister()); | 2503 summary->AddTemp(Location::RequiresRegister()); |
| 2408 } | 2504 } |
| 2409 return summary; | 2505 return summary; |
| 2410 } | 2506 } |
| 2411 | 2507 |
| 2412 | 2508 |
| 2413 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2509 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2414 if (null_check()) { | 2510 if (null_check()) { |
| 2415 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2511 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2416 kDeoptCheckClass); | 2512 kDeoptCheckClass); |
| 2417 __ BranchEqual(locs()->in(0).reg(), | 2513 __ beq(locs()->in(0).reg(), NULLREG, deopt); |
| 2418 reinterpret_cast<intptr_t>(Object::null()), deopt); | |
| 2419 return; | 2514 return; |
| 2420 } | 2515 } |
| 2421 | 2516 |
| 2422 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 2517 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| 2423 (unary_checks().NumberOfChecks() > 1)); | 2518 (unary_checks().NumberOfChecks() > 1)); |
| 2424 Register value = locs()->in(0).reg(); | 2519 Register value = locs()->in(0).reg(); |
| 2425 Register temp = locs()->temp(0).reg(); | 2520 Register temp = locs()->temp(0).reg(); |
| 2426 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2521 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2427 kDeoptCheckClass); | 2522 kDeoptCheckClass); |
| 2428 Label is_ok; | 2523 Label is_ok; |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2661 } | 2756 } |
| 2662 | 2757 |
| 2663 | 2758 |
| 2664 // The comparison result is in CMPRES. | 2759 // The comparison result is in CMPRES. |
| 2665 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, | 2760 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 2666 Condition true_condition) { | 2761 Condition true_condition) { |
| 2667 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); | 2762 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); |
| 2668 if (compiler->CanFallThroughTo(false_successor())) { | 2763 if (compiler->CanFallThroughTo(false_successor())) { |
| 2669 // If the next block is the false successor we will fall through to it. | 2764 // If the next block is the false successor we will fall through to it. |
| 2670 Label* label = compiler->GetJumpLabel(true_successor()); | 2765 Label* label = compiler->GetJumpLabel(true_successor()); |
| 2671 switch (true_condition) { | 2766 EmitBranchAfterCompare(compiler, true_condition, label); |
| 2672 case EQ: __ beq(CMPRES, ZR, label); break; | |
| 2673 case NE: __ bne(CMPRES, ZR, label); break; | |
| 2674 case GT: __ bgtz(CMPRES, label); break; | |
| 2675 case GE: __ bgez(CMPRES, label); break; | |
| 2676 case LT: __ bltz(CMPRES, label); break; | |
| 2677 case LE: __ blez(CMPRES, label); break; | |
| 2678 default: | |
| 2679 UNREACHABLE(); | |
| 2680 break; | |
| 2681 } | |
| 2682 } else { | 2767 } else { |
| 2683 // If the next block is the true successor we negate comparison and fall | 2768 // If the next block is the true successor we negate comparison and fall |
| 2684 // through to it. | 2769 // through to it. |
| 2685 Condition false_condition = NegateCondition(true_condition); | 2770 Condition false_condition = NegateCondition(true_condition); |
| 2686 Label* label = compiler->GetJumpLabel(false_successor()); | 2771 Label* label = compiler->GetJumpLabel(false_successor()); |
| 2687 switch (false_condition) { | 2772 EmitBranchAfterCompare(compiler, false_condition, label); |
| 2688 case EQ: __ beq(CMPRES, ZR, label); break; | |
| 2689 case NE: __ bne(CMPRES, ZR, label); break; | |
| 2690 case GT: __ bgtz(CMPRES, label); break; | |
| 2691 case GE: __ bgez(CMPRES, label); break; | |
| 2692 case LT: __ bltz(CMPRES, label); break; | |
| 2693 case LE: __ blez(CMPRES, label); break; | |
| 2694 default: | |
| 2695 UNREACHABLE(); | |
| 2696 break; | |
| 2697 } | |
| 2698 // Fall through or jump to the true successor. | 2773 // Fall through or jump to the true successor. |
| 2699 if (!compiler->CanFallThroughTo(true_successor())) { | 2774 if (!compiler->CanFallThroughTo(true_successor())) { |
| 2700 __ b(compiler->GetJumpLabel(true_successor())); | 2775 __ b(compiler->GetJumpLabel(true_successor())); |
| 2701 } | 2776 } |
| 2702 } | 2777 } |
| 2703 } | 2778 } |
| 2704 | 2779 |
| 2705 | 2780 |
| 2706 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { | 2781 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 2707 return LocationSummary::Make(0, | 2782 return LocationSummary::Make(0, |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2857 locs->set_in(1, Location::RequiresRegister()); | 2932 locs->set_in(1, Location::RequiresRegister()); |
| 2858 return locs; | 2933 return locs; |
| 2859 } | 2934 } |
| 2860 | 2935 |
| 2861 | 2936 |
| 2862 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2937 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2863 Register value_reg = locs()->in(0).reg(); | 2938 Register value_reg = locs()->in(0).reg(); |
| 2864 Register dest_reg = locs()->in(1).reg(); | 2939 Register dest_reg = locs()->in(1).reg(); |
| 2865 | 2940 |
| 2866 if (value()->NeedsStoreBuffer()) { | 2941 if (value()->NeedsStoreBuffer()) { |
| 2867 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), | 2942 __ StoreIntoObject(dest_reg, |
| 2868 value_reg); | 2943 FieldAddress(dest_reg, offset_in_bytes()), value_reg); |
| 2869 } else { | 2944 } else { |
| 2870 __ StoreIntoObjectNoBarrier( | 2945 __ StoreIntoObjectNoBarrier(dest_reg, |
| 2871 dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg); | 2946 FieldAddress(dest_reg, offset_in_bytes()), value_reg); |
| 2872 } | 2947 } |
| 2873 } | 2948 } |
| 2874 | 2949 |
| 2875 | 2950 |
| 2876 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { | 2951 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { |
| 2877 return MakeCallSummary(); | 2952 return MakeCallSummary(); |
| 2878 } | 2953 } |
| 2879 | 2954 |
| 2880 | 2955 |
| 2881 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2956 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2905 compiler->GenerateCall(token_pos(), | 2980 compiler->GenerateCall(token_pos(), |
| 2906 &label, | 2981 &label, |
| 2907 PcDescriptors::kOther, | 2982 PcDescriptors::kOther, |
| 2908 locs()); | 2983 locs()); |
| 2909 __ Drop(2); // Discard type arguments and receiver. | 2984 __ Drop(2); // Discard type arguments and receiver. |
| 2910 } | 2985 } |
| 2911 | 2986 |
| 2912 } // namespace dart | 2987 } // namespace dart |
| 2913 | 2988 |
| 2914 #endif // defined TARGET_ARCH_MIPS | 2989 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |