| 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 void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 518 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 500 const LocationSummary& locs, | 519 const LocationSummary& locs, |
| 501 Token::Kind kind, | 520 Token::Kind kind, |
| 502 BranchInstr* branch) { | 521 BranchInstr* branch) { |
| 503 __ TraceSimMsg("EmitSmiComparisonOp"); | 522 __ TraceSimMsg("EmitSmiComparisonOp"); |
| 504 Location left = locs.in(0); | 523 Location left = locs.in(0); |
| 505 Location right = locs.in(1); | 524 Location right = locs.in(1); |
| 506 ASSERT(!left.IsConstant() || !right.IsConstant()); | 525 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 507 | 526 |
| 508 Condition true_condition = TokenKindToSmiCondition(kind); | 527 Condition true_condition = TokenKindToSmiCondition(kind); |
| 509 | 528 |
| 510 if (left.IsConstant()) { | 529 if (left.IsConstant()) { |
| 511 __ CompareObject(CMPRES, right.reg(), left.constant()); | 530 __ CompareObject(CMPRES, TMP1, right.reg(), left.constant()); |
| 512 true_condition = FlowGraphCompiler::FlipCondition(true_condition); | 531 true_condition = FlowGraphCompiler::FlipCondition(true_condition); |
| 513 } else if (right.IsConstant()) { | 532 } else if (right.IsConstant()) { |
| 514 __ CompareObject(CMPRES, left.reg(), right.constant()); | 533 __ CompareObject(CMPRES, TMP1, left.reg(), right.constant()); |
| 515 } else { | 534 } else { |
| 516 __ subu(CMPRES, left.reg(), right.reg()); | 535 __ slt(CMPRES, left.reg(), right.reg()); |
| 536 __ slt(TMP1, right.reg(), left.reg()); |
| 517 } | 537 } |
| 518 | 538 |
| 519 if (branch != NULL) { | 539 if (branch != NULL) { |
| 520 branch->EmitBranchOnCondition(compiler, true_condition); | 540 branch->EmitBranchOnCondition(compiler, true_condition); |
| 521 } else { | 541 } else { |
| 522 Register result = locs.out().reg(); | 542 Register result = locs.out().reg(); |
| 523 Label done, is_true; | 543 Label done, is_true; |
| 524 switch (true_condition) { | 544 EmitBranchAfterCompare(compiler, true_condition, &is_true); |
| 525 case EQ: __ beq(CMPRES, ZR, &is_true); break; | |
| 526 case NE: __ bne(CMPRES, ZR, &is_true); break; | |
| 527 case GT: __ bgtz(CMPRES, &is_true); break; | |
| 528 case GE: __ bgez(CMPRES, &is_true); break; | |
| 529 case LT: __ bltz(CMPRES, &is_true); break; | |
| 530 case LE: __ blez(CMPRES, &is_true); break; | |
| 531 default: | |
| 532 UNREACHABLE(); | |
| 533 break; | |
| 534 } | |
| 535 __ LoadObject(result, Bool::False()); | 545 __ LoadObject(result, Bool::False()); |
| 536 __ b(&done); | 546 __ b(&done); |
| 537 __ Bind(&is_true); | 547 __ Bind(&is_true); |
| 538 __ LoadObject(result, Bool::True()); | 548 __ LoadObject(result, Bool::True()); |
| 539 __ Bind(&done); | 549 __ Bind(&done); |
| 540 } | 550 } |
| 541 } | 551 } |
| 542 | 552 |
| 543 | 553 |
| 544 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 554 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 EmitEqualityAsInstanceCall(compiler, | 652 EmitEqualityAsInstanceCall(compiler, |
| 643 deopt_id(), | 653 deopt_id(), |
| 644 token_pos(), | 654 token_pos(), |
| 645 Token::kEQ, // kNE reverse occurs at branch. | 655 Token::kEQ, // kNE reverse occurs at branch. |
| 646 locs(), | 656 locs(), |
| 647 *ic_data()); | 657 *ic_data()); |
| 648 if (branch->is_checked()) { | 658 if (branch->is_checked()) { |
| 649 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler); | 659 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler); |
| 650 } | 660 } |
| 651 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; | 661 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; |
| 652 __ CompareObject(CMPRES, V0, Bool::True()); | 662 __ CompareObject(CMPRES, TMP1, V0, Bool::True()); |
| 653 branch->EmitBranchOnCondition(compiler, branch_condition); | 663 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 654 } | 664 } |
| 655 | 665 |
| 656 | 666 |
| 657 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 667 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 658 const intptr_t kNumInputs = 2; | 668 const intptr_t kNumInputs = 2; |
| 659 const intptr_t kNumTemps = 0; | 669 const intptr_t kNumTemps = 0; |
| 660 if (operands_class_id() == kMintCid) { | 670 if (operands_class_id() == kMintCid) { |
| 661 const intptr_t kNumTemps = 2; | 671 const intptr_t kNumTemps = 2; |
| 662 LocationSummary* locs = | 672 LocationSummary* locs = |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 } | 788 } |
| 779 if (operands_class_id() == kMintCid) { | 789 if (operands_class_id() == kMintCid) { |
| 780 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); | 790 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); |
| 781 return; | 791 return; |
| 782 } | 792 } |
| 783 if (operands_class_id() == kDoubleCid) { | 793 if (operands_class_id() == kDoubleCid) { |
| 784 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 794 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 785 return; | 795 return; |
| 786 } | 796 } |
| 787 EmitNativeCode(compiler); | 797 EmitNativeCode(compiler); |
| 788 __ CompareObject(CMPRES, V0, Bool::True()); | 798 __ CompareObject(CMPRES, TMP1, V0, Bool::True()); |
| 789 branch->EmitBranchOnCondition(compiler, EQ); | 799 branch->EmitBranchOnCondition(compiler, EQ); |
| 790 } | 800 } |
| 791 | 801 |
| 792 | 802 |
| 793 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 803 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 794 const intptr_t kNumInputs = 0; | 804 const intptr_t kNumInputs = 0; |
| 795 const intptr_t kNumTemps = 3; | 805 const intptr_t kNumTemps = 3; |
| 796 LocationSummary* locs = | 806 LocationSummary* locs = |
| 797 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 807 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 798 locs->set_temp(0, Location::RegisterLocation(A1)); | 808 locs->set_temp(0, Location::RegisterLocation(A1)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 return NULL; | 862 return NULL; |
| 853 } | 863 } |
| 854 | 864 |
| 855 | 865 |
| 856 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 866 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 857 UNIMPLEMENTED(); | 867 UNIMPLEMENTED(); |
| 858 } | 868 } |
| 859 | 869 |
| 860 | 870 |
| 861 LocationSummary* LoadClassIdInstr::MakeLocationSummary() const { | 871 LocationSummary* LoadClassIdInstr::MakeLocationSummary() const { |
| 862 UNIMPLEMENTED(); | 872 const intptr_t kNumInputs = 1; |
| 863 return NULL; | 873 return LocationSummary::Make(kNumInputs, |
| 874 Location::RequiresRegister(), |
| 875 LocationSummary::kNoCall); |
| 864 } | 876 } |
| 865 | 877 |
| 866 | 878 |
| 867 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 879 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 868 UNIMPLEMENTED(); | 880 Register object = locs()->in(0).reg(); |
| 881 Register result = locs()->out().reg(); |
| 882 Label load, done; |
| 883 __ andi(CMPRES, object, Immediate(kSmiTagMask)); |
| 884 __ bne(CMPRES, ZR, &load); |
| 885 __ LoadImmediate(result, Smi::RawValue(kSmiCid)); |
| 886 __ b(&done); |
| 887 __ Bind(&load); |
| 888 __ LoadClassId(result, object); |
| 889 __ SmiTag(result); |
| 890 __ Bind(&done); |
| 869 } | 891 } |
| 870 | 892 |
| 871 | 893 |
| 872 CompileType LoadIndexedInstr::ComputeType() const { | 894 CompileType LoadIndexedInstr::ComputeType() const { |
| 873 switch (class_id_) { | 895 switch (class_id_) { |
| 874 case kArrayCid: | 896 case kArrayCid: |
| 875 case kImmutableArrayCid: | 897 case kImmutableArrayCid: |
| 876 return CompileType::Dynamic(); | 898 return CompileType::Dynamic(); |
| 877 | 899 |
| 878 case kTypedDataFloat32ArrayCid: | 900 case kTypedDataFloat32ArrayCid: |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 __ sll(index.reg(), index.reg(), 2); | 1009 __ sll(index.reg(), index.reg(), 2); |
| 988 break; | 1010 break; |
| 989 } | 1011 } |
| 990 case 16: { | 1012 case 16: { |
| 991 __ sll(index.reg(), index.reg(), 3); | 1013 __ sll(index.reg(), index.reg(), 3); |
| 992 break; | 1014 break; |
| 993 } | 1015 } |
| 994 default: | 1016 default: |
| 995 UNREACHABLE(); | 1017 UNREACHABLE(); |
| 996 } | 1018 } |
| 997 __ AddImmediate(index.reg(), | 1019 __ addu(index.reg(), array, index.reg()); |
| 1020 element_address = Address(index.reg(), |
| 998 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1021 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 999 element_address = Address(array, index.reg()); | |
| 1000 } | 1022 } |
| 1001 | 1023 |
| 1002 if ((representation() == kUnboxedDouble) || | 1024 if ((representation() == kUnboxedDouble) || |
| 1003 (representation() == kUnboxedMint) || | 1025 (representation() == kUnboxedMint) || |
| 1004 (representation() == kUnboxedFloat32x4)) { | 1026 (representation() == kUnboxedFloat32x4)) { |
| 1005 UNIMPLEMENTED(); | 1027 UNIMPLEMENTED(); |
| 1006 } | 1028 } |
| 1007 | 1029 |
| 1008 Register result = locs()->out().reg(); | 1030 Register result = locs()->out().reg(); |
| 1009 if ((index_scale() == 1) && index.IsRegister()) { | |
| 1010 __ SmiUntag(index.reg()); | |
| 1011 } | |
| 1012 switch (class_id()) { | 1031 switch (class_id()) { |
| 1013 case kTypedDataInt8ArrayCid: | 1032 case kTypedDataInt8ArrayCid: |
| 1014 ASSERT(index_scale() == 1); | 1033 ASSERT(index_scale() == 1); |
| 1015 __ lb(result, element_address); | 1034 __ lb(result, element_address); |
| 1016 __ SmiTag(result); | 1035 __ SmiTag(result); |
| 1017 break; | 1036 break; |
| 1018 case kTypedDataUint8ArrayCid: | 1037 case kTypedDataUint8ArrayCid: |
| 1019 case kTypedDataUint8ClampedArrayCid: | 1038 case kTypedDataUint8ClampedArrayCid: |
| 1020 case kExternalTypedDataUint8ArrayCid: | 1039 case kExternalTypedDataUint8ArrayCid: |
| 1021 case kExternalTypedDataUint8ClampedArrayCid: | 1040 case kExternalTypedDataUint8ClampedArrayCid: |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1054 default: | 1073 default: |
| 1055 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1074 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1056 __ lw(result, element_address); | 1075 __ lw(result, element_address); |
| 1057 break; | 1076 break; |
| 1058 } | 1077 } |
| 1059 } | 1078 } |
| 1060 | 1079 |
| 1061 | 1080 |
| 1062 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1081 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1063 intptr_t idx) const { | 1082 intptr_t idx) const { |
| 1064 UNIMPLEMENTED(); | 1083 // Array can be a Dart object or a pointer to external data. |
| 1065 return kTagged; | 1084 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
| 1085 if (idx == 1) return kTagged; // Index is a smi. |
| 1086 ASSERT(idx == 2); |
| 1087 switch (class_id_) { |
| 1088 case kArrayCid: |
| 1089 case kOneByteStringCid: |
| 1090 case kTypedDataInt8ArrayCid: |
| 1091 case kTypedDataUint8ArrayCid: |
| 1092 case kExternalTypedDataUint8ArrayCid: |
| 1093 case kTypedDataUint8ClampedArrayCid: |
| 1094 case kExternalTypedDataUint8ClampedArrayCid: |
| 1095 case kTypedDataInt16ArrayCid: |
| 1096 case kTypedDataUint16ArrayCid: |
| 1097 return kTagged; |
| 1098 case kTypedDataInt32ArrayCid: |
| 1099 case kTypedDataUint32ArrayCid: |
| 1100 return value()->IsSmiValue() ? kTagged : kUnboxedMint; |
| 1101 case kTypedDataFloat32ArrayCid: |
| 1102 case kTypedDataFloat64ArrayCid: |
| 1103 return kUnboxedDouble; |
| 1104 case kTypedDataFloat32x4ArrayCid: |
| 1105 return kUnboxedFloat32x4; |
| 1106 default: |
| 1107 UNIMPLEMENTED(); |
| 1108 return kTagged; |
| 1109 } |
| 1066 } | 1110 } |
| 1067 | 1111 |
| 1068 | 1112 |
| 1069 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { | 1113 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { |
| 1070 const intptr_t kNumInputs = 3; | 1114 const intptr_t kNumInputs = 3; |
| 1071 const intptr_t kNumTemps = 0; | 1115 const intptr_t kNumTemps = 0; |
| 1072 LocationSummary* locs = | 1116 LocationSummary* locs = |
| 1073 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1117 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1074 locs->set_in(0, Location::RequiresRegister()); | 1118 locs->set_in(0, Location::RequiresRegister()); |
| 1075 // The smi index is either untagged (element size == 1), or it is left smi | 1119 // The smi index is either untagged (element size == 1), or it is left smi |
| 1076 // tagged (for all element sizes > 1). | 1120 // tagged (for all element sizes > 1). |
| 1077 // TODO(regis): Revisit and see if the index can be immediate. | 1121 // TODO(regis): Revisit and see if the index can be immediate. |
| 1078 locs->set_in(1, Location::WritableRegister()); | 1122 locs->set_in(1, Location::WritableRegister()); |
| 1079 switch (class_id()) { | 1123 switch (class_id()) { |
| 1080 case kArrayCid: | 1124 case kArrayCid: |
| 1081 locs->set_in(2, ShouldEmitStoreBarrier() | 1125 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1082 ? Location::WritableRegister() | 1126 ? Location::WritableRegister() |
| 1083 : Location::RegisterOrConstant(value())); | 1127 : Location::RegisterOrConstant(value())); |
| 1084 break; | 1128 break; |
| 1085 case kExternalTypedDataUint8ArrayCid: | 1129 case kExternalTypedDataUint8ArrayCid: |
| 1086 case kExternalTypedDataUint8ClampedArrayCid: | 1130 case kExternalTypedDataUint8ClampedArrayCid: |
| 1087 case kTypedDataInt8ArrayCid: | 1131 case kTypedDataInt8ArrayCid: |
| 1088 case kTypedDataUint8ArrayCid: | 1132 case kTypedDataUint8ArrayCid: |
| 1089 case kTypedDataUint8ClampedArrayCid: | 1133 case kTypedDataUint8ClampedArrayCid: |
| 1090 case kOneByteStringCid: | 1134 case kOneByteStringCid: |
| 1135 locs->set_in(2, Location::RegisterOrSmiConstant(value())); |
| 1136 break; |
| 1091 case kTypedDataInt16ArrayCid: | 1137 case kTypedDataInt16ArrayCid: |
| 1092 case kTypedDataUint16ArrayCid: | 1138 case kTypedDataUint16ArrayCid: |
| 1093 case kTypedDataInt32ArrayCid: | 1139 case kTypedDataInt32ArrayCid: |
| 1094 case kTypedDataUint32ArrayCid: | 1140 case kTypedDataUint32ArrayCid: |
| 1141 locs->set_in(2, Location::WritableRegister()); |
| 1142 break; |
| 1095 case kTypedDataFloat32ArrayCid: | 1143 case kTypedDataFloat32ArrayCid: |
| 1096 case kTypedDataFloat64ArrayCid: | 1144 // TODO(regis): Verify. |
| 1145 // Need temp register for float-to-double conversion. |
| 1146 locs->AddTemp(Location::RequiresFpuRegister()); |
| 1147 // Fall through. |
| 1148 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. |
| 1097 case kTypedDataFloat32x4ArrayCid: | 1149 case kTypedDataFloat32x4ArrayCid: |
| 1098 UNIMPLEMENTED(); | 1150 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1099 break; | 1151 break; |
| 1100 default: | 1152 default: |
| 1101 UNREACHABLE(); | 1153 UNREACHABLE(); |
| 1102 return NULL; | 1154 return NULL; |
| 1103 } | 1155 } |
| 1104 return locs; | 1156 return locs; |
| 1105 } | 1157 } |
| 1106 | 1158 |
| 1107 | 1159 |
| 1108 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1160 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1136 __ sll(index.reg(), index.reg(), 2); | 1188 __ sll(index.reg(), index.reg(), 2); |
| 1137 break; | 1189 break; |
| 1138 } | 1190 } |
| 1139 case 16: { | 1191 case 16: { |
| 1140 __ sll(index.reg(), index.reg(), 3); | 1192 __ sll(index.reg(), index.reg(), 3); |
| 1141 break; | 1193 break; |
| 1142 } | 1194 } |
| 1143 default: | 1195 default: |
| 1144 UNREACHABLE(); | 1196 UNREACHABLE(); |
| 1145 } | 1197 } |
| 1146 __ AddImmediate(index.reg(), | 1198 __ addu(index.reg(), array, index.reg()); |
| 1199 element_address = Address(index.reg(), |
| 1147 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1200 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 1148 __ addu(TMP1, array, index.reg()); | |
| 1149 element_address = Address(TMP1); | |
| 1150 } | 1201 } |
| 1151 | 1202 |
| 1152 switch (class_id()) { | 1203 switch (class_id()) { |
| 1153 case kArrayCid: | 1204 case kArrayCid: |
| 1154 if (ShouldEmitStoreBarrier()) { | 1205 if (ShouldEmitStoreBarrier()) { |
| 1155 Register value = locs()->in(2).reg(); | 1206 Register value = locs()->in(2).reg(); |
| 1156 __ StoreIntoObject(array, element_address, value); | 1207 __ StoreIntoObject(array, element_address, value); |
| 1157 } else if (locs()->in(2).IsConstant()) { | 1208 } else if (locs()->in(2).IsConstant()) { |
| 1158 const Object& constant = locs()->in(2).constant(); | 1209 const Object& constant = locs()->in(2).constant(); |
| 1159 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1210 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 1160 } else { | 1211 } else { |
| 1161 Register value = locs()->in(2).reg(); | 1212 Register value = locs()->in(2).reg(); |
| 1162 __ StoreIntoObjectNoBarrier(array, element_address, value); | 1213 __ StoreIntoObjectNoBarrier(array, element_address, value); |
| 1163 } | 1214 } |
| 1164 break; | 1215 break; |
| 1165 case kTypedDataInt8ArrayCid: | 1216 case kTypedDataInt8ArrayCid: |
| 1166 case kTypedDataUint8ArrayCid: | 1217 case kTypedDataUint8ArrayCid: |
| 1167 case kExternalTypedDataUint8ArrayCid: | 1218 case kExternalTypedDataUint8ArrayCid: |
| 1219 case kOneByteStringCid: { |
| 1220 if (locs()->in(2).IsConstant()) { |
| 1221 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1222 __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value())); |
| 1223 __ sb(TMP, element_address); |
| 1224 } else { |
| 1225 Register value = locs()->in(2).reg(); |
| 1226 __ SmiUntag(value); |
| 1227 __ sb(value, element_address); |
| 1228 } |
| 1229 break; |
| 1230 } |
| 1168 case kTypedDataUint8ClampedArrayCid: | 1231 case kTypedDataUint8ClampedArrayCid: |
| 1169 case kExternalTypedDataUint8ClampedArrayCid: | 1232 case kExternalTypedDataUint8ClampedArrayCid: { |
| 1170 case kOneByteStringCid: | 1233 if (locs()->in(2).IsConstant()) { |
| 1234 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1235 intptr_t value = constant.Value(); |
| 1236 // Clamp to 0x0 or 0xFF respectively. |
| 1237 if (value > 0xFF) { |
| 1238 value = 0xFF; |
| 1239 } else if (value < 0) { |
| 1240 value = 0; |
| 1241 } |
| 1242 __ LoadImmediate(TMP, static_cast<int8_t>(value)); |
| 1243 __ sb(TMP, element_address); |
| 1244 } else { |
| 1245 Register value = locs()->in(2).reg(); |
| 1246 Label store_value, bigger, smaller; |
| 1247 __ SmiUntag(value); |
| 1248 __ BranchUnsignedLess(value, 0xFF + 1, &store_value); |
| 1249 __ LoadImmediate(TMP, 0xFF); |
| 1250 __ slti(CMPRES, value, Immediate(1)); |
| 1251 __ movn(TMP, ZR, CMPRES); |
| 1252 __ mov(value, TMP); |
| 1253 __ Bind(&store_value); |
| 1254 __ sb(value, element_address); |
| 1255 } |
| 1256 break; |
| 1257 } |
| 1171 case kTypedDataInt16ArrayCid: | 1258 case kTypedDataInt16ArrayCid: |
| 1172 case kTypedDataUint16ArrayCid: | 1259 case kTypedDataUint16ArrayCid: { |
| 1260 Register value = locs()->in(2).reg(); |
| 1261 __ SmiUntag(value); |
| 1262 __ sh(value, element_address); |
| 1263 break; |
| 1264 } |
| 1173 case kTypedDataInt32ArrayCid: | 1265 case kTypedDataInt32ArrayCid: |
| 1174 case kTypedDataUint32ArrayCid: | 1266 case kTypedDataUint32ArrayCid: { |
| 1267 if (value()->IsSmiValue()) { |
| 1268 ASSERT(RequiredInputRepresentation(2) == kTagged); |
| 1269 Register value = locs()->in(2).reg(); |
| 1270 __ SmiUntag(value); |
| 1271 __ sw(value, element_address); |
| 1272 } else { |
| 1273 UNIMPLEMENTED(); |
| 1274 } |
| 1275 break; |
| 1276 } |
| 1175 case kTypedDataFloat32ArrayCid: | 1277 case kTypedDataFloat32ArrayCid: |
| 1176 case kTypedDataFloat64ArrayCid: | 1278 case kTypedDataFloat64ArrayCid: |
| 1177 case kTypedDataFloat32x4ArrayCid: | 1279 case kTypedDataFloat32x4ArrayCid: |
| 1178 UNIMPLEMENTED(); | 1280 UNIMPLEMENTED(); |
| 1179 break; | 1281 break; |
| 1180 default: | 1282 default: |
| 1181 UNREACHABLE(); | 1283 UNREACHABLE(); |
| 1182 } | 1284 } |
| 1183 } | 1285 } |
| 1184 | 1286 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1292 | 1394 |
| 1293 if (field_cid != kSmiCid) { | 1395 if (field_cid != kSmiCid) { |
| 1294 __ beq(CMPRES, ZR, fail); | 1396 __ beq(CMPRES, ZR, fail); |
| 1295 __ LoadClassId(value_cid_reg, value_reg); | 1397 __ LoadClassId(value_cid_reg, value_reg); |
| 1296 __ LoadImmediate(TMP1, field_cid); | 1398 __ LoadImmediate(TMP1, field_cid); |
| 1297 __ subu(CMPRES, value_cid_reg, TMP1); | 1399 __ subu(CMPRES, value_cid_reg, TMP1); |
| 1298 } | 1400 } |
| 1299 | 1401 |
| 1300 if (field().is_nullable() && (field_cid != kNullCid)) { | 1402 if (field().is_nullable() && (field_cid != kNullCid)) { |
| 1301 __ beq(CMPRES, ZR, &ok); | 1403 __ beq(CMPRES, ZR, &ok); |
| 1302 __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null())); | 1404 __ subu(CMPRES, value_reg, NULLREG); |
| 1303 __ subu(CMPRES, value_reg, TMP1); | |
| 1304 } | 1405 } |
| 1305 | 1406 |
| 1306 if (ok_is_fall_through) { | 1407 if (ok_is_fall_through) { |
| 1307 __ bne(CMPRES, ZR, fail); | 1408 __ bne(CMPRES, ZR, fail); |
| 1308 } else { | 1409 } else { |
| 1309 __ beq(CMPRES, ZR, &ok); | 1410 __ beq(CMPRES, ZR, &ok); |
| 1310 } | 1411 } |
| 1311 } else { | 1412 } else { |
| 1312 // Both value's and field's class id is known. | 1413 // Both value's and field's class id is known. |
| 1313 if ((value_cid != field_cid) && (value_cid != nullability)) { | 1414 if ((value_cid != field_cid) && (value_cid != nullability)) { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1500 // (or null). | 1601 // (or null). |
| 1501 if (!type_arguments().IsUninstantiatedIdentity() && | 1602 if (!type_arguments().IsUninstantiatedIdentity() && |
| 1502 !type_arguments().CanShareInstantiatorTypeArguments( | 1603 !type_arguments().CanShareInstantiatorTypeArguments( |
| 1503 instantiator_class())) { | 1604 instantiator_class())) { |
| 1504 // If the instantiator is null and if the type argument vector | 1605 // If the instantiator is null and if the type argument vector |
| 1505 // instantiated from null becomes a vector of dynamic, then use null as | 1606 // instantiated from null becomes a vector of dynamic, then use null as |
| 1506 // the type arguments. | 1607 // the type arguments. |
| 1507 Label type_arguments_instantiated; | 1608 Label type_arguments_instantiated; |
| 1508 const intptr_t len = type_arguments().Length(); | 1609 const intptr_t len = type_arguments().Length(); |
| 1509 if (type_arguments().IsRawInstantiatedRaw(len)) { | 1610 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 1510 __ BranchEqual(instantiator_reg, | 1611 __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated); |
| 1511 reinterpret_cast<intptr_t>(Object::null()), | |
| 1512 &type_arguments_instantiated); | |
| 1513 } | 1612 } |
| 1514 // Instantiate non-null type arguments. | 1613 // Instantiate non-null type arguments. |
| 1515 // A runtime call to instantiate the type arguments is required. | 1614 // A runtime call to instantiate the type arguments is required. |
| 1516 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1615 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 1517 __ LoadObject(TMP1, Object::ZoneHandle()); | 1616 __ LoadObject(TMP1, Object::ZoneHandle()); |
| 1518 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Make room for the result. | 1617 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Make room for the result. |
| 1519 __ LoadObject(TMP1, type_arguments()); | 1618 __ LoadObject(TMP1, type_arguments()); |
| 1520 __ sw(TMP1, Address(SP, 1 * kWordSize)); | 1619 __ sw(TMP1, Address(SP, 1 * kWordSize)); |
| 1521 // Push instantiator type arguments. | 1620 // Push instantiator type arguments. |
| 1522 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); | 1621 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1557 // instantiator_reg is the instantiator type argument vector, i.e. an | 1656 // instantiator_reg is the instantiator type argument vector, i.e. an |
| 1558 // AbstractTypeArguments object (or null). | 1657 // AbstractTypeArguments object (or null). |
| 1559 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 1658 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 1560 !type_arguments().CanShareInstantiatorTypeArguments( | 1659 !type_arguments().CanShareInstantiatorTypeArguments( |
| 1561 instantiator_class())); | 1660 instantiator_class())); |
| 1562 // If the instantiator is null and if the type argument vector | 1661 // If the instantiator is null and if the type argument vector |
| 1563 // instantiated from null becomes a vector of dynamic, then use null as | 1662 // instantiated from null becomes a vector of dynamic, then use null as |
| 1564 // the type arguments. | 1663 // the type arguments. |
| 1565 Label type_arguments_instantiated; | 1664 Label type_arguments_instantiated; |
| 1566 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); | 1665 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); |
| 1567 __ BranchEqual(instantiator_reg, | 1666 __ beq(instantiator_reg, NULLREG, &type_arguments_instantiated); |
| 1568 reinterpret_cast<intptr_t>(Object::null()), | |
| 1569 &type_arguments_instantiated); | |
| 1570 // Instantiate non-null type arguments. | 1667 // Instantiate non-null type arguments. |
| 1571 // In the non-factory case, we rely on the allocation stub to | 1668 // In the non-factory case, we rely on the allocation stub to |
| 1572 // instantiate the type arguments. | 1669 // instantiate the type arguments. |
| 1573 __ LoadObject(result_reg, type_arguments()); | 1670 __ LoadObject(result_reg, type_arguments()); |
| 1574 // result_reg: uninstantiated type arguments. | 1671 // result_reg: uninstantiated type arguments. |
| 1575 __ Bind(&type_arguments_instantiated); | 1672 __ Bind(&type_arguments_instantiated); |
| 1576 | 1673 |
| 1577 // result_reg: uninstantiated or instantiated type arguments. | 1674 // result_reg: uninstantiated or instantiated type arguments. |
| 1578 } | 1675 } |
| 1579 | 1676 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1599 // (or null). | 1696 // (or null). |
| 1600 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 1697 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 1601 !type_arguments().CanShareInstantiatorTypeArguments( | 1698 !type_arguments().CanShareInstantiatorTypeArguments( |
| 1602 instantiator_class())); | 1699 instantiator_class())); |
| 1603 | 1700 |
| 1604 // If the instantiator is null and if the type argument vector | 1701 // If the instantiator is null and if the type argument vector |
| 1605 // instantiated from null becomes a vector of dynamic, then use null as | 1702 // instantiated from null becomes a vector of dynamic, then use null as |
| 1606 // the type arguments and do not pass the instantiator. | 1703 // the type arguments and do not pass the instantiator. |
| 1607 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); | 1704 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); |
| 1608 Label instantiator_not_null; | 1705 Label instantiator_not_null; |
| 1609 __ BranchNotEqual(instantiator_reg, | 1706 __ bne(instantiator_reg, NULLREG, &instantiator_not_null); |
| 1610 reinterpret_cast<intptr_t>(Object::null()), &instantiator_not_null); | |
| 1611 // Null was used in VisitExtractConstructorTypeArguments as the | 1707 // Null was used in VisitExtractConstructorTypeArguments as the |
| 1612 // instantiated type arguments, no proper instantiator needed. | 1708 // instantiated type arguments, no proper instantiator needed. |
| 1613 __ LoadImmediate(instantiator_reg, | 1709 __ LoadImmediate(instantiator_reg, |
| 1614 Smi::RawValue(StubCode::kNoInstantiator)); | 1710 Smi::RawValue(StubCode::kNoInstantiator)); |
| 1615 __ Bind(&instantiator_not_null); | 1711 __ Bind(&instantiator_not_null); |
| 1616 // instantiator_reg: instantiator or kNoInstantiator. | 1712 // instantiator_reg: instantiator or kNoInstantiator. |
| 1617 } | 1713 } |
| 1618 | 1714 |
| 1619 | 1715 |
| 1620 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { | 1716 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1674 | 1770 |
| 1675 ASSERT(!exception_var().is_captured()); | 1771 ASSERT(!exception_var().is_captured()); |
| 1676 ASSERT(!stacktrace_var().is_captured()); | 1772 ASSERT(!stacktrace_var().is_captured()); |
| 1677 | 1773 |
| 1678 __ sw(kExceptionObjectReg, | 1774 __ sw(kExceptionObjectReg, |
| 1679 Address(FP, exception_var().index() * kWordSize)); | 1775 Address(FP, exception_var().index() * kWordSize)); |
| 1680 __ sw(kStackTraceObjectReg, | 1776 __ sw(kStackTraceObjectReg, |
| 1681 Address(FP, stacktrace_var().index() * kWordSize)); | 1777 Address(FP, stacktrace_var().index() * kWordSize)); |
| 1682 | 1778 |
| 1683 Label next; | 1779 Label next; |
| 1684 __ mov(T0, RA); // Save return adress. | 1780 __ mov(TMP, RA); // Save return adress. |
| 1685 // Restore the pool pointer. | 1781 // Restore the pool pointer. |
| 1686 __ bal(&next); // Branch and link to next instruction to get PC in RA. | 1782 __ bal(&next); // Branch and link to next instruction to get PC in RA. |
| 1687 __ delay_slot()->mov(T1, RA); // Save PC of the following mov. | 1783 __ delay_slot()->mov(CMPRES, RA); // Save PC of the following mov. |
| 1688 | 1784 |
| 1689 // Calculate offset of pool pointer from the PC. | 1785 // Calculate offset of pool pointer from the PC. |
| 1690 const intptr_t object_pool_pc_dist = | 1786 const intptr_t object_pool_pc_dist = |
| 1691 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 1787 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 1692 compiler->assembler()->CodeSize(); | 1788 compiler->assembler()->CodeSize(); |
| 1693 | 1789 |
| 1694 __ Bind(&next); | 1790 __ Bind(&next); |
| 1695 __ mov(RA, T0); // Restore return address. | 1791 __ mov(RA, TMP); // Restore return address. |
| 1696 __ lw(PP, Address(T1, -object_pool_pc_dist)); | 1792 __ lw(PP, Address(CMPRES, -object_pool_pc_dist)); |
| 1697 } | 1793 } |
| 1698 | 1794 |
| 1699 | 1795 |
| 1700 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const { | 1796 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const { |
| 1701 const intptr_t kNumInputs = 0; | 1797 const intptr_t kNumInputs = 0; |
| 1702 const intptr_t kNumTemps = 0; | 1798 const intptr_t kNumTemps = 0; |
| 1703 LocationSummary* summary = | 1799 LocationSummary* summary = |
| 1704 new LocationSummary(kNumInputs, | 1800 new LocationSummary(kNumInputs, |
| 1705 kNumTemps, | 1801 kNumTemps, |
| 1706 LocationSummary::kCallOnSlowPath); | 1802 LocationSummary::kCallOnSlowPath); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1749 __ Bind(slow_path->exit_label()); | 1845 __ Bind(slow_path->exit_label()); |
| 1750 } | 1846 } |
| 1751 | 1847 |
| 1752 | 1848 |
| 1753 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { | 1849 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { |
| 1754 const intptr_t kNumInputs = 2; | 1850 const intptr_t kNumInputs = 2; |
| 1755 if (op_kind() == Token::kTRUNCDIV) { | 1851 if (op_kind() == Token::kTRUNCDIV) { |
| 1756 UNIMPLEMENTED(); | 1852 UNIMPLEMENTED(); |
| 1757 return NULL; | 1853 return NULL; |
| 1758 } else { | 1854 } else { |
| 1759 const intptr_t kNumTemps = 0; | 1855 const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0; |
| 1760 LocationSummary* summary = | 1856 LocationSummary* summary = |
| 1761 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1857 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1762 summary->set_in(0, Location::RequiresRegister()); | 1858 summary->set_in(0, Location::RequiresRegister()); |
| 1763 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 1859 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 1764 if (op_kind() == Token::kADD) { | 1860 if (op_kind() == Token::kADD) { |
| 1765 // Need an extra temp for the overflow detection code. | 1861 // Need an extra temp for the overflow detection code. |
| 1766 summary->set_temp(0, Location::RequiresRegister()); | 1862 summary->set_temp(0, Location::RequiresRegister()); |
| 1767 } | 1863 } |
| 1768 // We make use of 3-operand instructions by not requiring result register | 1864 // We make use of 3-operand instructions by not requiring result register |
| 1769 // to be identical to first input register as on Intel. | 1865 // to be identical to first input register as on Intel. |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2401 summary->AddTemp(Location::RequiresRegister()); | 2497 summary->AddTemp(Location::RequiresRegister()); |
| 2402 } | 2498 } |
| 2403 return summary; | 2499 return summary; |
| 2404 } | 2500 } |
| 2405 | 2501 |
| 2406 | 2502 |
| 2407 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2503 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2408 if (null_check()) { | 2504 if (null_check()) { |
| 2409 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2505 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2410 kDeoptCheckClass); | 2506 kDeoptCheckClass); |
| 2411 __ BranchEqual(locs()->in(0).reg(), | 2507 __ beq(locs()->in(0).reg(), NULLREG, deopt); |
| 2412 reinterpret_cast<intptr_t>(Object::null()), deopt); | |
| 2413 return; | 2508 return; |
| 2414 } | 2509 } |
| 2415 | 2510 |
| 2416 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 2511 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| 2417 (unary_checks().NumberOfChecks() > 1)); | 2512 (unary_checks().NumberOfChecks() > 1)); |
| 2418 Register value = locs()->in(0).reg(); | 2513 Register value = locs()->in(0).reg(); |
| 2419 Register temp = locs()->temp(0).reg(); | 2514 Register temp = locs()->temp(0).reg(); |
| 2420 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2515 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2421 kDeoptCheckClass); | 2516 kDeoptCheckClass); |
| 2422 Label is_ok; | 2517 Label is_ok; |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2655 } | 2750 } |
| 2656 | 2751 |
| 2657 | 2752 |
| 2658 // The comparison result is in CMPRES. | 2753 // The comparison result is in CMPRES. |
| 2659 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, | 2754 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 2660 Condition true_condition) { | 2755 Condition true_condition) { |
| 2661 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); | 2756 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); |
| 2662 if (compiler->CanFallThroughTo(false_successor())) { | 2757 if (compiler->CanFallThroughTo(false_successor())) { |
| 2663 // If the next block is the false successor we will fall through to it. | 2758 // If the next block is the false successor we will fall through to it. |
| 2664 Label* label = compiler->GetJumpLabel(true_successor()); | 2759 Label* label = compiler->GetJumpLabel(true_successor()); |
| 2665 switch (true_condition) { | 2760 EmitBranchAfterCompare(compiler, true_condition, label); |
| 2666 case EQ: __ beq(CMPRES, ZR, label); break; | |
| 2667 case NE: __ bne(CMPRES, ZR, label); break; | |
| 2668 case GT: __ bgtz(CMPRES, label); break; | |
| 2669 case GE: __ bgez(CMPRES, label); break; | |
| 2670 case LT: __ bltz(CMPRES, label); break; | |
| 2671 case LE: __ blez(CMPRES, label); break; | |
| 2672 default: | |
| 2673 UNREACHABLE(); | |
| 2674 break; | |
| 2675 } | |
| 2676 } else { | 2761 } else { |
| 2677 // If the next block is the true successor we negate comparison and fall | 2762 // If the next block is the true successor we negate comparison and fall |
| 2678 // through to it. | 2763 // through to it. |
| 2679 Condition false_condition = NegateCondition(true_condition); | 2764 Condition false_condition = NegateCondition(true_condition); |
| 2680 Label* label = compiler->GetJumpLabel(false_successor()); | 2765 Label* label = compiler->GetJumpLabel(false_successor()); |
| 2681 switch (false_condition) { | 2766 EmitBranchAfterCompare(compiler, false_condition, label); |
| 2682 case EQ: __ beq(CMPRES, ZR, label); break; | |
| 2683 case NE: __ bne(CMPRES, ZR, label); break; | |
| 2684 case GT: __ bgtz(CMPRES, label); break; | |
| 2685 case GE: __ bgez(CMPRES, label); break; | |
| 2686 case LT: __ bltz(CMPRES, label); break; | |
| 2687 case LE: __ blez(CMPRES, label); break; | |
| 2688 default: | |
| 2689 UNREACHABLE(); | |
| 2690 break; | |
| 2691 } | |
| 2692 // Fall through or jump to the true successor. | 2767 // Fall through or jump to the true successor. |
| 2693 if (!compiler->CanFallThroughTo(true_successor())) { | 2768 if (!compiler->CanFallThroughTo(true_successor())) { |
| 2694 __ b(compiler->GetJumpLabel(true_successor())); | 2769 __ b(compiler->GetJumpLabel(true_successor())); |
| 2695 } | 2770 } |
| 2696 } | 2771 } |
| 2697 } | 2772 } |
| 2698 | 2773 |
| 2699 | 2774 |
| 2700 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { | 2775 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 2701 return LocationSummary::Make(0, | 2776 return LocationSummary::Make(0, |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2851 locs->set_in(1, Location::RequiresRegister()); | 2926 locs->set_in(1, Location::RequiresRegister()); |
| 2852 return locs; | 2927 return locs; |
| 2853 } | 2928 } |
| 2854 | 2929 |
| 2855 | 2930 |
| 2856 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2931 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2857 Register value_reg = locs()->in(0).reg(); | 2932 Register value_reg = locs()->in(0).reg(); |
| 2858 Register dest_reg = locs()->in(1).reg(); | 2933 Register dest_reg = locs()->in(1).reg(); |
| 2859 | 2934 |
| 2860 if (value()->NeedsStoreBuffer()) { | 2935 if (value()->NeedsStoreBuffer()) { |
| 2861 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), | 2936 __ StoreIntoObject(dest_reg, |
| 2862 value_reg); | 2937 FieldAddress(dest_reg, offset_in_bytes()), value_reg); |
| 2863 } else { | 2938 } else { |
| 2864 __ StoreIntoObjectNoBarrier( | 2939 __ StoreIntoObjectNoBarrier(dest_reg, |
| 2865 dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg); | 2940 FieldAddress(dest_reg, offset_in_bytes()), value_reg); |
| 2866 } | 2941 } |
| 2867 } | 2942 } |
| 2868 | 2943 |
| 2869 | 2944 |
| 2870 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { | 2945 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { |
| 2871 return MakeCallSummary(); | 2946 return MakeCallSummary(); |
| 2872 } | 2947 } |
| 2873 | 2948 |
| 2874 | 2949 |
| 2875 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2950 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2899 compiler->GenerateCall(token_pos(), | 2974 compiler->GenerateCall(token_pos(), |
| 2900 &label, | 2975 &label, |
| 2901 PcDescriptors::kOther, | 2976 PcDescriptors::kOther, |
| 2902 locs()); | 2977 locs()); |
| 2903 __ Drop(2); // Discard type arguments and receiver. | 2978 __ Drop(2); // Discard type arguments and receiver. |
| 2904 } | 2979 } |
| 2905 | 2980 |
| 2906 } // namespace dart | 2981 } // namespace dart |
| 2907 | 2982 |
| 2908 #endif // defined TARGET_ARCH_MIPS | 2983 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |