| 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/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 void Intrinsifier::GrowableArraySetData(Assembler* assembler) { | 207 void Intrinsifier::GrowableArraySetData(Assembler* assembler) { |
| 208 if (FLAG_enable_type_checks) { | 208 if (FLAG_enable_type_checks) { |
| 209 return; | 209 return; |
| 210 } | 210 } |
| 211 Label fall_through; | 211 Label fall_through; |
| 212 __ lw(T1, Address(SP, 0 * kWordSize)); // Data. | 212 __ lw(T1, Address(SP, 0 * kWordSize)); // Data. |
| 213 // Check that data is an ObjectArray. | 213 // Check that data is an ObjectArray. |
| 214 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 214 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); |
| 215 __ beq(CMPRES1, ZR, &fall_through); // Data is Smi. | 215 __ beq(CMPRES1, ZR, &fall_through); // Data is Smi. |
| 216 __ LoadClassId(CMPRES1, T1); | 216 __ LoadClassId(CMPRES1, T1); |
| 217 __ BranchNotEqual(CMPRES1, kArrayCid, &fall_through); | 217 __ BranchNotEqual(CMPRES1, Immediate(kArrayCid), &fall_through); |
| 218 __ lw(T0, Address(SP, 1 * kWordSize)); // Growable array. | 218 __ lw(T0, Address(SP, 1 * kWordSize)); // Growable array. |
| 219 __ StoreIntoObject(T0, | 219 __ StoreIntoObject(T0, |
| 220 FieldAddress(T0, GrowableObjectArray::data_offset()), | 220 FieldAddress(T0, GrowableObjectArray::data_offset()), |
| 221 T1); | 221 T1); |
| 222 __ Ret(); | 222 __ Ret(); |
| 223 __ Bind(&fall_through); | 223 __ Bind(&fall_through); |
| 224 } | 224 } |
| 225 | 225 |
| 226 | 226 |
| 227 // Add an element to growable array if it doesn't need to grow, otherwise | 227 // Add an element to growable array if it doesn't need to grow, otherwise |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 | 259 |
| 260 | 260 |
| 261 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \ | 261 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \ |
| 262 Label fall_through; \ | 262 Label fall_through; \ |
| 263 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \ | 263 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \ |
| 264 __ lw(T2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \ | 264 __ lw(T2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \ |
| 265 /* Check that length is a positive Smi. */ \ | 265 /* Check that length is a positive Smi. */ \ |
| 266 /* T2: requested array length argument. */ \ | 266 /* T2: requested array length argument. */ \ |
| 267 __ andi(CMPRES1, T2, Immediate(kSmiTagMask)); \ | 267 __ andi(CMPRES1, T2, Immediate(kSmiTagMask)); \ |
| 268 __ bne(CMPRES1, ZR, &fall_through); \ | 268 __ bne(CMPRES1, ZR, &fall_through); \ |
| 269 __ BranchSignedLess(T2, 0, &fall_through); \ | 269 __ BranchSignedLess(T2, Immediate(0), &fall_through); \ |
| 270 __ SmiUntag(T2); \ | 270 __ SmiUntag(T2); \ |
| 271 /* Check for maximum allowed length. */ \ | 271 /* Check for maximum allowed length. */ \ |
| 272 /* T2: untagged array length. */ \ | 272 /* T2: untagged array length. */ \ |
| 273 __ BranchSignedGreater(T2, max_len, &fall_through); \ | 273 __ BranchSignedGreater(T2, Immediate(max_len), &fall_through); \ |
| 274 __ sll(T2, T2, scale_shift); \ | 274 __ sll(T2, T2, scale_shift); \ |
| 275 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ | 275 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ |
| 276 __ AddImmediate(T2, fixed_size); \ | 276 __ AddImmediate(T2, fixed_size); \ |
| 277 __ LoadImmediate(TMP, -kObjectAlignment); \ | 277 __ LoadImmediate(TMP, -kObjectAlignment); \ |
| 278 __ and_(T2, T2, TMP); \ | 278 __ and_(T2, T2, TMP); \ |
| 279 Heap* heap = Isolate::Current()->heap(); \ | 279 Heap* heap = Isolate::Current()->heap(); \ |
| 280 Heap::Space space = heap->SpaceForAllocation(cid); \ | 280 Heap::Space space = heap->SpaceForAllocation(cid); \ |
| 281 __ LoadImmediate(V0, heap->TopAddress(space)); \ | 281 __ LoadImmediate(V0, heap->TopAddress(space)); \ |
| 282 __ lw(V0, Address(V0, 0)); \ | 282 __ lw(V0, Address(V0, 0)); \ |
| 283 \ | 283 \ |
| (...skipping 14 matching lines...) Expand all Loading... |
| 298 __ LoadImmediate(T3, heap->TopAddress(space)); \ | 298 __ LoadImmediate(T3, heap->TopAddress(space)); \ |
| 299 __ sw(T1, Address(T3, 0)); \ | 299 __ sw(T1, Address(T3, 0)); \ |
| 300 __ AddImmediate(V0, kHeapObjectTag); \ | 300 __ AddImmediate(V0, kHeapObjectTag); \ |
| 301 __ UpdateAllocationStatsWithSize(cid, T2, T4, space); \ | 301 __ UpdateAllocationStatsWithSize(cid, T2, T4, space); \ |
| 302 /* Initialize the tags. */ \ | 302 /* Initialize the tags. */ \ |
| 303 /* V0: new object start as a tagged pointer. */ \ | 303 /* V0: new object start as a tagged pointer. */ \ |
| 304 /* T1: new object end address. */ \ | 304 /* T1: new object end address. */ \ |
| 305 /* T2: allocation size. */ \ | 305 /* T2: allocation size. */ \ |
| 306 { \ | 306 { \ |
| 307 Label size_tag_overflow, done; \ | 307 Label size_tag_overflow, done; \ |
| 308 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, \ | 308 __ BranchUnsignedGreater(T2, Immediate(RawObject::SizeTag::kMaxSizeTag), \ |
| 309 &size_tag_overflow); \ | 309 &size_tag_overflow); \ |
| 310 __ b(&done); \ | 310 __ b(&done); \ |
| 311 __ delay_slot()->sll(T2, T2, \ | 311 __ delay_slot()->sll(T2, T2, \ |
| 312 RawObject::kSizeTagPos - kObjectAlignmentLog2); \ | 312 RawObject::kSizeTagPos - kObjectAlignmentLog2); \ |
| 313 \ | 313 \ |
| 314 __ Bind(&size_tag_overflow); \ | 314 __ Bind(&size_tag_overflow); \ |
| 315 __ mov(T2, ZR); \ | 315 __ mov(T2, ZR); \ |
| 316 __ Bind(&done); \ | 316 __ Bind(&done); \ |
| 317 \ | 317 \ |
| 318 /* Get the class index and insert it into the tags. */ \ | 318 /* Get the class index and insert it into the tags. */ \ |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 | 533 |
| 534 TestBothArgumentsSmis(assembler, &fall_through); | 534 TestBothArgumentsSmis(assembler, &fall_through); |
| 535 __ beq(T0, ZR, &fall_through); // If b is 0, fall through. | 535 __ beq(T0, ZR, &fall_through); // If b is 0, fall through. |
| 536 | 536 |
| 537 __ SmiUntag(T0); | 537 __ SmiUntag(T0); |
| 538 __ SmiUntag(T1); | 538 __ SmiUntag(T1); |
| 539 __ div(T1, T0); // LO <- T1 / T0 | 539 __ div(T1, T0); // LO <- T1 / T0 |
| 540 __ mflo(V0); // V0 <- LO | 540 __ mflo(V0); // V0 <- LO |
| 541 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we | 541 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we |
| 542 // cannot tag the result. | 542 // cannot tag the result. |
| 543 __ BranchEqual(V0, 0x40000000, &fall_through); | 543 __ BranchEqual(V0, Immediate(0x40000000), &fall_through); |
| 544 __ Ret(); | 544 __ Ret(); |
| 545 __ delay_slot()->SmiTag(V0); | 545 __ delay_slot()->SmiTag(V0); |
| 546 __ Bind(&fall_through); | 546 __ Bind(&fall_through); |
| 547 } | 547 } |
| 548 | 548 |
| 549 | 549 |
| 550 void Intrinsifier::Integer_negate(Assembler* assembler) { | 550 void Intrinsifier::Integer_negate(Assembler* assembler) { |
| 551 Label fall_through; | 551 Label fall_through; |
| 552 | 552 |
| 553 __ lw(T0, Address(SP, + 0 * kWordSize)); // Grabs first argument. | 553 __ lw(T0, Address(SP, + 0 * kWordSize)); // Grabs first argument. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 Integer_bitXorFromInteger(assembler); | 604 Integer_bitXorFromInteger(assembler); |
| 605 } | 605 } |
| 606 | 606 |
| 607 | 607 |
| 608 void Intrinsifier::Integer_shl(Assembler* assembler) { | 608 void Intrinsifier::Integer_shl(Assembler* assembler) { |
| 609 ASSERT(kSmiTagShift == 1); | 609 ASSERT(kSmiTagShift == 1); |
| 610 ASSERT(kSmiTag == 0); | 610 ASSERT(kSmiTag == 0); |
| 611 Label fall_through, overflow; | 611 Label fall_through, overflow; |
| 612 | 612 |
| 613 TestBothArgumentsSmis(assembler, &fall_through); | 613 TestBothArgumentsSmis(assembler, &fall_through); |
| 614 __ BranchUnsignedGreater(T0, Smi::RawValue(Smi::kBits), &fall_through); | 614 __ BranchUnsignedGreater( |
| 615 T0, Immediate(Smi::RawValue(Smi::kBits)), &fall_through); |
| 615 __ SmiUntag(T0); | 616 __ SmiUntag(T0); |
| 616 | 617 |
| 617 // Check for overflow by shifting left and shifting back arithmetically. | 618 // Check for overflow by shifting left and shifting back arithmetically. |
| 618 // If the result is different from the original, there was overflow. | 619 // If the result is different from the original, there was overflow. |
| 619 __ sllv(TMP, T1, T0); | 620 __ sllv(TMP, T1, T0); |
| 620 __ srav(CMPRES1, TMP, T0); | 621 __ srav(CMPRES1, TMP, T0); |
| 621 __ bne(CMPRES1, T1, &overflow); | 622 __ bne(CMPRES1, T1, &overflow); |
| 622 | 623 |
| 623 // No overflow, result in V0. | 624 // No overflow, result in V0. |
| 624 __ Ret(); | 625 __ Ret(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 __ bne(CMPRES1, ZR, ¬_smi); | 666 __ bne(CMPRES1, ZR, ¬_smi); |
| 666 __ SmiUntag(reg); | 667 __ SmiUntag(reg); |
| 667 | 668 |
| 668 // Sign extend to 64 bit | 669 // Sign extend to 64 bit |
| 669 __ mov(res_lo, reg); | 670 __ mov(res_lo, reg); |
| 670 __ b(&done); | 671 __ b(&done); |
| 671 __ delay_slot()->sra(res_hi, reg, 31); | 672 __ delay_slot()->sra(res_hi, reg, 31); |
| 672 | 673 |
| 673 __ Bind(¬_smi); | 674 __ Bind(¬_smi); |
| 674 __ LoadClassId(CMPRES1, reg); | 675 __ LoadClassId(CMPRES1, reg); |
| 675 __ BranchNotEqual(CMPRES1, kMintCid, not_smi_or_mint); | 676 __ BranchNotEqual(CMPRES1, Immediate(kMintCid), not_smi_or_mint); |
| 676 | 677 |
| 677 // Mint. | 678 // Mint. |
| 678 __ lw(res_lo, FieldAddress(reg, Mint::value_offset())); | 679 __ lw(res_lo, FieldAddress(reg, Mint::value_offset())); |
| 679 __ lw(res_hi, FieldAddress(reg, Mint::value_offset() + kWordSize)); | 680 __ lw(res_hi, FieldAddress(reg, Mint::value_offset() + kWordSize)); |
| 680 __ Bind(&done); | 681 __ Bind(&done); |
| 681 return; | 682 return; |
| 682 } | 683 } |
| 683 | 684 |
| 684 | 685 |
| 685 static void CompareIntegers(Assembler* assembler, Condition true_condition) { | 686 static void CompareIntegers(Assembler* assembler, Condition true_condition) { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 __ Bind(&check_for_mint); | 806 __ Bind(&check_for_mint); |
| 806 | 807 |
| 807 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 808 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); |
| 808 __ bne(CMPRES1, ZR, &receiver_not_smi); // Check receiver. | 809 __ bne(CMPRES1, ZR, &receiver_not_smi); // Check receiver. |
| 809 | 810 |
| 810 // Left (receiver) is Smi, return false if right is not Double. | 811 // Left (receiver) is Smi, return false if right is not Double. |
| 811 // Note that an instance of Mint or Bigint never contains a value that can be | 812 // Note that an instance of Mint or Bigint never contains a value that can be |
| 812 // represented by Smi. | 813 // represented by Smi. |
| 813 | 814 |
| 814 __ LoadClassId(CMPRES1, T0); | 815 __ LoadClassId(CMPRES1, T0); |
| 815 __ BranchEqual(CMPRES1, kDoubleCid, &fall_through); | 816 __ BranchEqual(CMPRES1, Immediate(kDoubleCid), &fall_through); |
| 816 __ LoadObject(V0, Bool::False()); // Smi == Mint -> false. | 817 __ LoadObject(V0, Bool::False()); // Smi == Mint -> false. |
| 817 __ Ret(); | 818 __ Ret(); |
| 818 | 819 |
| 819 __ Bind(&receiver_not_smi); | 820 __ Bind(&receiver_not_smi); |
| 820 // T1:: receiver. | 821 // T1:: receiver. |
| 821 | 822 |
| 822 __ LoadClassId(CMPRES1, T1); | 823 __ LoadClassId(CMPRES1, T1); |
| 823 __ BranchNotEqual(CMPRES1, kMintCid, &fall_through); | 824 __ BranchNotEqual(CMPRES1, Immediate(kMintCid), &fall_through); |
| 824 // Receiver is Mint, return false if right is Smi. | 825 // Receiver is Mint, return false if right is Smi. |
| 825 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 826 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); |
| 826 __ bne(CMPRES1, ZR, &fall_through); | 827 __ bne(CMPRES1, ZR, &fall_through); |
| 827 __ LoadObject(V0, Bool::False()); | 828 __ LoadObject(V0, Bool::False()); |
| 828 __ Ret(); | 829 __ Ret(); |
| 829 // TODO(srdjan): Implement Mint == Mint comparison. | 830 // TODO(srdjan): Implement Mint == Mint comparison. |
| 830 | 831 |
| 831 __ Bind(&fall_through); | 832 __ Bind(&fall_through); |
| 832 } | 833 } |
| 833 | 834 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 // Check if the last argument is a double, jump to label 'is_smi' if smi | 909 // Check if the last argument is a double, jump to label 'is_smi' if smi |
| 909 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 910 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
| 910 // Returns the last argument in T0. | 911 // Returns the last argument in T0. |
| 911 static void TestLastArgumentIsDouble(Assembler* assembler, | 912 static void TestLastArgumentIsDouble(Assembler* assembler, |
| 912 Label* is_smi, | 913 Label* is_smi, |
| 913 Label* not_double_smi) { | 914 Label* not_double_smi) { |
| 914 __ lw(T0, Address(SP, 0 * kWordSize)); | 915 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 915 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 916 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); |
| 916 __ beq(CMPRES1, ZR, is_smi); | 917 __ beq(CMPRES1, ZR, is_smi); |
| 917 __ LoadClassId(CMPRES1, T0); | 918 __ LoadClassId(CMPRES1, T0); |
| 918 __ BranchNotEqual(CMPRES1, kDoubleCid, not_double_smi); | 919 __ BranchNotEqual(CMPRES1, Immediate(kDoubleCid), not_double_smi); |
| 919 // Fall through with Double in T0. | 920 // Fall through with Double in T0. |
| 920 } | 921 } |
| 921 | 922 |
| 922 | 923 |
| 923 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown | 924 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown |
| 924 // type. Return true or false object in the register V0. Any NaN argument | 925 // type. Return true or false object in the register V0. Any NaN argument |
| 925 // returns false. Any non-double arg1 causes control flow to fall through to the | 926 // returns false. Any non-double arg1 causes control flow to fall through to the |
| 926 // slow case (compiled method body). | 927 // slow case (compiled method body). |
| 927 static void CompareDoubles(Assembler* assembler, Condition true_condition) { | 928 static void CompareDoubles(Assembler* assembler, Condition true_condition) { |
| 928 Label is_smi, double_op, no_NaN, fall_through; | 929 Label is_smi, double_op, no_NaN, fall_through; |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1267 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. | 1268 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. |
| 1268 __ lw(T0, Address(SP, 1 * kWordSize)); // String. | 1269 __ lw(T0, Address(SP, 1 * kWordSize)); // String. |
| 1269 | 1270 |
| 1270 // Checks. | 1271 // Checks. |
| 1271 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 1272 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); |
| 1272 __ bne(T1, ZR, &fall_through); // Index is not a Smi. | 1273 __ bne(T1, ZR, &fall_through); // Index is not a Smi. |
| 1273 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. | 1274 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. |
| 1274 // Runtime throws exception. | 1275 // Runtime throws exception. |
| 1275 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); | 1276 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); |
| 1276 __ LoadClassId(CMPRES1, T0); // Class ID check. | 1277 __ LoadClassId(CMPRES1, T0); // Class ID check. |
| 1277 __ BranchNotEqual(CMPRES1, kOneByteStringCid, &try_two_byte_string); | 1278 __ BranchNotEqual( |
| 1279 CMPRES1, Immediate(kOneByteStringCid), &try_two_byte_string); |
| 1278 | 1280 |
| 1279 // Grab byte and return. | 1281 // Grab byte and return. |
| 1280 __ SmiUntag(T1); | 1282 __ SmiUntag(T1); |
| 1281 __ addu(T2, T0, T1); | 1283 __ addu(T2, T0, T1); |
| 1282 __ lbu(V0, FieldAddress(T2, OneByteString::data_offset())); | 1284 __ lbu(V0, FieldAddress(T2, OneByteString::data_offset())); |
| 1283 __ Ret(); | 1285 __ Ret(); |
| 1284 __ delay_slot()->SmiTag(V0); | 1286 __ delay_slot()->SmiTag(V0); |
| 1285 | 1287 |
| 1286 __ Bind(&try_two_byte_string); | 1288 __ Bind(&try_two_byte_string); |
| 1287 __ BranchNotEqual(CMPRES1, kTwoByteStringCid, &fall_through); | 1289 __ BranchNotEqual(CMPRES1, Immediate(kTwoByteStringCid), &fall_through); |
| 1288 ASSERT(kSmiTagShift == 1); | 1290 ASSERT(kSmiTagShift == 1); |
| 1289 __ addu(T2, T0, T1); | 1291 __ addu(T2, T0, T1); |
| 1290 __ lhu(V0, FieldAddress(T2, TwoByteString::data_offset())); | 1292 __ lhu(V0, FieldAddress(T2, TwoByteString::data_offset())); |
| 1291 __ Ret(); | 1293 __ Ret(); |
| 1292 __ delay_slot()->SmiTag(V0); | 1294 __ delay_slot()->SmiTag(V0); |
| 1293 | 1295 |
| 1294 __ Bind(&fall_through); | 1296 __ Bind(&fall_through); |
| 1295 } | 1297 } |
| 1296 | 1298 |
| 1297 | 1299 |
| 1298 void Intrinsifier::StringBaseCharAt(Assembler* assembler) { | 1300 void Intrinsifier::StringBaseCharAt(Assembler* assembler) { |
| 1299 Label fall_through, try_two_byte_string; | 1301 Label fall_through, try_two_byte_string; |
| 1300 | 1302 |
| 1301 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. | 1303 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. |
| 1302 __ lw(T0, Address(SP, 1 * kWordSize)); // String. | 1304 __ lw(T0, Address(SP, 1 * kWordSize)); // String. |
| 1303 | 1305 |
| 1304 // Checks. | 1306 // Checks. |
| 1305 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 1307 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); |
| 1306 __ bne(T1, ZR, &fall_through); // Index is not a Smi. | 1308 __ bne(T1, ZR, &fall_through); // Index is not a Smi. |
| 1307 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. | 1309 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. |
| 1308 // Runtime throws exception. | 1310 // Runtime throws exception. |
| 1309 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); | 1311 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); |
| 1310 __ LoadClassId(CMPRES1, T0); // Class ID check. | 1312 __ LoadClassId(CMPRES1, T0); // Class ID check. |
| 1311 __ BranchNotEqual(CMPRES1, kOneByteStringCid, &try_two_byte_string); | 1313 __ BranchNotEqual( |
| 1314 CMPRES1, Immediate(kOneByteStringCid), &try_two_byte_string); |
| 1312 | 1315 |
| 1313 // Grab byte and return. | 1316 // Grab byte and return. |
| 1314 __ SmiUntag(T1); | 1317 __ SmiUntag(T1); |
| 1315 __ addu(T2, T0, T1); | 1318 __ addu(T2, T0, T1); |
| 1316 __ lbu(T2, FieldAddress(T2, OneByteString::data_offset())); | 1319 __ lbu(T2, FieldAddress(T2, OneByteString::data_offset())); |
| 1317 __ BranchUnsignedGreaterEqual( | 1320 __ BranchUnsignedGreaterEqual( |
| 1318 T2, Symbols::kNumberOfOneCharCodeSymbols, &fall_through); | 1321 T2, Immediate(Symbols::kNumberOfOneCharCodeSymbols), &fall_through); |
| 1319 __ LoadImmediate( | 1322 __ LoadImmediate( |
| 1320 V0, reinterpret_cast<uword>(Symbols::PredefinedAddress())); | 1323 V0, reinterpret_cast<uword>(Symbols::PredefinedAddress())); |
| 1321 __ AddImmediate(V0, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 1324 __ AddImmediate(V0, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
| 1322 __ sll(T2, T2, 2); | 1325 __ sll(T2, T2, 2); |
| 1323 __ addu(T2, T2, V0); | 1326 __ addu(T2, T2, V0); |
| 1324 __ Ret(); | 1327 __ Ret(); |
| 1325 __ delay_slot()->lw(V0, Address(T2)); | 1328 __ delay_slot()->lw(V0, Address(T2)); |
| 1326 | 1329 |
| 1327 __ Bind(&try_two_byte_string); | 1330 __ Bind(&try_two_byte_string); |
| 1328 __ BranchNotEqual(CMPRES1, kTwoByteStringCid, &fall_through); | 1331 __ BranchNotEqual(CMPRES1, Immediate(kTwoByteStringCid), &fall_through); |
| 1329 ASSERT(kSmiTagShift == 1); | 1332 ASSERT(kSmiTagShift == 1); |
| 1330 __ addu(T2, T0, T1); | 1333 __ addu(T2, T0, T1); |
| 1331 __ lhu(T2, FieldAddress(T2, TwoByteString::data_offset())); | 1334 __ lhu(T2, FieldAddress(T2, TwoByteString::data_offset())); |
| 1332 __ BranchUnsignedGreaterEqual( | 1335 __ BranchUnsignedGreaterEqual( |
| 1333 T2, Symbols::kNumberOfOneCharCodeSymbols, &fall_through); | 1336 T2, Immediate(Symbols::kNumberOfOneCharCodeSymbols), &fall_through); |
| 1334 __ LoadImmediate(V0, | 1337 __ LoadImmediate(V0, |
| 1335 reinterpret_cast<uword>(Symbols::PredefinedAddress())); | 1338 reinterpret_cast<uword>(Symbols::PredefinedAddress())); |
| 1336 __ AddImmediate(V0, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 1339 __ AddImmediate(V0, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
| 1337 __ sll(T2, T2, 2); | 1340 __ sll(T2, T2, 2); |
| 1338 __ addu(T2, T2, V0); | 1341 __ addu(T2, T2, V0); |
| 1339 __ Ret(); | 1342 __ Ret(); |
| 1340 __ delay_slot()->lw(V0, Address(T2)); | 1343 __ delay_slot()->lw(V0, Address(T2)); |
| 1341 | 1344 |
| 1342 __ Bind(&fall_through); | 1345 __ Bind(&fall_through); |
| 1343 } | 1346 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1364 __ lw(T1, Address(SP, 0 * kWordSize)); | 1367 __ lw(T1, Address(SP, 0 * kWordSize)); |
| 1365 __ lw(V0, FieldAddress(T1, String::hash_offset())); | 1368 __ lw(V0, FieldAddress(T1, String::hash_offset())); |
| 1366 __ beq(V0, ZR, &no_hash); | 1369 __ beq(V0, ZR, &no_hash); |
| 1367 __ Ret(); // Return if already computed. | 1370 __ Ret(); // Return if already computed. |
| 1368 __ Bind(&no_hash); | 1371 __ Bind(&no_hash); |
| 1369 | 1372 |
| 1370 __ lw(T2, FieldAddress(T1, String::length_offset())); | 1373 __ lw(T2, FieldAddress(T1, String::length_offset())); |
| 1371 | 1374 |
| 1372 Label done; | 1375 Label done; |
| 1373 // If the string is empty, set the hash to 1, and return. | 1376 // If the string is empty, set the hash to 1, and return. |
| 1374 __ BranchEqual(T2, Smi::RawValue(0), &done); | 1377 __ BranchEqual(T2, Immediate(Smi::RawValue(0)), &done); |
| 1375 __ delay_slot()->mov(V0, ZR); | 1378 __ delay_slot()->mov(V0, ZR); |
| 1376 | 1379 |
| 1377 __ SmiUntag(T2); | 1380 __ SmiUntag(T2); |
| 1378 __ AddImmediate(T3, T1, OneByteString::data_offset() - kHeapObjectTag); | 1381 __ AddImmediate(T3, T1, OneByteString::data_offset() - kHeapObjectTag); |
| 1379 __ addu(T4, T3, T2); | 1382 __ addu(T4, T3, T2); |
| 1380 // V0: Hash code, untagged integer. | 1383 // V0: Hash code, untagged integer. |
| 1381 // T1: Instance of OneByteString. | 1384 // T1: Instance of OneByteString. |
| 1382 // T2: String length, untagged integer. | 1385 // T2: String length, untagged integer. |
| 1383 // T3: String data start. | 1386 // T3: String data start. |
| 1384 // T4: String data end. | 1387 // T4: String data end. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1468 __ UpdateAllocationStatsWithSize(cid, T2, T3, space); | 1471 __ UpdateAllocationStatsWithSize(cid, T2, T3, space); |
| 1469 | 1472 |
| 1470 // Initialize the tags. | 1473 // Initialize the tags. |
| 1471 // V0: new object start as a tagged pointer. | 1474 // V0: new object start as a tagged pointer. |
| 1472 // T1: new object end address. | 1475 // T1: new object end address. |
| 1473 // T2: allocation size. | 1476 // T2: allocation size. |
| 1474 { | 1477 { |
| 1475 Label overflow, done; | 1478 Label overflow, done; |
| 1476 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 1479 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 1477 | 1480 |
| 1478 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); | 1481 __ BranchUnsignedGreater( |
| 1482 T2, Immediate(RawObject::SizeTag::kMaxSizeTag), &overflow); |
| 1479 __ b(&done); | 1483 __ b(&done); |
| 1480 __ delay_slot()->sll(T2, T2, shift); | 1484 __ delay_slot()->sll(T2, T2, shift); |
| 1481 __ Bind(&overflow); | 1485 __ Bind(&overflow); |
| 1482 __ mov(T2, ZR); | 1486 __ mov(T2, ZR); |
| 1483 __ Bind(&done); | 1487 __ Bind(&done); |
| 1484 | 1488 |
| 1485 // Get the class index and insert it into the tags. | 1489 // Get the class index and insert it into the tags. |
| 1486 // T2: size and bit tags. | 1490 // T2: size and bit tags. |
| 1487 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); | 1491 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); |
| 1488 __ or_(T2, T2, TMP); | 1492 __ or_(T2, T2, TMP); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1588 __ lw(T0, Address(SP, 1 * kWordSize)); // This. | 1592 __ lw(T0, Address(SP, 1 * kWordSize)); // This. |
| 1589 __ lw(T1, Address(SP, 0 * kWordSize)); // Other. | 1593 __ lw(T1, Address(SP, 0 * kWordSize)); // Other. |
| 1590 | 1594 |
| 1591 // Are identical? | 1595 // Are identical? |
| 1592 __ beq(T0, T1, &is_true); | 1596 __ beq(T0, T1, &is_true); |
| 1593 | 1597 |
| 1594 // Is other OneByteString? | 1598 // Is other OneByteString? |
| 1595 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 1599 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); |
| 1596 __ beq(CMPRES1, ZR, &fall_through); // Other is Smi. | 1600 __ beq(CMPRES1, ZR, &fall_through); // Other is Smi. |
| 1597 __ LoadClassId(CMPRES1, T1); // Class ID check. | 1601 __ LoadClassId(CMPRES1, T1); // Class ID check. |
| 1598 __ BranchNotEqual(CMPRES1, string_cid, &fall_through); | 1602 __ BranchNotEqual(CMPRES1, Immediate(string_cid), &fall_through); |
| 1599 | 1603 |
| 1600 // Have same length? | 1604 // Have same length? |
| 1601 __ lw(T2, FieldAddress(T0, String::length_offset())); | 1605 __ lw(T2, FieldAddress(T0, String::length_offset())); |
| 1602 __ lw(T3, FieldAddress(T1, String::length_offset())); | 1606 __ lw(T3, FieldAddress(T1, String::length_offset())); |
| 1603 __ bne(T2, T3, &is_false); | 1607 __ bne(T2, T3, &is_false); |
| 1604 | 1608 |
| 1605 // Check contents, no fall-through possible. | 1609 // Check contents, no fall-through possible. |
| 1606 ASSERT((string_cid == kOneByteStringCid) || | 1610 ASSERT((string_cid == kOneByteStringCid) || |
| 1607 (string_cid == kTwoByteStringCid)); | 1611 (string_cid == kTwoByteStringCid)); |
| 1608 __ SmiUntag(T2); | 1612 __ SmiUntag(T2); |
| 1609 __ Bind(&loop); | 1613 __ Bind(&loop); |
| 1610 __ AddImmediate(T2, -1); | 1614 __ AddImmediate(T2, -1); |
| 1611 __ BranchSignedLess(T2, 0, &is_true); | 1615 __ BranchSignedLess(T2, Immediate(0), &is_true); |
| 1612 if (string_cid == kOneByteStringCid) { | 1616 if (string_cid == kOneByteStringCid) { |
| 1613 __ lbu(V0, FieldAddress(T0, OneByteString::data_offset())); | 1617 __ lbu(V0, FieldAddress(T0, OneByteString::data_offset())); |
| 1614 __ lbu(V1, FieldAddress(T1, OneByteString::data_offset())); | 1618 __ lbu(V1, FieldAddress(T1, OneByteString::data_offset())); |
| 1615 __ AddImmediate(T0, 1); | 1619 __ AddImmediate(T0, 1); |
| 1616 __ AddImmediate(T1, 1); | 1620 __ AddImmediate(T1, 1); |
| 1617 } else if (string_cid == kTwoByteStringCid) { | 1621 } else if (string_cid == kTwoByteStringCid) { |
| 1618 __ lhu(V0, FieldAddress(T0, OneByteString::data_offset())); | 1622 __ lhu(V0, FieldAddress(T0, OneByteString::data_offset())); |
| 1619 __ lhu(V1, FieldAddress(T1, OneByteString::data_offset())); | 1623 __ lhu(V1, FieldAddress(T1, OneByteString::data_offset())); |
| 1620 __ AddImmediate(T0, 2); | 1624 __ AddImmediate(T0, 2); |
| 1621 __ AddImmediate(T1, 2); | 1625 __ AddImmediate(T1, 2); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1680 Isolate* isolate = Isolate::Current(); | 1684 Isolate* isolate = Isolate::Current(); |
| 1681 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate)); | 1685 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate)); |
| 1682 // Set return value. | 1686 // Set return value. |
| 1683 __ Ret(); | 1687 __ Ret(); |
| 1684 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset())); | 1688 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset())); |
| 1685 } | 1689 } |
| 1686 | 1690 |
| 1687 } // namespace dart | 1691 } // namespace dart |
| 1688 | 1692 |
| 1689 #endif // defined TARGET_ARCH_MIPS | 1693 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |