| 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 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 __ mov(T3, A1); // Array length. | 730 __ mov(T3, A1); // Array length. |
| 731 | 731 |
| 732 // Check that length is a positive Smi. | 732 // Check that length is a positive Smi. |
| 733 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); | 733 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); |
| 734 __ bne(CMPRES1, ZR, &slow_case); | 734 __ bne(CMPRES1, ZR, &slow_case); |
| 735 __ bltz(T3, &slow_case); | 735 __ bltz(T3, &slow_case); |
| 736 | 736 |
| 737 // Check for maximum allowed length. | 737 // Check for maximum allowed length. |
| 738 const intptr_t max_len = | 738 const intptr_t max_len = |
| 739 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); | 739 reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); |
| 740 __ BranchUnsignedGreater(T3, max_len, &slow_case); | 740 __ BranchUnsignedGreater(T3, Immediate(max_len), &slow_case); |
| 741 | 741 |
| 742 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 742 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 743 __ LoadImmediate(T2, fixed_size); | 743 __ LoadImmediate(T2, fixed_size); |
| 744 __ sll(T3, T3, 1); // T3 is a Smi. | 744 __ sll(T3, T3, 1); // T3 is a Smi. |
| 745 __ addu(T2, T2, T3); | 745 __ addu(T2, T2, T3); |
| 746 ASSERT(kSmiTagShift == 1); | 746 ASSERT(kSmiTagShift == 1); |
| 747 __ LoadImmediate(T3, ~(kObjectAlignment - 1)); | 747 __ LoadImmediate(T3, ~(kObjectAlignment - 1)); |
| 748 __ and_(T2, T2, T3); | 748 __ and_(T2, T2, T3); |
| 749 | 749 |
| 750 // T2: Allocation size. | 750 // T2: Allocation size. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 774 __ UpdateAllocationStatsWithSize(cid, T2, T4, space); | 774 __ UpdateAllocationStatsWithSize(cid, T2, T4, space); |
| 775 | 775 |
| 776 // Initialize the tags. | 776 // Initialize the tags. |
| 777 // T0: new object start as a tagged pointer. | 777 // T0: new object start as a tagged pointer. |
| 778 // T1: new object end address. | 778 // T1: new object end address. |
| 779 // T2: allocation size. | 779 // T2: allocation size. |
| 780 { | 780 { |
| 781 Label overflow, done; | 781 Label overflow, done; |
| 782 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 782 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 783 | 783 |
| 784 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); | 784 __ BranchUnsignedGreater( |
| 785 T2, Immediate(RawObject::SizeTag::kMaxSizeTag), &overflow); |
| 785 __ b(&done); | 786 __ b(&done); |
| 786 __ delay_slot()->sll(T2, T2, shift); | 787 __ delay_slot()->sll(T2, T2, shift); |
| 787 __ Bind(&overflow); | 788 __ Bind(&overflow); |
| 788 __ mov(T2, ZR); | 789 __ mov(T2, ZR); |
| 789 __ Bind(&done); | 790 __ Bind(&done); |
| 790 | 791 |
| 791 // Get the class index and insert it into the tags. | 792 // Get the class index and insert it into the tags. |
| 792 // T2: size and bit tags. | 793 // T2: size and bit tags. |
| 793 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); | 794 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); |
| 794 __ or_(T2, T2, TMP); | 795 __ or_(T2, T2, TMP); |
| (...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1475 // S5: IC data object (preserved). | 1476 // S5: IC data object (preserved). |
| 1476 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1477 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
| 1477 // T0: ic_data_array with check entries: classes and target functions. | 1478 // T0: ic_data_array with check entries: classes and target functions. |
| 1478 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1479 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
| 1479 // T0: points directly to the first ic data array element. | 1480 // T0: points directly to the first ic data array element. |
| 1480 #if defined(DEBUG) | 1481 #if defined(DEBUG) |
| 1481 // Check that first entry is for Smi/Smi. | 1482 // Check that first entry is for Smi/Smi. |
| 1482 Label error, ok; | 1483 Label error, ok; |
| 1483 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid)); | 1484 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid)); |
| 1484 __ lw(T4, Address(T0)); | 1485 __ lw(T4, Address(T0)); |
| 1485 __ BranchNotEqual(T4, imm_smi_cid, &error); | 1486 __ BranchNotEqual(T4, Immediate(imm_smi_cid), &error); |
| 1486 __ lw(T4, Address(T0, kWordSize)); | 1487 __ lw(T4, Address(T0, kWordSize)); |
| 1487 __ BranchEqual(T4, imm_smi_cid, &ok); | 1488 __ BranchEqual(T4, Immediate(imm_smi_cid), &ok); |
| 1488 __ Bind(&error); | 1489 __ Bind(&error); |
| 1489 __ Stop("Incorrect IC data"); | 1490 __ Stop("Incorrect IC data"); |
| 1490 __ Bind(&ok); | 1491 __ Bind(&ok); |
| 1491 #endif | 1492 #endif |
| 1492 // Update counter. | 1493 // Update counter. |
| 1493 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1494 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1494 __ lw(T4, Address(T0, count_offset)); | 1495 __ lw(T4, Address(T0, count_offset)); |
| 1495 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); | 1496 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); |
| 1496 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. | 1497 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. |
| 1497 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); | 1498 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1519 Token::Kind kind) { | 1520 Token::Kind kind) { |
| 1520 __ TraceSimMsg("NArgsCheckInlineCacheStub"); | 1521 __ TraceSimMsg("NArgsCheckInlineCacheStub"); |
| 1521 ASSERT(num_args > 0); | 1522 ASSERT(num_args > 0); |
| 1522 #if defined(DEBUG) | 1523 #if defined(DEBUG) |
| 1523 { Label ok; | 1524 { Label ok; |
| 1524 // Check that the IC data array has NumArgsTested() == num_args. | 1525 // Check that the IC data array has NumArgsTested() == num_args. |
| 1525 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1526 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
| 1526 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); | 1527 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); |
| 1527 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1528 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1528 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); | 1529 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); |
| 1529 __ BranchEqual(T0, num_args, &ok); | 1530 __ BranchEqual(T0, Immediate(num_args), &ok); |
| 1530 __ Stop("Incorrect stub for IC data"); | 1531 __ Stop("Incorrect stub for IC data"); |
| 1531 __ Bind(&ok); | 1532 __ Bind(&ok); |
| 1532 } | 1533 } |
| 1533 #endif // DEBUG | 1534 #endif // DEBUG |
| 1534 | 1535 |
| 1535 | 1536 |
| 1536 // Check single stepping. | 1537 // Check single stepping. |
| 1537 Label stepping, done_stepping; | 1538 Label stepping, done_stepping; |
| 1538 __ LoadIsolate(T0); | 1539 __ LoadIsolate(T0); |
| 1539 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1540 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1540 __ BranchNotEqual(T0, 0, &stepping); | 1541 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 1541 __ Bind(&done_stepping); | 1542 __ Bind(&done_stepping); |
| 1542 | 1543 |
| 1543 if (kind != Token::kILLEGAL) { | 1544 if (kind != Token::kILLEGAL) { |
| 1544 Label not_smi_or_overflow; | 1545 Label not_smi_or_overflow; |
| 1545 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1546 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
| 1546 __ Bind(¬_smi_or_overflow); | 1547 __ Bind(¬_smi_or_overflow); |
| 1547 } | 1548 } |
| 1548 | 1549 |
| 1549 // Load argument descriptor into S4. | 1550 // Load argument descriptor into S4. |
| 1550 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1551 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1605 __ addu(T3, T3, SP); | 1606 __ addu(T3, T3, SP); |
| 1606 __ lw(T3, Address(T3)); | 1607 __ lw(T3, Address(T3)); |
| 1607 __ LoadTaggedClassIdMayBeSmi(T3, T3); | 1608 __ LoadTaggedClassIdMayBeSmi(T3, T3); |
| 1608 } | 1609 } |
| 1609 | 1610 |
| 1610 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1611 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1611 __ AddImmediate(T0, entry_size); // Next entry. | 1612 __ AddImmediate(T0, entry_size); // Next entry. |
| 1612 __ lw(T4, Address(T0)); // Next class ID. | 1613 __ lw(T4, Address(T0)); // Next class ID. |
| 1613 | 1614 |
| 1614 __ Bind(&test); | 1615 __ Bind(&test); |
| 1615 __ BranchNotEqual(T4, Smi::RawValue(kIllegalCid), &loop); // Done? | 1616 __ BranchNotEqual(T4, Immediate(Smi::RawValue(kIllegalCid)), &loop); // Done? |
| 1616 | 1617 |
| 1617 // IC miss. | 1618 // IC miss. |
| 1618 // Restore return address. | 1619 // Restore return address. |
| 1619 __ mov(RA, T2); | 1620 __ mov(RA, T2); |
| 1620 | 1621 |
| 1621 // Compute address of arguments (first read number of arguments from | 1622 // Compute address of arguments (first read number of arguments from |
| 1622 // arguments descriptor array and then compute address on the stack). | 1623 // arguments descriptor array and then compute address on the stack). |
| 1623 // T1: argument_count - 1 (smi). | 1624 // T1: argument_count - 1 (smi). |
| 1624 __ sll(T1, T1, 1); // T1 is Smi. | 1625 __ sll(T1, T1, 1); // T1 is Smi. |
| 1625 __ addu(T1, SP, T1); | 1626 __ addu(T1, SP, T1); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1786 __ beq(T0, ZR, &ok); | 1787 __ beq(T0, ZR, &ok); |
| 1787 __ Stop("Incorrect IC data for unoptimized static call"); | 1788 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1788 __ Bind(&ok); | 1789 __ Bind(&ok); |
| 1789 } | 1790 } |
| 1790 #endif // DEBUG | 1791 #endif // DEBUG |
| 1791 | 1792 |
| 1792 // Check single stepping. | 1793 // Check single stepping. |
| 1793 Label stepping, done_stepping; | 1794 Label stepping, done_stepping; |
| 1794 __ LoadIsolate(T0); | 1795 __ LoadIsolate(T0); |
| 1795 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1796 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1796 __ BranchNotEqual(T0, 0, &stepping); | 1797 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 1797 __ Bind(&done_stepping); | 1798 __ Bind(&done_stepping); |
| 1798 | 1799 |
| 1799 // S5: IC data object (preserved). | 1800 // S5: IC data object (preserved). |
| 1800 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1801 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
| 1801 // T0: ic_data_array with entries: target functions and count. | 1802 // T0: ic_data_array with entries: target functions and count. |
| 1802 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1803 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
| 1803 // T0: points directly to the first ic data array element. | 1804 // T0: points directly to the first ic data array element. |
| 1804 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1805 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1805 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1806 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1806 | 1807 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1933 } | 1934 } |
| 1934 | 1935 |
| 1935 | 1936 |
| 1936 // Called only from unoptimized code. All relevant registers have been saved. | 1937 // Called only from unoptimized code. All relevant registers have been saved. |
| 1937 // RA: return address. | 1938 // RA: return address. |
| 1938 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1939 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
| 1939 // Check single stepping. | 1940 // Check single stepping. |
| 1940 Label stepping, done_stepping; | 1941 Label stepping, done_stepping; |
| 1941 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 1942 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
| 1942 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1943 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1943 __ BranchNotEqual(T0, 0, &stepping); | 1944 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 1944 __ Bind(&done_stepping); | 1945 __ Bind(&done_stepping); |
| 1945 | 1946 |
| 1946 __ Ret(); | 1947 __ Ret(); |
| 1947 | 1948 |
| 1948 // Call single step callback in debugger. | 1949 // Call single step callback in debugger. |
| 1949 __ Bind(&stepping); | 1950 __ Bind(&stepping); |
| 1950 __ EnterStubFrame(); | 1951 __ EnterStubFrame(); |
| 1951 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 1952 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
| 1952 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. | 1953 __ sw(RA, Address(SP, 0 * kWordSize)); // Return address. |
| 1953 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1954 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1968 __ TraceSimMsg("SubtypeNTestCacheStub"); | 1969 __ TraceSimMsg("SubtypeNTestCacheStub"); |
| 1969 ASSERT((1 <= n) && (n <= 3)); | 1970 ASSERT((1 <= n) && (n <= 3)); |
| 1970 if (n > 1) { | 1971 if (n > 1) { |
| 1971 // Get instance type arguments. | 1972 // Get instance type arguments. |
| 1972 __ LoadClass(T0, A0); | 1973 __ LoadClass(T0, A0); |
| 1973 // Compute instance type arguments into T1. | 1974 // Compute instance type arguments into T1. |
| 1974 Label has_no_type_arguments; | 1975 Label has_no_type_arguments; |
| 1975 __ LoadImmediate(T1, reinterpret_cast<intptr_t>(Object::null())); | 1976 __ LoadImmediate(T1, reinterpret_cast<intptr_t>(Object::null())); |
| 1976 __ lw(T2, FieldAddress(T0, | 1977 __ lw(T2, FieldAddress(T0, |
| 1977 Class::type_arguments_field_offset_in_words_offset())); | 1978 Class::type_arguments_field_offset_in_words_offset())); |
| 1978 __ BranchEqual(T2, Class::kNoTypeArguments, &has_no_type_arguments); | 1979 __ BranchEqual( |
| 1980 T2, Immediate(Class::kNoTypeArguments), &has_no_type_arguments); |
| 1979 __ sll(T2, T2, 2); | 1981 __ sll(T2, T2, 2); |
| 1980 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4 | 1982 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4 |
| 1981 __ lw(T1, FieldAddress(T2, 0)); | 1983 __ lw(T1, FieldAddress(T2, 0)); |
| 1982 __ Bind(&has_no_type_arguments); | 1984 __ Bind(&has_no_type_arguments); |
| 1983 } | 1985 } |
| 1984 __ LoadClassId(T0, A0); | 1986 __ LoadClassId(T0, A0); |
| 1985 // A0: instance. | 1987 // A0: instance. |
| 1986 // A1: instantiator type arguments or NULL. | 1988 // A1: instantiator type arguments or NULL. |
| 1987 // A2: SubtypeTestCache. | 1989 // A2: SubtypeTestCache. |
| 1988 // T0: instance class id. | 1990 // T0: instance class id. |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2221 // RA: return address. | 2223 // RA: return address. |
| 2222 // SP + 4: left operand. | 2224 // SP + 4: left operand. |
| 2223 // SP + 0: right operand. | 2225 // SP + 0: right operand. |
| 2224 // Returns: CMPRES1 is zero if equal, non-zero otherwise. | 2226 // Returns: CMPRES1 is zero if equal, non-zero otherwise. |
| 2225 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2227 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 2226 Assembler* assembler) { | 2228 Assembler* assembler) { |
| 2227 // Check single stepping. | 2229 // Check single stepping. |
| 2228 Label stepping, done_stepping; | 2230 Label stepping, done_stepping; |
| 2229 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); | 2231 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); |
| 2230 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 2232 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 2231 __ BranchNotEqual(T0, 0, &stepping); | 2233 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 2232 __ Bind(&done_stepping); | 2234 __ Bind(&done_stepping); |
| 2233 | 2235 |
| 2234 const Register temp1 = T2; | 2236 const Register temp1 = T2; |
| 2235 const Register temp2 = T3; | 2237 const Register temp2 = T3; |
| 2236 const Register left = T1; | 2238 const Register left = T1; |
| 2237 const Register right = T0; | 2239 const Register right = T0; |
| 2238 __ lw(left, Address(SP, 1 * kWordSize)); | 2240 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2239 __ lw(right, Address(SP, 0 * kWordSize)); | 2241 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2240 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2242 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2241 __ Ret(); | 2243 __ Ret(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2265 const Register right = T0; | 2267 const Register right = T0; |
| 2266 __ lw(left, Address(SP, 1 * kWordSize)); | 2268 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2267 __ lw(right, Address(SP, 0 * kWordSize)); | 2269 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2268 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2270 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2269 __ Ret(); | 2271 __ Ret(); |
| 2270 } | 2272 } |
| 2271 | 2273 |
| 2272 } // namespace dart | 2274 } // namespace dart |
| 2273 | 2275 |
| 2274 #endif // defined TARGET_ARCH_MIPS | 2276 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |