| 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 // Save current Context pointer into Isolate structure. | 58 // Save current Context pointer into Isolate structure. |
| 59 __ sw(CTX, Address(A0, Isolate::top_context_offset())); | 59 __ sw(CTX, Address(A0, Isolate::top_context_offset())); |
| 60 | 60 |
| 61 // Cache Isolate pointer into CTX while executing runtime code. | 61 // Cache Isolate pointer into CTX while executing runtime code. |
| 62 __ mov(CTX, A0); | 62 __ mov(CTX, A0); |
| 63 | 63 |
| 64 #if defined(DEBUG) | 64 #if defined(DEBUG) |
| 65 { Label ok; | 65 { Label ok; |
| 66 // Check that we are always entering from Dart code. | 66 // Check that we are always entering from Dart code. |
| 67 __ lw(T0, Address(A0, Isolate::vm_tag_offset())); | 67 __ lw(T0, Address(A0, Isolate::vm_tag_offset())); |
| 68 __ BranchEqual(T0, VMTag::kDartTagId, &ok); | 68 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); |
| 69 __ Stop("Not coming from Dart code."); | 69 __ Stop("Not coming from Dart code."); |
| 70 __ Bind(&ok); | 70 __ Bind(&ok); |
| 71 } | 71 } |
| 72 #endif | 72 #endif |
| 73 | 73 |
| 74 // Mark that the isolate is executing VM code. | 74 // Mark that the isolate is executing VM code. |
| 75 __ sw(S5, Address(A0, Isolate::vm_tag_offset())); | 75 __ sw(S5, Address(A0, Isolate::vm_tag_offset())); |
| 76 | 76 |
| 77 // Reserve space for arguments and align frame before entering C++ world. | 77 // Reserve space for arguments and align frame before entering C++ world. |
| 78 // NativeArguments are passed in registers. | 78 // NativeArguments are passed in registers. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 // Save current Context pointer into Isolate structure. | 184 // Save current Context pointer into Isolate structure. |
| 185 __ sw(CTX, Address(A0, Isolate::top_context_offset())); | 185 __ sw(CTX, Address(A0, Isolate::top_context_offset())); |
| 186 | 186 |
| 187 // Cache Isolate pointer into CTX while executing native code. | 187 // Cache Isolate pointer into CTX while executing native code. |
| 188 __ mov(CTX, A0); | 188 __ mov(CTX, A0); |
| 189 | 189 |
| 190 #if defined(DEBUG) | 190 #if defined(DEBUG) |
| 191 { Label ok; | 191 { Label ok; |
| 192 // Check that we are always entering from Dart code. | 192 // Check that we are always entering from Dart code. |
| 193 __ lw(T0, Address(A0, Isolate::vm_tag_offset())); | 193 __ lw(T0, Address(A0, Isolate::vm_tag_offset())); |
| 194 __ BranchEqual(T0, VMTag::kDartTagId, &ok); | 194 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); |
| 195 __ Stop("Not coming from Dart code."); | 195 __ Stop("Not coming from Dart code."); |
| 196 __ Bind(&ok); | 196 __ Bind(&ok); |
| 197 } | 197 } |
| 198 #endif | 198 #endif |
| 199 | 199 |
| 200 // Mark that the isolate is executing Native code. | 200 // Mark that the isolate is executing Native code. |
| 201 __ sw(T5, Address(A0, Isolate::vm_tag_offset())); | 201 __ sw(T5, Address(A0, Isolate::vm_tag_offset())); |
| 202 | 202 |
| 203 // Initialize NativeArguments structure and call native function. | 203 // Initialize NativeArguments structure and call native function. |
| 204 // Registers A0, A1, A2, and A3 are used. | 204 // Registers A0, A1, A2, and A3 are used. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 // Save current Context pointer into Isolate structure. | 299 // Save current Context pointer into Isolate structure. |
| 300 __ sw(CTX, Address(A0, Isolate::top_context_offset())); | 300 __ sw(CTX, Address(A0, Isolate::top_context_offset())); |
| 301 | 301 |
| 302 // Cache Isolate pointer into CTX while executing native code. | 302 // Cache Isolate pointer into CTX while executing native code. |
| 303 __ mov(CTX, A0); | 303 __ mov(CTX, A0); |
| 304 | 304 |
| 305 #if defined(DEBUG) | 305 #if defined(DEBUG) |
| 306 { Label ok; | 306 { Label ok; |
| 307 // Check that we are always entering from Dart code. | 307 // Check that we are always entering from Dart code. |
| 308 __ lw(T0, Address(A0, Isolate::vm_tag_offset())); | 308 __ lw(T0, Address(A0, Isolate::vm_tag_offset())); |
| 309 __ BranchEqual(T0, VMTag::kDartTagId, &ok); | 309 __ BranchEqual(T0, Immediate(VMTag::kDartTagId), &ok); |
| 310 __ Stop("Not coming from Dart code."); | 310 __ Stop("Not coming from Dart code."); |
| 311 __ Bind(&ok); | 311 __ Bind(&ok); |
| 312 } | 312 } |
| 313 #endif | 313 #endif |
| 314 | 314 |
| 315 // Mark that the isolate is executing Native code. | 315 // Mark that the isolate is executing Native code. |
| 316 __ sw(T5, Address(A0, Isolate::vm_tag_offset())); | 316 __ sw(T5, Address(A0, Isolate::vm_tag_offset())); |
| 317 | 317 |
| 318 // Initialize NativeArguments structure and call native function. | 318 // Initialize NativeArguments structure and call native function. |
| 319 // Registers A0, A1, A2, and A3 are used. | 319 // Registers A0, A1, A2, and A3 are used. |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 __ mov(T3, A1); // Array length. | 697 __ mov(T3, A1); // Array length. |
| 698 | 698 |
| 699 // Check that length is a positive Smi. | 699 // Check that length is a positive Smi. |
| 700 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); | 700 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); |
| 701 __ bne(CMPRES1, ZR, &slow_case); | 701 __ bne(CMPRES1, ZR, &slow_case); |
| 702 __ bltz(T3, &slow_case); | 702 __ bltz(T3, &slow_case); |
| 703 | 703 |
| 704 // Check for maximum allowed length. | 704 // Check for maximum allowed length. |
| 705 const intptr_t max_len = | 705 const intptr_t max_len = |
| 706 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); | 706 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); |
| 707 __ BranchUnsignedGreater(T3, max_len, &slow_case); | 707 __ BranchUnsignedGreater(T3, Immediate(max_len), &slow_case); |
| 708 | 708 |
| 709 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 709 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 710 __ LoadImmediate(T2, fixed_size); | 710 __ LoadImmediate(T2, fixed_size); |
| 711 __ sll(T3, T3, 1); // T3 is a Smi. | 711 __ sll(T3, T3, 1); // T3 is a Smi. |
| 712 __ addu(T2, T2, T3); | 712 __ addu(T2, T2, T3); |
| 713 ASSERT(kSmiTagShift == 1); | 713 ASSERT(kSmiTagShift == 1); |
| 714 __ LoadImmediate(T3, ~(kObjectAlignment - 1)); | 714 __ LoadImmediate(T3, ~(kObjectAlignment - 1)); |
| 715 __ and_(T2, T2, T3); | 715 __ and_(T2, T2, T3); |
| 716 | 716 |
| 717 // T2: Allocation size. | 717 // T2: Allocation size. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 741 __ UpdateAllocationStatsWithSize(cid, T2, T4, space); | 741 __ UpdateAllocationStatsWithSize(cid, T2, T4, space); |
| 742 | 742 |
| 743 // Initialize the tags. | 743 // Initialize the tags. |
| 744 // T0: new object start as a tagged pointer. | 744 // T0: new object start as a tagged pointer. |
| 745 // T1: new object end address. | 745 // T1: new object end address. |
| 746 // T2: allocation size. | 746 // T2: allocation size. |
| 747 { | 747 { |
| 748 Label overflow, done; | 748 Label overflow, done; |
| 749 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 749 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 750 | 750 |
| 751 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); | 751 __ BranchUnsignedGreater( |
| 752 T2, Immediate(RawObject::SizeTag::kMaxSizeTag), &overflow); |
| 752 __ b(&done); | 753 __ b(&done); |
| 753 __ delay_slot()->sll(T2, T2, shift); | 754 __ delay_slot()->sll(T2, T2, shift); |
| 754 __ Bind(&overflow); | 755 __ Bind(&overflow); |
| 755 __ mov(T2, ZR); | 756 __ mov(T2, ZR); |
| 756 __ Bind(&done); | 757 __ Bind(&done); |
| 757 | 758 |
| 758 // Get the class index and insert it into the tags. | 759 // Get the class index and insert it into the tags. |
| 759 // T2: size and bit tags. | 760 // T2: size and bit tags. |
| 760 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); | 761 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); |
| 761 __ or_(T2, T2, TMP); | 762 __ or_(T2, T2, TMP); |
| (...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 // S5: IC data object (preserved). | 1440 // S5: IC data object (preserved). |
| 1440 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1441 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
| 1441 // T0: ic_data_array with check entries: classes and target functions. | 1442 // T0: ic_data_array with check entries: classes and target functions. |
| 1442 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1443 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
| 1443 // T0: points directly to the first ic data array element. | 1444 // T0: points directly to the first ic data array element. |
| 1444 #if defined(DEBUG) | 1445 #if defined(DEBUG) |
| 1445 // Check that first entry is for Smi/Smi. | 1446 // Check that first entry is for Smi/Smi. |
| 1446 Label error, ok; | 1447 Label error, ok; |
| 1447 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid)); | 1448 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid)); |
| 1448 __ lw(T4, Address(T0)); | 1449 __ lw(T4, Address(T0)); |
| 1449 __ BranchNotEqual(T4, imm_smi_cid, &error); | 1450 __ BranchNotEqual(T4, Immediate(imm_smi_cid), &error); |
| 1450 __ lw(T4, Address(T0, kWordSize)); | 1451 __ lw(T4, Address(T0, kWordSize)); |
| 1451 __ BranchEqual(T4, imm_smi_cid, &ok); | 1452 __ BranchEqual(T4, Immediate(imm_smi_cid), &ok); |
| 1452 __ Bind(&error); | 1453 __ Bind(&error); |
| 1453 __ Stop("Incorrect IC data"); | 1454 __ Stop("Incorrect IC data"); |
| 1454 __ Bind(&ok); | 1455 __ Bind(&ok); |
| 1455 #endif | 1456 #endif |
| 1456 // Update counter. | 1457 // Update counter. |
| 1457 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1458 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1458 __ lw(T4, Address(T0, count_offset)); | 1459 __ lw(T4, Address(T0, count_offset)); |
| 1459 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); | 1460 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); |
| 1460 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. | 1461 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. |
| 1461 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); | 1462 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1483 Token::Kind kind) { | 1484 Token::Kind kind) { |
| 1484 __ TraceSimMsg("NArgsCheckInlineCacheStub"); | 1485 __ TraceSimMsg("NArgsCheckInlineCacheStub"); |
| 1485 ASSERT(num_args > 0); | 1486 ASSERT(num_args > 0); |
| 1486 #if defined(DEBUG) | 1487 #if defined(DEBUG) |
| 1487 { Label ok; | 1488 { Label ok; |
| 1488 // Check that the IC data array has NumArgsTested() == num_args. | 1489 // Check that the IC data array has NumArgsTested() == num_args. |
| 1489 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1490 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
| 1490 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); | 1491 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); |
| 1491 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1492 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1492 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); | 1493 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); |
| 1493 __ BranchEqual(T0, num_args, &ok); | 1494 __ BranchEqual(T0, Immediate(num_args), &ok); |
| 1494 __ Stop("Incorrect stub for IC data"); | 1495 __ Stop("Incorrect stub for IC data"); |
| 1495 __ Bind(&ok); | 1496 __ Bind(&ok); |
| 1496 } | 1497 } |
| 1497 #endif // DEBUG | 1498 #endif // DEBUG |
| 1498 | 1499 |
| 1499 | 1500 |
| 1500 // Check single stepping. | 1501 // Check single stepping. |
| 1501 Label stepping, done_stepping; | 1502 Label stepping, done_stepping; |
| 1502 __ LoadImmediate(T0, Isolate::CurrentAddress()); | 1503 __ LoadImmediate(T0, Isolate::CurrentAddress()); |
| 1503 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1504 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1504 __ BranchNotEqual(T0, 0, &stepping); | 1505 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 1505 __ Bind(&done_stepping); | 1506 __ Bind(&done_stepping); |
| 1506 | 1507 |
| 1507 if (kind != Token::kILLEGAL) { | 1508 if (kind != Token::kILLEGAL) { |
| 1508 Label not_smi_or_overflow; | 1509 Label not_smi_or_overflow; |
| 1509 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1510 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
| 1510 __ Bind(¬_smi_or_overflow); | 1511 __ Bind(¬_smi_or_overflow); |
| 1511 } | 1512 } |
| 1512 | 1513 |
| 1513 // Load argument descriptor into S4. | 1514 // Load argument descriptor into S4. |
| 1514 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1515 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1569 __ addu(T3, T3, SP); | 1570 __ addu(T3, T3, SP); |
| 1570 __ lw(T3, Address(T3)); | 1571 __ lw(T3, Address(T3)); |
| 1571 __ LoadTaggedClassIdMayBeSmi(T3, T3); | 1572 __ LoadTaggedClassIdMayBeSmi(T3, T3); |
| 1572 } | 1573 } |
| 1573 | 1574 |
| 1574 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1575 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1575 __ AddImmediate(T0, entry_size); // Next entry. | 1576 __ AddImmediate(T0, entry_size); // Next entry. |
| 1576 __ lw(T4, Address(T0)); // Next class ID. | 1577 __ lw(T4, Address(T0)); // Next class ID. |
| 1577 | 1578 |
| 1578 __ Bind(&test); | 1579 __ Bind(&test); |
| 1579 __ BranchNotEqual(T4, Smi::RawValue(kIllegalCid), &loop); // Done? | 1580 __ BranchNotEqual(T4, Immediate(Smi::RawValue(kIllegalCid)), &loop); // Done? |
| 1580 | 1581 |
| 1581 // IC miss. | 1582 // IC miss. |
| 1582 // Restore return address. | 1583 // Restore return address. |
| 1583 __ mov(RA, T2); | 1584 __ mov(RA, T2); |
| 1584 | 1585 |
| 1585 // Compute address of arguments (first read number of arguments from | 1586 // Compute address of arguments (first read number of arguments from |
| 1586 // arguments descriptor array and then compute address on the stack). | 1587 // arguments descriptor array and then compute address on the stack). |
| 1587 // T1: argument_count - 1 (smi). | 1588 // T1: argument_count - 1 (smi). |
| 1588 __ sll(T1, T1, 1); // T1 is Smi. | 1589 __ sll(T1, T1, 1); // T1 is Smi. |
| 1589 __ addu(T1, SP, T1); | 1590 __ addu(T1, SP, T1); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 __ beq(T0, ZR, &ok); | 1751 __ beq(T0, ZR, &ok); |
| 1751 __ Stop("Incorrect IC data for unoptimized static call"); | 1752 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1752 __ Bind(&ok); | 1753 __ Bind(&ok); |
| 1753 } | 1754 } |
| 1754 #endif // DEBUG | 1755 #endif // DEBUG |
| 1755 | 1756 |
| 1756 // Check single stepping. | 1757 // Check single stepping. |
| 1757 Label stepping, done_stepping; | 1758 Label stepping, done_stepping; |
| 1758 __ LoadImmediate(T0, Isolate::CurrentAddress()); | 1759 __ LoadImmediate(T0, Isolate::CurrentAddress()); |
| 1759 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1760 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1760 __ BranchNotEqual(T0, 0, &stepping); | 1761 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 1761 __ Bind(&done_stepping); | 1762 __ Bind(&done_stepping); |
| 1762 | 1763 |
| 1763 // S5: IC data object (preserved). | 1764 // S5: IC data object (preserved). |
| 1764 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1765 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
| 1765 // T0: ic_data_array with entries: target functions and count. | 1766 // T0: ic_data_array with entries: target functions and count. |
| 1766 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1767 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
| 1767 // T0: points directly to the first ic data array element. | 1768 // T0: points directly to the first ic data array element. |
| 1768 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1769 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1769 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1770 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1770 | 1771 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1897 } | 1898 } |
| 1898 | 1899 |
| 1899 | 1900 |
| 1900 // Called only from unoptimized code. All relevant registers have been saved. | 1901 // Called only from unoptimized code. All relevant registers have been saved. |
| 1901 // RA: return address. | 1902 // RA: return address. |
| 1902 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1903 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
| 1903 // Check single stepping. | 1904 // Check single stepping. |
| 1904 Label stepping, done_stepping; | 1905 Label stepping, done_stepping; |
| 1905 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 1906 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
| 1906 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1907 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1907 __ BranchNotEqual(T0, 0, &stepping); | 1908 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 1908 __ Bind(&done_stepping); | 1909 __ Bind(&done_stepping); |
| 1909 | 1910 |
| 1910 __ Ret(); | 1911 __ Ret(); |
| 1911 | 1912 |
| 1912 // Call single step callback in debugger. | 1913 // Call single step callback in debugger. |
| 1913 __ Bind(&stepping); | 1914 __ Bind(&stepping); |
| 1914 __ EnterStubFrame(); | 1915 __ EnterStubFrame(); |
| 1915 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 1916 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
| 1916 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1917 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
| 1917 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1918 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1932 __ TraceSimMsg("SubtypeNTestCacheStub"); | 1933 __ TraceSimMsg("SubtypeNTestCacheStub"); |
| 1933 ASSERT((1 <= n) && (n <= 3)); | 1934 ASSERT((1 <= n) && (n <= 3)); |
| 1934 if (n > 1) { | 1935 if (n > 1) { |
| 1935 // Get instance type arguments. | 1936 // Get instance type arguments. |
| 1936 __ LoadClass(T0, A0); | 1937 __ LoadClass(T0, A0); |
| 1937 // Compute instance type arguments into T1. | 1938 // Compute instance type arguments into T1. |
| 1938 Label has_no_type_arguments; | 1939 Label has_no_type_arguments; |
| 1939 __ LoadImmediate(T1, reinterpret_cast<intptr_t>(Object::null())); | 1940 __ LoadImmediate(T1, reinterpret_cast<intptr_t>(Object::null())); |
| 1940 __ lw(T2, FieldAddress(T0, | 1941 __ lw(T2, FieldAddress(T0, |
| 1941 Class::type_arguments_field_offset_in_words_offset())); | 1942 Class::type_arguments_field_offset_in_words_offset())); |
| 1942 __ BranchEqual(T2, Class::kNoTypeArguments, &has_no_type_arguments); | 1943 __ BranchEqual( |
| 1944 T2, Immediate(Class::kNoTypeArguments), &has_no_type_arguments); |
| 1943 __ sll(T2, T2, 2); | 1945 __ sll(T2, T2, 2); |
| 1944 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4 | 1946 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4 |
| 1945 __ lw(T1, FieldAddress(T2, 0)); | 1947 __ lw(T1, FieldAddress(T2, 0)); |
| 1946 __ Bind(&has_no_type_arguments); | 1948 __ Bind(&has_no_type_arguments); |
| 1947 } | 1949 } |
| 1948 __ LoadClassId(T0, A0); | 1950 __ LoadClassId(T0, A0); |
| 1949 // A0: instance. | 1951 // A0: instance. |
| 1950 // A1: instantiator type arguments or NULL. | 1952 // A1: instantiator type arguments or NULL. |
| 1951 // A2: SubtypeTestCache. | 1953 // A2: SubtypeTestCache. |
| 1952 // T0: instance class id. | 1954 // T0: instance class id. |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2185 // RA: return address. | 2187 // RA: return address. |
| 2186 // SP + 4: left operand. | 2188 // SP + 4: left operand. |
| 2187 // SP + 0: right operand. | 2189 // SP + 0: right operand. |
| 2188 // Returns: CMPRES1 is zero if equal, non-zero otherwise. | 2190 // Returns: CMPRES1 is zero if equal, non-zero otherwise. |
| 2189 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2191 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 2190 Assembler* assembler) { | 2192 Assembler* assembler) { |
| 2191 // Check single stepping. | 2193 // Check single stepping. |
| 2192 Label stepping, done_stepping; | 2194 Label stepping, done_stepping; |
| 2193 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 2195 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
| 2194 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 2196 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 2195 __ BranchNotEqual(T0, 0, &stepping); | 2197 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 2196 __ Bind(&done_stepping); | 2198 __ Bind(&done_stepping); |
| 2197 | 2199 |
| 2198 const Register temp1 = T2; | 2200 const Register temp1 = T2; |
| 2199 const Register temp2 = T3; | 2201 const Register temp2 = T3; |
| 2200 const Register left = T1; | 2202 const Register left = T1; |
| 2201 const Register right = T0; | 2203 const Register right = T0; |
| 2202 __ lw(left, Address(SP, 1 * kWordSize)); | 2204 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2203 __ lw(right, Address(SP, 0 * kWordSize)); | 2205 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2204 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2206 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2205 __ Ret(); | 2207 __ Ret(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2229 const Register right = T0; | 2231 const Register right = T0; |
| 2230 __ lw(left, Address(SP, 1 * kWordSize)); | 2232 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2231 __ lw(right, Address(SP, 0 * kWordSize)); | 2233 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2232 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2234 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2233 __ Ret(); | 2235 __ Ret(); |
| 2234 } | 2236 } |
| 2235 | 2237 |
| 2236 } // namespace dart | 2238 } // namespace dart |
| 2237 | 2239 |
| 2238 #endif // defined TARGET_ARCH_MIPS | 2240 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |