| 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" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/heap.h" | 13 #include "vm/heap.h" |
| 14 #include "vm/instructions.h" | 14 #include "vm/instructions.h" |
| 15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
| 16 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
| 17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 18 #include "vm/tags.h" | 18 #include "vm/tags.h" |
| 19 | 19 |
| 20 #define __ assembler-> | 20 #define __ assembler-> |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); | 24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); |
| 25 DEFINE_FLAG(bool, use_slow_path, false, | 25 DEFINE_FLAG(bool, use_slow_path, false, |
| 26 "Set to true for debugging & verifying the slow paths."); | 26 "Set to true for debugging & verifying the slow paths."); |
| 27 DECLARE_FLAG(bool, trace_optimized_ic_calls); | 27 DECLARE_FLAG(bool, trace_optimized_ic_calls); |
| 28 DECLARE_FLAG(int, optimization_counter_threshold); |
| 28 | 29 |
| 29 // Input parameters: | 30 // Input parameters: |
| 30 // RA : return address. | 31 // RA : return address. |
| 31 // SP : address of last argument in argument array. | 32 // SP : address of last argument in argument array. |
| 32 // SP + 4*S4 - 4 : address of first argument in argument array. | 33 // SP + 4*S4 - 4 : address of first argument in argument array. |
| 33 // SP + 4*S4 : address of return value. | 34 // SP + 4*S4 : address of return value. |
| 34 // S5 : address of the runtime function to call. | 35 // S5 : address of the runtime function to call. |
| 35 // S4 : number of arguments to the call. | 36 // S4 : number of arguments to the call. |
| 36 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
| 37 const intptr_t isolate_offset = NativeArguments::isolate_offset(); | 38 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
| (...skipping 1292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1330 } | 1331 } |
| 1331 __ lw(T7, FieldAddress(func_reg, Function::usage_counter_offset())); | 1332 __ lw(T7, FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1332 __ addiu(T7, T7, Immediate(1)); | 1333 __ addiu(T7, T7, Immediate(1)); |
| 1333 __ sw(T7, FieldAddress(func_reg, Function::usage_counter_offset())); | 1334 __ sw(T7, FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1334 } | 1335 } |
| 1335 | 1336 |
| 1336 | 1337 |
| 1337 // Loads function into 'temp_reg'. | 1338 // Loads function into 'temp_reg'. |
| 1338 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, | 1339 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
| 1339 Register temp_reg) { | 1340 Register temp_reg) { |
| 1340 __ Comment("UsageCounterIncrement"); | 1341 if (FLAG_optimization_counter_threshold != -1) { |
| 1341 Register ic_reg = S5; | 1342 __ Comment("UsageCounterIncrement"); |
| 1342 Register func_reg = temp_reg; | 1343 Register ic_reg = S5; |
| 1343 ASSERT(temp_reg == T0); | 1344 Register func_reg = temp_reg; |
| 1344 __ Comment("Increment function counter"); | 1345 ASSERT(temp_reg == T0); |
| 1345 __ lw(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); | 1346 __ Comment("Increment function counter"); |
| 1346 __ lw(T1, FieldAddress(func_reg, Function::usage_counter_offset())); | 1347 __ lw(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); |
| 1347 __ addiu(T1, T1, Immediate(1)); | 1348 __ lw(T1, FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1348 __ sw(T1, FieldAddress(func_reg, Function::usage_counter_offset())); | 1349 __ addiu(T1, T1, Immediate(1)); |
| 1350 __ sw(T1, FieldAddress(func_reg, Function::usage_counter_offset())); |
| 1351 } |
| 1349 } | 1352 } |
| 1350 | 1353 |
| 1351 | 1354 |
| 1352 // Note: S5 must be preserved. | 1355 // Note: S5 must be preserved. |
| 1353 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1356 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
| 1354 // must have been primed with a Smi/Smi check that will be used for counting | 1357 // must have been primed with a Smi/Smi check that will be used for counting |
| 1355 // the invocations. | 1358 // the invocations. |
| 1356 static void EmitFastSmiOp(Assembler* assembler, | 1359 static void EmitFastSmiOp(Assembler* assembler, |
| 1357 Token::Kind kind, | 1360 Token::Kind kind, |
| 1358 intptr_t num_args, | 1361 intptr_t num_args, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1397 Label error, ok; | 1400 Label error, ok; |
| 1398 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid)); | 1401 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid)); |
| 1399 __ lw(T4, Address(T0)); | 1402 __ lw(T4, Address(T0)); |
| 1400 __ BranchNotEqual(T4, Immediate(imm_smi_cid), &error); | 1403 __ BranchNotEqual(T4, Immediate(imm_smi_cid), &error); |
| 1401 __ lw(T4, Address(T0, kWordSize)); | 1404 __ lw(T4, Address(T0, kWordSize)); |
| 1402 __ BranchEqual(T4, Immediate(imm_smi_cid), &ok); | 1405 __ BranchEqual(T4, Immediate(imm_smi_cid), &ok); |
| 1403 __ Bind(&error); | 1406 __ Bind(&error); |
| 1404 __ Stop("Incorrect IC data"); | 1407 __ Stop("Incorrect IC data"); |
| 1405 __ Bind(&ok); | 1408 __ Bind(&ok); |
| 1406 #endif | 1409 #endif |
| 1407 // Update counter. | 1410 if (FLAG_optimization_counter_threshold != -1) { |
| 1408 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1411 // Update counter. |
| 1409 __ lw(T4, Address(T0, count_offset)); | 1412 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1410 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); | 1413 __ lw(T4, Address(T0, count_offset)); |
| 1411 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. | 1414 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); |
| 1412 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); | 1415 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. |
| 1413 __ movz(T4, T7, CMPRES1); | 1416 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); |
| 1414 __ sw(T4, Address(T0, count_offset)); | 1417 __ movz(T4, T7, CMPRES1); |
| 1418 __ sw(T4, Address(T0, count_offset)); |
| 1419 } |
| 1415 | 1420 |
| 1416 __ Ret(); | 1421 __ Ret(); |
| 1417 } | 1422 } |
| 1418 | 1423 |
| 1419 | 1424 |
| 1420 // Generate inline cache check for 'num_args'. | 1425 // Generate inline cache check for 'num_args'. |
| 1421 // RA: return address | 1426 // RA: return address |
| 1422 // S5: Inline cache data object. | 1427 // S5: Inline cache data object. |
| 1423 // Control flow: | 1428 // Control flow: |
| 1424 // - If receiver is null -> jump to IC miss. | 1429 // - If receiver is null -> jump to IC miss. |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1586 Label call_target_function; | 1591 Label call_target_function; |
| 1587 __ b(&call_target_function); | 1592 __ b(&call_target_function); |
| 1588 | 1593 |
| 1589 __ Bind(&found); | 1594 __ Bind(&found); |
| 1590 __ Comment("Update caller's counter"); | 1595 __ Comment("Update caller's counter"); |
| 1591 // T0: Pointer to an IC data check group. | 1596 // T0: Pointer to an IC data check group. |
| 1592 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1597 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1593 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1598 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1594 __ lw(T3, Address(T0, target_offset)); | 1599 __ lw(T3, Address(T0, target_offset)); |
| 1595 | 1600 |
| 1596 // Update counter. | 1601 if (FLAG_optimization_counter_threshold != -1) { |
| 1597 __ lw(T4, Address(T0, count_offset)); | 1602 // Update counter. |
| 1598 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); | 1603 __ lw(T4, Address(T0, count_offset)); |
| 1599 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. | 1604 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); |
| 1600 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); | 1605 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. |
| 1601 __ movz(T4, T7, CMPRES1); | 1606 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); |
| 1602 __ sw(T4, Address(T0, count_offset)); | 1607 __ movz(T4, T7, CMPRES1); |
| 1608 __ sw(T4, Address(T0, count_offset)); |
| 1609 } |
| 1603 | 1610 |
| 1604 __ Comment("Call target"); | 1611 __ Comment("Call target"); |
| 1605 __ Bind(&call_target_function); | 1612 __ Bind(&call_target_function); |
| 1606 // T0 <- T3: Target function. | 1613 // T0 <- T3: Target function. |
| 1607 __ mov(T0, T3); | 1614 __ mov(T0, T3); |
| 1608 Label is_compiled; | 1615 Label is_compiled; |
| 1609 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); | 1616 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); |
| 1610 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); | 1617 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); |
| 1611 if (range_collection_mode == kCollectRanges) { | 1618 if (range_collection_mode == kCollectRanges) { |
| 1612 const intptr_t frame_size = num_args + 2; | 1619 const intptr_t frame_size = num_args + 2; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1782 __ Bind(&done_stepping); | 1789 __ Bind(&done_stepping); |
| 1783 | 1790 |
| 1784 // S5: IC data object (preserved). | 1791 // S5: IC data object (preserved). |
| 1785 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1792 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
| 1786 // T0: ic_data_array with entries: target functions and count. | 1793 // T0: ic_data_array with entries: target functions and count. |
| 1787 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1794 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
| 1788 // T0: points directly to the first ic data array element. | 1795 // T0: points directly to the first ic data array element. |
| 1789 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1796 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1790 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1797 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1791 | 1798 |
| 1792 // Increment count for this call. | 1799 if (FLAG_optimization_counter_threshold != -1) { |
| 1793 __ lw(T4, Address(T0, count_offset)); | 1800 // Increment count for this call. |
| 1794 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); | 1801 __ lw(T4, Address(T0, count_offset)); |
| 1795 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. | 1802 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); |
| 1796 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); | 1803 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. |
| 1797 __ movz(T4, T7, CMPRES1); | 1804 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); |
| 1798 __ sw(T4, Address(T0, count_offset)); | 1805 __ movz(T4, T7, CMPRES1); |
| 1806 __ sw(T4, Address(T0, count_offset)); |
| 1807 } |
| 1799 | 1808 |
| 1800 // Load arguments descriptor into S4. | 1809 // Load arguments descriptor into S4. |
| 1801 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1810 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
| 1802 | 1811 |
| 1803 // Get function and call it, if possible. | 1812 // Get function and call it, if possible. |
| 1804 __ lw(T0, Address(T0, target_offset)); | 1813 __ lw(T0, Address(T0, target_offset)); |
| 1805 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); | 1814 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); |
| 1806 | 1815 |
| 1807 // T4: target instructions. | 1816 // T4: target instructions. |
| 1808 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); | 1817 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2251 const Register right = T0; | 2260 const Register right = T0; |
| 2252 __ lw(left, Address(SP, 1 * kWordSize)); | 2261 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2253 __ lw(right, Address(SP, 0 * kWordSize)); | 2262 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2254 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2263 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2255 __ Ret(); | 2264 __ Ret(); |
| 2256 } | 2265 } |
| 2257 | 2266 |
| 2258 } // namespace dart | 2267 } // namespace dart |
| 2259 | 2268 |
| 2260 #endif // defined TARGET_ARCH_MIPS | 2269 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |