| 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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 __ addu(T1, FP, T1); | 293 __ addu(T1, FP, T1); |
| 294 __ AddImmediate(T1, kParamEndSlotFromFp * kWordSize); | 294 __ AddImmediate(T1, kParamEndSlotFromFp * kWordSize); |
| 295 // T1: address of first argument on stack. | 295 // T1: address of first argument on stack. |
| 296 // T2: address of first argument in array. | 296 // T2: address of first argument in array. |
| 297 | 297 |
| 298 Label loop, loop_exit; | 298 Label loop, loop_exit; |
| 299 __ blez(A1, &loop_exit); | 299 __ blez(A1, &loop_exit); |
| 300 __ delay_slot()->addiu(T2, V0, | 300 __ delay_slot()->addiu(T2, V0, |
| 301 Immediate(Array::data_offset() - kHeapObjectTag)); | 301 Immediate(Array::data_offset() - kHeapObjectTag)); |
| 302 __ Bind(&loop); | 302 __ Bind(&loop); |
| 303 __ lw(TMP, Address(T1)); | 303 __ lw(T3, Address(T1)); |
| 304 __ addiu(A1, A1, Immediate(-Smi::RawValue(1))); | 304 __ addiu(A1, A1, Immediate(-Smi::RawValue(1))); |
| 305 __ addiu(T1, T1, Immediate(-kWordSize)); | 305 __ addiu(T1, T1, Immediate(-kWordSize)); |
| 306 __ addiu(T2, T2, Immediate(kWordSize)); | 306 __ addiu(T2, T2, Immediate(kWordSize)); |
| 307 __ bgez(A1, &loop); | 307 __ bgez(A1, &loop); |
| 308 __ delay_slot()->sw(TMP, Address(T2, -kWordSize)); | 308 __ delay_slot()->sw(T3, Address(T2, -kWordSize)); |
| 309 __ Bind(&loop_exit); | 309 __ Bind(&loop_exit); |
| 310 } | 310 } |
| 311 | 311 |
| 312 | 312 |
| 313 // Input parameters: | 313 // Input parameters: |
| 314 // S5: ic-data. | 314 // S5: ic-data. |
| 315 // S4: arguments descriptor array. | 315 // S4: arguments descriptor array. |
| 316 // Note: The receiver object is the first argument to the function being | 316 // Note: The receiver object is the first argument to the function being |
| 317 // called, the stub accesses the receiver from this location directly | 317 // called, the stub accesses the receiver from this location directly |
| 318 // when trying to resolve the call. | 318 // when trying to resolve the call. |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 __ and_(T3, T3, TMP1); | 582 __ and_(T3, T3, TMP1); |
| 583 __ addu(T2, T3, V0); | 583 __ addu(T2, T3, V0); |
| 584 | 584 |
| 585 // Check if the allocation fits into the remaining space. | 585 // Check if the allocation fits into the remaining space. |
| 586 // V0: potential new object start. | 586 // V0: potential new object start. |
| 587 // A0: array element type. | 587 // A0: array element type. |
| 588 // A1: array length as Smi. | 588 // A1: array length as Smi. |
| 589 // T0: points to new space object. | 589 // T0: points to new space object. |
| 590 // T2: potential next object start. | 590 // T2: potential next object start. |
| 591 // T3: array size. | 591 // T3: array size. |
| 592 __ lw(TMP1, Address(T0, Scavenger::end_offset())); | 592 __ lw(CMPRES1, Address(T0, Scavenger::end_offset())); |
| 593 __ BranchUnsignedGreaterEqual(T2, TMP1, &slow_case); | 593 __ BranchUnsignedGreaterEqual(T2, CMPRES1, &slow_case); |
| 594 | 594 |
| 595 // Successfully allocated the object(s), now update top to point to | 595 // Successfully allocated the object(s), now update top to point to |
| 596 // next object start and initialize the object. | 596 // next object start and initialize the object. |
| 597 // V0: potential new object start. | 597 // V0: potential new object start. |
| 598 // T2: potential next object start. | 598 // T2: potential next object start. |
| 599 // T0: Points to new space object. | 599 // T0: Points to new space object. |
| 600 __ sw(T2, Address(T0, Scavenger::top_offset())); | 600 __ sw(T2, Address(T0, Scavenger::top_offset())); |
| 601 __ addiu(V0, V0, Immediate(kHeapObjectTag)); | 601 __ addiu(V0, V0, Immediate(kHeapObjectTag)); |
| 602 | 602 |
| 603 // V0: new object start as a tagged pointer. | 603 // V0: new object start as a tagged pointer. |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 __ LoadImmediate(T5, heap->TopAddress()); | 946 __ LoadImmediate(T5, heap->TopAddress()); |
| 947 __ lw(V0, Address(T5, 0)); | 947 __ lw(V0, Address(T5, 0)); |
| 948 __ addu(T3, T2, V0); | 948 __ addu(T3, T2, V0); |
| 949 | 949 |
| 950 // Check if the allocation fits into the remaining space. | 950 // Check if the allocation fits into the remaining space. |
| 951 // V0: potential new object. | 951 // V0: potential new object. |
| 952 // T1: number of context variables. | 952 // T1: number of context variables. |
| 953 // T2: object size. | 953 // T2: object size. |
| 954 // T3: potential next object start. | 954 // T3: potential next object start. |
| 955 __ LoadImmediate(TMP1, heap->EndAddress()); | 955 __ LoadImmediate(TMP1, heap->EndAddress()); |
| 956 __ lw(TMP1, Address(TMP1, 0)); | 956 __ lw(CMPRES1, Address(TMP1, 0)); |
| 957 if (FLAG_use_slow_path) { | 957 if (FLAG_use_slow_path) { |
| 958 __ b(&slow_case); | 958 __ b(&slow_case); |
| 959 } else { | 959 } else { |
| 960 __ BranchUnsignedGreaterEqual(T3, TMP1, &slow_case); | 960 __ BranchUnsignedGreaterEqual(T3, CMPRES1, &slow_case); |
| 961 } | 961 } |
| 962 | 962 |
| 963 // Successfully allocated the object, now update top to point to | 963 // Successfully allocated the object, now update top to point to |
| 964 // next object start and initialize the object. | 964 // next object start and initialize the object. |
| 965 // V0: new object. | 965 // V0: new object. |
| 966 // T1: number of context variables. | 966 // T1: number of context variables. |
| 967 // T2: object size. | 967 // T2: object size. |
| 968 // T3: next object start. | 968 // T3: next object start. |
| 969 __ sw(T3, Address(T5, 0)); | 969 __ sw(T3, Address(T5, 0)); |
| 970 __ addiu(V0, V0, Immediate(kHeapObjectTag)); | 970 __ addiu(V0, V0, Immediate(kHeapObjectTag)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 // V0: new object. | 1005 // V0: new object. |
| 1006 // T1: number of context variables. | 1006 // T1: number of context variables. |
| 1007 Label loop, loop_exit; | 1007 Label loop, loop_exit; |
| 1008 __ blez(T1, &loop_exit); | 1008 __ blez(T1, &loop_exit); |
| 1009 // Setup the parent field. | 1009 // Setup the parent field. |
| 1010 __ delay_slot()->sw(T7, FieldAddress(V0, Context::parent_offset())); | 1010 __ delay_slot()->sw(T7, FieldAddress(V0, Context::parent_offset())); |
| 1011 __ AddImmediate(T3, V0, Context::variable_offset(0) - kHeapObjectTag); | 1011 __ AddImmediate(T3, V0, Context::variable_offset(0) - kHeapObjectTag); |
| 1012 __ sll(T1, T1, 2); | 1012 __ sll(T1, T1, 2); |
| 1013 __ Bind(&loop); | 1013 __ Bind(&loop); |
| 1014 __ addiu(T1, T1, Immediate(-kWordSize)); | 1014 __ addiu(T1, T1, Immediate(-kWordSize)); |
| 1015 __ addu(TMP1, T3, T1); | 1015 __ addu(T4, T3, T1); |
| 1016 __ bgtz(T1, &loop); | 1016 __ bgtz(T1, &loop); |
| 1017 __ delay_slot()->sw(T7, Address(TMP1)); | 1017 __ delay_slot()->sw(T7, Address(T4)); |
| 1018 __ Bind(&loop_exit); | 1018 __ Bind(&loop_exit); |
| 1019 | 1019 |
| 1020 // Done allocating and initializing the context. | 1020 // Done allocating and initializing the context. |
| 1021 // V0: new object. | 1021 // V0: new object. |
| 1022 __ Ret(); | 1022 __ Ret(); |
| 1023 | 1023 |
| 1024 __ Bind(&slow_case); | 1024 __ Bind(&slow_case); |
| 1025 } | 1025 } |
| 1026 // Create a stub frame as we are pushing some objects on the stack before | 1026 // Create a stub frame as we are pushing some objects on the stack before |
| 1027 // calling into the runtime. | 1027 // calling into the runtime. |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 __ delay_slot()->mov(T4, T3); | 1154 __ delay_slot()->mov(T4, T3); |
| 1155 __ AddImmediate(T3, type_args_size); | 1155 __ AddImmediate(T3, type_args_size); |
| 1156 __ Bind(&no_instantiator); | 1156 __ Bind(&no_instantiator); |
| 1157 // T4: potential new object end and, if T4 != T3, potential new | 1157 // T4: potential new object end and, if T4 != T3, potential new |
| 1158 // InstantiatedTypeArguments object start. | 1158 // InstantiatedTypeArguments object start. |
| 1159 } | 1159 } |
| 1160 // Check if the allocation fits into the remaining space. | 1160 // Check if the allocation fits into the remaining space. |
| 1161 // T2: potential new object start. | 1161 // T2: potential new object start. |
| 1162 // T3: potential next object start. | 1162 // T3: potential next object start. |
| 1163 __ LoadImmediate(TMP1, heap->EndAddress()); | 1163 __ LoadImmediate(TMP1, heap->EndAddress()); |
| 1164 __ lw(TMP1, Address(TMP1)); | 1164 __ lw(CMPRES1, Address(TMP1)); |
| 1165 if (FLAG_use_slow_path) { | 1165 if (FLAG_use_slow_path) { |
| 1166 __ b(&slow_case); | 1166 __ b(&slow_case); |
| 1167 } else { | 1167 } else { |
| 1168 __ BranchUnsignedGreaterEqual(T3, TMP1, &slow_case); | 1168 __ BranchUnsignedGreaterEqual(T3, CMPRES1, &slow_case); |
| 1169 } | 1169 } |
| 1170 | 1170 |
| 1171 // Successfully allocated the object(s), now update top to point to | 1171 // Successfully allocated the object(s), now update top to point to |
| 1172 // next object start and initialize the object. | 1172 // next object start and initialize the object. |
| 1173 __ sw(T3, Address(T5)); | 1173 __ sw(T3, Address(T5)); |
| 1174 | 1174 |
| 1175 if (is_cls_parameterized) { | 1175 if (is_cls_parameterized) { |
| 1176 // Initialize the type arguments field in the object. | 1176 // Initialize the type arguments field in the object. |
| 1177 // T2: new object start. | 1177 // T2: new object start. |
| 1178 // T4: potential new object end and, if T4 != T3, potential new | 1178 // T4: potential new object end and, if T4 != T3, potential new |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1322 __ AddImmediate(T3, T2, closure_size); | 1322 __ AddImmediate(T3, T2, closure_size); |
| 1323 if (is_implicit_instance_closure) { | 1323 if (is_implicit_instance_closure) { |
| 1324 __ mov(T4, T3); // T4: new context address. | 1324 __ mov(T4, T3); // T4: new context address. |
| 1325 __ AddImmediate(T3, context_size); | 1325 __ AddImmediate(T3, context_size); |
| 1326 } | 1326 } |
| 1327 // Check if the allocation fits into the remaining space. | 1327 // Check if the allocation fits into the remaining space. |
| 1328 // T2: potential new closure object. | 1328 // T2: potential new closure object. |
| 1329 // T3: address of top of heap. | 1329 // T3: address of top of heap. |
| 1330 // T4: potential new context object (only if is_implicit_closure). | 1330 // T4: potential new context object (only if is_implicit_closure). |
| 1331 __ LoadImmediate(TMP1, heap->EndAddress()); | 1331 __ LoadImmediate(TMP1, heap->EndAddress()); |
| 1332 __ lw(TMP1, Address(TMP1)); | 1332 __ lw(CMPRES1, Address(TMP1)); |
| 1333 if (FLAG_use_slow_path) { | 1333 if (FLAG_use_slow_path) { |
| 1334 __ b(&slow_case); | 1334 __ b(&slow_case); |
| 1335 } else { | 1335 } else { |
| 1336 __ BranchUnsignedGreaterEqual(T3, TMP1, &slow_case); | 1336 __ BranchUnsignedGreaterEqual(T3, CMPRES1, &slow_case); |
| 1337 } | 1337 } |
| 1338 | 1338 |
| 1339 // Successfully allocated the object, now update top to point to | 1339 // Successfully allocated the object, now update top to point to |
| 1340 // next object start and initialize the object. | 1340 // next object start and initialize the object. |
| 1341 __ sw(T3, Address(T5)); | 1341 __ sw(T3, Address(T5)); |
| 1342 | 1342 |
| 1343 // T2: new closure object. | 1343 // T2: new closure object. |
| 1344 // T4: new context object (only if is_implicit_closure). | 1344 // T4: new context object (only if is_implicit_closure). |
| 1345 // Set the tags. | 1345 // Set the tags. |
| 1346 uword tags = 0; | 1346 uword tags = 0; |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 // and the arguments descriptor array. | 1681 // and the arguments descriptor array. |
| 1682 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); | 1682 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); |
| 1683 __ LeaveStubFrame(); | 1683 __ LeaveStubFrame(); |
| 1684 Label call_target_function; | 1684 Label call_target_function; |
| 1685 __ BranchNotEqual(T3, reinterpret_cast<int32_t>(Object::null()), | 1685 __ BranchNotEqual(T3, reinterpret_cast<int32_t>(Object::null()), |
| 1686 &call_target_function); | 1686 &call_target_function); |
| 1687 | 1687 |
| 1688 // NoSuchMethod or closure. | 1688 // NoSuchMethod or closure. |
| 1689 // Mark IC call that it may be a closure call that does not collect | 1689 // Mark IC call that it may be a closure call that does not collect |
| 1690 // type feedback. | 1690 // type feedback. |
| 1691 __ LoadImmediate(TMP1, 1); | 1691 __ LoadImmediate(T6, 1); |
| 1692 __ Branch(&StubCode::InstanceFunctionLookupLabel()); | 1692 __ Branch(&StubCode::InstanceFunctionLookupLabel()); |
| 1693 __ delay_slot()->sb(TMP1, FieldAddress(S5, ICData::is_closure_call_offset())); | 1693 __ delay_slot()->sb(T6, FieldAddress(S5, ICData::is_closure_call_offset())); |
| 1694 | 1694 |
| 1695 __ Bind(&found); | 1695 __ Bind(&found); |
| 1696 // T0: Pointer to an IC data check group. | 1696 // T0: Pointer to an IC data check group. |
| 1697 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1697 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1698 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1698 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1699 __ lw(T3, Address(T0, target_offset)); | 1699 __ lw(T3, Address(T0, target_offset)); |
| 1700 __ lw(T4, Address(T0, count_offset)); | 1700 __ lw(T4, Address(T0, count_offset)); |
| 1701 | 1701 |
| 1702 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); | 1702 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6); |
| 1703 | 1703 |
| 1704 __ bgez(T5, &call_target_function); // No overflow. | 1704 __ bgez(T5, &call_target_function); // No overflow. |
| 1705 __ delay_slot()->sw(T4, Address(T0, count_offset)); | 1705 __ delay_slot()->sw(T4, Address(T0, count_offset)); |
| 1706 | 1706 |
| 1707 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); | 1707 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); |
| 1708 __ sw(T1, Address(T0, count_offset)); | 1708 __ sw(T1, Address(T0, count_offset)); |
| 1709 | 1709 |
| 1710 __ Bind(&call_target_function); | 1710 __ Bind(&call_target_function); |
| 1711 // T3: Target function. | 1711 // T3: Target function. |
| 1712 __ lw(T3, FieldAddress(T3, Function::code_offset())); | 1712 __ lw(T3, FieldAddress(T3, Function::code_offset())); |
| 1713 __ lw(T3, FieldAddress(T3, Code::instructions_offset())); | 1713 __ lw(T3, FieldAddress(T3, Code::instructions_offset())); |
| 1714 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); | 1714 __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag); |
| 1715 __ jr(T3); | 1715 __ jr(T3); |
| 1716 | 1716 |
| 1717 // Instance in T3, return its class-id in T3 as Smi. | 1717 // Instance in T3, return its class-id in T3 as Smi. |
| 1718 __ Bind(&get_class_id_as_smi); | 1718 __ Bind(&get_class_id_as_smi); |
| 1719 Label not_smi; | 1719 Label not_smi; |
| 1720 // Test if Smi -> load Smi class for comparison. | 1720 // Test if Smi -> load Smi class for comparison. |
| 1721 __ andi(TMP1, T3, Immediate(kSmiTagMask)); | 1721 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); |
| 1722 __ bne(TMP1, ZR, ¬_smi); | 1722 __ bne(CMPRES1, ZR, ¬_smi); |
| 1723 __ jr(RA); | 1723 __ jr(RA); |
| 1724 __ delay_slot()->addiu(T3, ZR, Immediate(Smi::RawValue(kSmiCid))); | 1724 __ delay_slot()->addiu(T3, ZR, Immediate(Smi::RawValue(kSmiCid))); |
| 1725 | 1725 |
| 1726 __ Bind(¬_smi); | 1726 __ Bind(¬_smi); |
| 1727 __ LoadClassId(T3, T3); | 1727 __ LoadClassId(T3, T3); |
| 1728 __ jr(RA); | 1728 __ jr(RA); |
| 1729 __ delay_slot()->SmiTag(T3); | 1729 __ delay_slot()->SmiTag(T3); |
| 1730 } | 1730 } |
| 1731 | 1731 |
| 1732 | 1732 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1847 | 1847 |
| 1848 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); | 1848 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); |
| 1849 __ sw(T1, Address(T0, count_offset)); | 1849 __ sw(T1, Address(T0, count_offset)); |
| 1850 | 1850 |
| 1851 __ Bind(&increment_done); | 1851 __ Bind(&increment_done); |
| 1852 | 1852 |
| 1853 Label target_is_compiled; | 1853 Label target_is_compiled; |
| 1854 // Get function and call it, if possible. | 1854 // Get function and call it, if possible. |
| 1855 __ lw(T3, Address(T0, target_offset)); | 1855 __ lw(T3, Address(T0, target_offset)); |
| 1856 __ lw(T4, FieldAddress(T3, Function::code_offset())); | 1856 __ lw(T4, FieldAddress(T3, Function::code_offset())); |
| 1857 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); | 1857 __ LoadImmediate(CMPRES1, reinterpret_cast<intptr_t>(Object::null())); |
| 1858 __ bne(T4, TMP, &target_is_compiled); | 1858 __ bne(T4, CMPRES1, &target_is_compiled); |
| 1859 | 1859 |
| 1860 __ EnterStubFrame(); | 1860 __ EnterStubFrame(); |
| 1861 // Preserve target function and IC data object. | 1861 // Preserve target function and IC data object. |
| 1862 // Two preserved registers, one argument (function) => 3 slots. | 1862 // Two preserved registers, one argument (function) => 3 slots. |
| 1863 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 1863 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 1864 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data. | 1864 __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data. |
| 1865 __ sw(T3, Address(SP, 1 * kWordSize)); // Preserve function. | 1865 __ sw(T3, Address(SP, 1 * kWordSize)); // Preserve function. |
| 1866 __ sw(T3, Address(SP, 0 * kWordSize)); // Function argument. | 1866 __ sw(T3, Address(SP, 0 * kWordSize)); // Function argument. |
| 1867 __ CallRuntime(kCompileFunctionRuntimeEntry); | 1867 __ CallRuntime(kCompileFunctionRuntimeEntry); |
| 1868 __ lw(T3, Address(SP, 1 * kWordSize)); // Restore function. | 1868 __ lw(T3, Address(SP, 1 * kWordSize)); // Restore function. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1947 // Create a stub frame as we are pushing some objects on the stack before | 1947 // Create a stub frame as we are pushing some objects on the stack before |
| 1948 // calling into the runtime. | 1948 // calling into the runtime. |
| 1949 __ TraceSimMsg("BreakpointDynamicStub"); | 1949 __ TraceSimMsg("BreakpointDynamicStub"); |
| 1950 __ EnterStubFrame(); | 1950 __ EnterStubFrame(); |
| 1951 __ Push(S5); | 1951 __ Push(S5); |
| 1952 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1952 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
| 1953 __ Pop(S5); | 1953 __ Pop(S5); |
| 1954 __ LeaveStubFrame(); | 1954 __ LeaveStubFrame(); |
| 1955 | 1955 |
| 1956 // Find out which dispatch stub to call. | 1956 // Find out which dispatch stub to call. |
| 1957 __ lw(TMP1, FieldAddress(S5, ICData::num_args_tested_offset())); | 1957 __ lw(T1, FieldAddress(S5, ICData::num_args_tested_offset())); |
| 1958 | 1958 |
| 1959 Label one_arg, two_args, three_args; | 1959 Label one_arg, two_args, three_args; |
| 1960 __ BranchEqual(TMP1, 1, &one_arg); | 1960 __ BranchEqual(T1, 1, &one_arg); |
| 1961 __ BranchEqual(TMP1, 2, &two_args); | 1961 __ BranchEqual(T1, 2, &two_args); |
| 1962 __ BranchEqual(TMP1, 3, &three_args); | 1962 __ BranchEqual(T1, 3, &three_args); |
| 1963 __ Stop("Unsupported number of arguments tested."); | 1963 __ Stop("Unsupported number of arguments tested."); |
| 1964 | 1964 |
| 1965 __ Bind(&one_arg); | 1965 __ Bind(&one_arg); |
| 1966 __ Branch(&StubCode::OneArgCheckInlineCacheLabel()); | 1966 __ Branch(&StubCode::OneArgCheckInlineCacheLabel()); |
| 1967 __ Bind(&two_args); | 1967 __ Bind(&two_args); |
| 1968 __ Branch(&StubCode::TwoArgsCheckInlineCacheLabel()); | 1968 __ Branch(&StubCode::TwoArgsCheckInlineCacheLabel()); |
| 1969 __ Bind(&three_args); | 1969 __ Bind(&three_args); |
| 1970 __ Branch(&StubCode::ThreeArgsCheckInlineCacheLabel()); | 1970 __ Branch(&StubCode::ThreeArgsCheckInlineCacheLabel()); |
| 1971 __ break_(0); | 1971 __ break_(0); |
| 1972 } | 1972 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2114 // T0: ICData. | 2114 // T0: ICData. |
| 2115 // V0: result. | 2115 // V0: result. |
| 2116 // TODO(srdjan): Move to VM stubs once Boolean objects become VM objects. | 2116 // TODO(srdjan): Move to VM stubs once Boolean objects become VM objects. |
| 2117 void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) { | 2117 void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) { |
| 2118 __ TraceSimMsg("EqualityWithNullArgStub"); | 2118 __ TraceSimMsg("EqualityWithNullArgStub"); |
| 2119 __ Comment("EqualityWithNullArgStub"); | 2119 __ Comment("EqualityWithNullArgStub"); |
| 2120 __ EnterStubFrame(); | 2120 __ EnterStubFrame(); |
| 2121 static const intptr_t kNumArgsTested = 2; | 2121 static const intptr_t kNumArgsTested = 2; |
| 2122 #if defined(DEBUG) | 2122 #if defined(DEBUG) |
| 2123 { Label ok; | 2123 { Label ok; |
| 2124 __ lw(TMP1, FieldAddress(T0, ICData::num_args_tested_offset())); | 2124 __ lw(CMPRES1, FieldAddress(T0, ICData::num_args_tested_offset())); |
| 2125 __ BranchEqual(TMP1, kNumArgsTested, &ok); | 2125 __ BranchEqual(CMPRES1, kNumArgsTested, &ok); |
| 2126 __ Stop("Incorrect ICData for equality"); | 2126 __ Stop("Incorrect ICData for equality"); |
| 2127 __ Bind(&ok); | 2127 __ Bind(&ok); |
| 2128 } | 2128 } |
| 2129 #endif // DEBUG | 2129 #endif // DEBUG |
| 2130 // Check IC data, update if needed. | 2130 // Check IC data, update if needed. |
| 2131 // T0: IC data object (preserved). | 2131 // T0: IC data object (preserved). |
| 2132 __ lw(T6, FieldAddress(T0, ICData::ic_data_offset())); | 2132 __ lw(T6, FieldAddress(T0, ICData::ic_data_offset())); |
| 2133 // T6: ic_data_array with check entries: classes and target functions. | 2133 // T6: ic_data_array with check entries: classes and target functions. |
| 2134 __ AddImmediate(T6, Array::data_offset() - kHeapObjectTag); | 2134 __ AddImmediate(T6, Array::data_offset() - kHeapObjectTag); |
| 2135 // T6: points directly to the first ic data array element. | 2135 // T6: points directly to the first ic data array element. |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2312 __ CallRuntime(kBigintCompareRuntimeEntry); | 2312 __ CallRuntime(kBigintCompareRuntimeEntry); |
| 2313 __ TraceSimMsg("IdenticalWithNumberCheckStub return"); | 2313 __ TraceSimMsg("IdenticalWithNumberCheckStub return"); |
| 2314 // Result in V0, 0 means equal. | 2314 // Result in V0, 0 means equal. |
| 2315 __ LeaveStubFrame(); | 2315 __ LeaveStubFrame(); |
| 2316 __ b(&done); | 2316 __ b(&done); |
| 2317 __ delay_slot()->mov(CMPRES, V0); | 2317 __ delay_slot()->mov(CMPRES, V0); |
| 2318 | 2318 |
| 2319 __ Bind(&reference_compare); | 2319 __ Bind(&reference_compare); |
| 2320 __ subu(CMPRES, left, right); | 2320 __ subu(CMPRES, left, right); |
| 2321 __ Bind(&done); | 2321 __ Bind(&done); |
| 2322 // A branch or test after this comparison will check CMPRES == TMP1. | 2322 // A branch or test after this comparison will check CMPRES1 == CMPRES2. |
| 2323 __ mov(TMP1, ZR); | 2323 __ mov(CMPRES2, ZR); |
| 2324 } | 2324 } |
| 2325 | 2325 |
| 2326 | 2326 |
| 2327 // Called only from unoptimized code. All relevant registers have been saved. | 2327 // Called only from unoptimized code. All relevant registers have been saved. |
| 2328 // RA: return address. | 2328 // RA: return address. |
| 2329 // SP + 4: left operand. | 2329 // SP + 4: left operand. |
| 2330 // SP + 0: right operand. | 2330 // SP + 0: right operand. |
| 2331 // Returns: CMPRES is zero if equal, non-zero otherwise. | 2331 // Returns: CMPRES is zero if equal, non-zero otherwise. |
| 2332 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2332 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 2333 Assembler* assembler) { | 2333 Assembler* assembler) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2380 __ lw(left, Address(SP, 1 * kWordSize)); | 2380 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2381 __ lw(temp2, Address(SP, 2 * kWordSize)); | 2381 __ lw(temp2, Address(SP, 2 * kWordSize)); |
| 2382 __ lw(temp1, Address(SP, 3 * kWordSize)); | 2382 __ lw(temp1, Address(SP, 3 * kWordSize)); |
| 2383 __ Ret(); | 2383 __ Ret(); |
| 2384 __ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); | 2384 __ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
| 2385 } | 2385 } |
| 2386 | 2386 |
| 2387 } // namespace dart | 2387 } // namespace dart |
| 2388 | 2388 |
| 2389 #endif // defined TARGET_ARCH_MIPS | 2389 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |