| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 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 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 // R2: array length as Smi. | 641 // R2: array length as Smi. |
| 642 // R1: array element type (either NULL or an instantiated type). | 642 // R1: array element type (either NULL or an instantiated type). |
| 643 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved. | 643 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved. |
| 644 // The newly allocated object is returned in R0. | 644 // The newly allocated object is returned in R0. |
| 645 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 645 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 646 Label slow_case; | 646 Label slow_case; |
| 647 // Compute the size to be allocated, it is based on the array length | 647 // Compute the size to be allocated, it is based on the array length |
| 648 // and is computed as: | 648 // and is computed as: |
| 649 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 649 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 650 // Assert that length is a Smi. | 650 // Assert that length is a Smi. |
| 651 __ tsti(R2, kSmiTagMask); | 651 __ tsti(R2, Immediate(kSmiTagMask)); |
| 652 if (FLAG_use_slow_path) { | 652 if (FLAG_use_slow_path) { |
| 653 __ b(&slow_case); | 653 __ b(&slow_case); |
| 654 } else { | 654 } else { |
| 655 __ b(&slow_case, NE); | 655 __ b(&slow_case, NE); |
| 656 } | 656 } |
| 657 __ cmp(R2, Operand(0)); | 657 __ cmp(R2, Operand(0)); |
| 658 __ b(&slow_case, LT); | 658 __ b(&slow_case, LT); |
| 659 | 659 |
| 660 Isolate* isolate = Isolate::Current(); | 660 Isolate* isolate = Isolate::Current(); |
| 661 Heap* heap = isolate->heap(); | 661 Heap* heap = isolate->heap(); |
| 662 const intptr_t cid = kArrayCid; | 662 const intptr_t cid = kArrayCid; |
| 663 Heap::Space space = heap->SpaceForAllocation(cid); | 663 Heap::Space space = heap->SpaceForAllocation(cid); |
| 664 const uword top_address = heap->TopAddress(space); | 664 const uword top_address = heap->TopAddress(space); |
| 665 __ LoadImmediate(R8, top_address, kNoPP); | 665 __ LoadImmediate(R8, top_address, kNoPP); |
| 666 const uword end_address = heap->EndAddress(space); | 666 const uword end_address = heap->EndAddress(space); |
| 667 ASSERT(top_address < end_address); | 667 ASSERT(top_address < end_address); |
| 668 const uword top_offset = 0; | 668 const uword top_offset = 0; |
| 669 const uword end_offset = end_address - top_address; | 669 const uword end_offset = end_address - top_address; |
| 670 | 670 |
| 671 // Calculate and align allocation size. | 671 // Calculate and align allocation size. |
| 672 // Load new object start and calculate next object start. | 672 // Load new object start and calculate next object start. |
| 673 // R1: array element type. | 673 // R1: array element type. |
| 674 // R2: array length as Smi. | 674 // R2: array length as Smi. |
| 675 // R8: points to new space object. | 675 // R8: points to new space object. |
| 676 __ LoadFromOffset(R0, R8, top_offset, kNoPP); | 676 __ LoadFromOffset(R0, R8, top_offset, kNoPP); |
| 677 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 677 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 678 __ LoadImmediate(R3, fixed_size, kNoPP); | 678 __ LoadImmediate(R3, fixed_size, kNoPP); |
| 679 __ add(R3, R3, Operand(R2, LSL, 2)); // R2 is Smi. | 679 __ add(R3, R3, Operand(R2, LSL, 2)); // R2 is Smi. |
| 680 ASSERT(kSmiTagShift == 1); | 680 ASSERT(kSmiTagShift == 1); |
| 681 __ andi(R3, R3, ~(kObjectAlignment - 1)); | 681 __ andi(R3, R3, Immediate(~(kObjectAlignment - 1))); |
| 682 __ adds(R7, R3, Operand(R0)); | 682 __ adds(R7, R3, Operand(R0)); |
| 683 __ b(&slow_case, VS); | 683 __ b(&slow_case, VS); |
| 684 | 684 |
| 685 // Check if the allocation fits into the remaining space. | 685 // Check if the allocation fits into the remaining space. |
| 686 // R0: potential new object start. | 686 // R0: potential new object start. |
| 687 // R1: array element type. | 687 // R1: array element type. |
| 688 // R2: array length as Smi. | 688 // R2: array length as Smi. |
| 689 // R3: array size. | 689 // R3: array size. |
| 690 // R7: potential next object start. | 690 // R7: potential next object start. |
| 691 // R8: points to new space object. | 691 // R8: points to new space object. |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 961 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 962 if (FLAG_inline_alloc) { | 962 if (FLAG_inline_alloc) { |
| 963 Label slow_case; | 963 Label slow_case; |
| 964 Heap* heap = Isolate::Current()->heap(); | 964 Heap* heap = Isolate::Current()->heap(); |
| 965 // First compute the rounded instance size. | 965 // First compute the rounded instance size. |
| 966 // R1: number of context variables. | 966 // R1: number of context variables. |
| 967 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; | 967 intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; |
| 968 __ LoadImmediate(R2, fixed_size, kNoPP); | 968 __ LoadImmediate(R2, fixed_size, kNoPP); |
| 969 __ add(R2, R2, Operand(R1, LSL, 3)); | 969 __ add(R2, R2, Operand(R1, LSL, 3)); |
| 970 ASSERT(kSmiTagShift == 1); | 970 ASSERT(kSmiTagShift == 1); |
| 971 __ andi(R2, R2, ~(kObjectAlignment - 1)); | 971 __ andi(R2, R2, Immediate(~(kObjectAlignment - 1))); |
| 972 | 972 |
| 973 // Now allocate the object. | 973 // Now allocate the object. |
| 974 // R1: number of context variables. | 974 // R1: number of context variables. |
| 975 // R2: object size. | 975 // R2: object size. |
| 976 const intptr_t cid = kContextCid; | 976 const intptr_t cid = kContextCid; |
| 977 Heap::Space space = heap->SpaceForAllocation(cid); | 977 Heap::Space space = heap->SpaceForAllocation(cid); |
| 978 __ LoadImmediate(R5, heap->TopAddress(space), kNoPP); | 978 __ LoadImmediate(R5, heap->TopAddress(space), kNoPP); |
| 979 __ ldr(R0, Address(R5)); | 979 __ ldr(R0, Address(R5)); |
| 980 __ add(R3, R2, Operand(R0)); | 980 __ add(R3, R2, Operand(R0)); |
| 981 // Check if the allocation fits into the remaining space. | 981 // Check if the allocation fits into the remaining space. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1079 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); | 1079 DECLARE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate); |
| 1080 | 1080 |
| 1081 // Helper stub to implement Assembler::StoreIntoObject. | 1081 // Helper stub to implement Assembler::StoreIntoObject. |
| 1082 // Input parameters: | 1082 // Input parameters: |
| 1083 // R0: Address being stored | 1083 // R0: Address being stored |
| 1084 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { | 1084 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { |
| 1085 Label add_to_buffer; | 1085 Label add_to_buffer; |
| 1086 // Check whether this object has already been remembered. Skip adding to the | 1086 // Check whether this object has already been remembered. Skip adding to the |
| 1087 // store buffer if the object is in the store buffer already. | 1087 // store buffer if the object is in the store buffer already. |
| 1088 __ LoadFieldFromOffset(TMP, R0, Object::tags_offset(), kNoPP); | 1088 __ LoadFieldFromOffset(TMP, R0, Object::tags_offset(), kNoPP); |
| 1089 __ tsti(TMP, 1 << RawObject::kRememberedBit); | 1089 __ tsti(TMP, Immediate(1 << RawObject::kRememberedBit)); |
| 1090 __ b(&add_to_buffer, EQ); | 1090 __ b(&add_to_buffer, EQ); |
| 1091 __ ret(); | 1091 __ ret(); |
| 1092 | 1092 |
| 1093 __ Bind(&add_to_buffer); | 1093 __ Bind(&add_to_buffer); |
| 1094 // Save values being destroyed. | 1094 // Save values being destroyed. |
| 1095 __ Push(R1); | 1095 __ Push(R1); |
| 1096 __ Push(R2); | 1096 __ Push(R2); |
| 1097 __ Push(R3); | 1097 __ Push(R3); |
| 1098 | 1098 |
| 1099 __ orri(R2, TMP, 1 << RawObject::kRememberedBit); | 1099 __ orri(R2, TMP, Immediate(1 << RawObject::kRememberedBit)); |
| 1100 __ StoreFieldToOffset(R2, R0, Object::tags_offset(), kNoPP); | 1100 __ StoreFieldToOffset(R2, R0, Object::tags_offset(), kNoPP); |
| 1101 | 1101 |
| 1102 // Load the isolate. | 1102 // Load the isolate. |
| 1103 // Spilled: R1, R2, R3. | 1103 // Spilled: R1, R2, R3. |
| 1104 // R0: address being stored. | 1104 // R0: address being stored. |
| 1105 __ LoadImmediate(R1, Isolate::CurrentAddress(), kNoPP); | 1105 __ LoadImmediate(R1, Isolate::CurrentAddress(), kNoPP); |
| 1106 | 1106 |
| 1107 // Load the StoreBuffer block out of the isolate. Then load top_ out of the | 1107 // Load the StoreBuffer block out of the isolate. Then load top_ out of the |
| 1108 // StoreBufferBlock and add the address to the pointers_. | 1108 // StoreBufferBlock and add the address to the pointers_. |
| 1109 // R1: isolate. | 1109 // R1: isolate. |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 Token::Kind kind, | 1355 Token::Kind kind, |
| 1356 intptr_t num_args, | 1356 intptr_t num_args, |
| 1357 Label* not_smi_or_overflow) { | 1357 Label* not_smi_or_overflow) { |
| 1358 if (FLAG_throw_on_javascript_int_overflow) { | 1358 if (FLAG_throw_on_javascript_int_overflow) { |
| 1359 // The overflow check is more complex than implemented below. | 1359 // The overflow check is more complex than implemented below. |
| 1360 return; | 1360 return; |
| 1361 } | 1361 } |
| 1362 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Right. | 1362 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Right. |
| 1363 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Left. | 1363 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Left. |
| 1364 __ orr(TMP, R0, Operand(R1)); | 1364 __ orr(TMP, R0, Operand(R1)); |
| 1365 __ tsti(TMP, kSmiTagMask); | 1365 __ tsti(TMP, Immediate(kSmiTagMask)); |
| 1366 __ b(not_smi_or_overflow, NE); | 1366 __ b(not_smi_or_overflow, NE); |
| 1367 switch (kind) { | 1367 switch (kind) { |
| 1368 case Token::kADD: { | 1368 case Token::kADD: { |
| 1369 __ adds(R0, R1, Operand(R0)); // Adds. | 1369 __ adds(R0, R1, Operand(R0)); // Adds. |
| 1370 __ b(not_smi_or_overflow, VS); // Branch if overflow. | 1370 __ b(not_smi_or_overflow, VS); // Branch if overflow. |
| 1371 break; | 1371 break; |
| 1372 } | 1372 } |
| 1373 case Token::kSUB: { | 1373 case Token::kSUB: { |
| 1374 __ subs(R0, R1, Operand(R0)); // Subtract. | 1374 __ subs(R0, R1, Operand(R0)); // Subtract. |
| 1375 __ b(not_smi_or_overflow, VS); // Branch if overflow. | 1375 __ b(not_smi_or_overflow, VS); // Branch if overflow. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1432 const RuntimeEntry& handle_ic_miss, | 1432 const RuntimeEntry& handle_ic_miss, |
| 1433 Token::Kind kind) { | 1433 Token::Kind kind) { |
| 1434 ASSERT(num_args > 0); | 1434 ASSERT(num_args > 0); |
| 1435 #if defined(DEBUG) | 1435 #if defined(DEBUG) |
| 1436 { Label ok; | 1436 { Label ok; |
| 1437 // Check that the IC data array has NumArgsTested() == num_args. | 1437 // Check that the IC data array has NumArgsTested() == num_args. |
| 1438 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1438 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
| 1439 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, | 1439 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, |
| 1440 kNoPP, kUnsignedWord); | 1440 kNoPP, kUnsignedWord); |
| 1441 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1441 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1442 __ andi(R6, R6, ICData::NumArgsTestedMask()); | 1442 __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask())); |
| 1443 __ CompareImmediate(R6, num_args, kNoPP); | 1443 __ CompareImmediate(R6, num_args, kNoPP); |
| 1444 __ b(&ok, EQ); | 1444 __ b(&ok, EQ); |
| 1445 __ Stop("Incorrect stub for IC data"); | 1445 __ Stop("Incorrect stub for IC data"); |
| 1446 __ Bind(&ok); | 1446 __ Bind(&ok); |
| 1447 } | 1447 } |
| 1448 #endif // DEBUG | 1448 #endif // DEBUG |
| 1449 | 1449 |
| 1450 // Check single stepping. | 1450 // Check single stepping. |
| 1451 Label stepping, done_stepping; | 1451 Label stepping, done_stepping; |
| 1452 __ LoadImmediate(R6, Isolate::CurrentAddress(), kNoPP); | 1452 __ LoadImmediate(R6, Isolate::CurrentAddress(), kNoPP); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1664 | 1664 |
| 1665 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1665 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1666 GenerateUsageCounterIncrement(assembler, R6); | 1666 GenerateUsageCounterIncrement(assembler, R6); |
| 1667 #if defined(DEBUG) | 1667 #if defined(DEBUG) |
| 1668 { Label ok; | 1668 { Label ok; |
| 1669 // Check that the IC data array has NumArgsTested() == 0. | 1669 // Check that the IC data array has NumArgsTested() == 0. |
| 1670 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1670 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
| 1671 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, | 1671 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, |
| 1672 kNoPP, kUnsignedWord); | 1672 kNoPP, kUnsignedWord); |
| 1673 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1673 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1674 __ andi(R6, R6, ICData::NumArgsTestedMask()); | 1674 __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask())); |
| 1675 __ CompareImmediate(R6, 0, kNoPP); | 1675 __ CompareImmediate(R6, 0, kNoPP); |
| 1676 __ b(&ok, EQ); | 1676 __ b(&ok, EQ); |
| 1677 __ Stop("Incorrect IC data for unoptimized static call"); | 1677 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1678 __ Bind(&ok); | 1678 __ Bind(&ok); |
| 1679 } | 1679 } |
| 1680 #endif // DEBUG | 1680 #endif // DEBUG |
| 1681 | 1681 |
| 1682 // Check single stepping. | 1682 // Check single stepping. |
| 1683 Label stepping, done_stepping; | 1683 Label stepping, done_stepping; |
| 1684 __ LoadImmediate(R6, Isolate::CurrentAddress(), kNoPP); | 1684 __ LoadImmediate(R6, Isolate::CurrentAddress(), kNoPP); |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1996 // Return Zero condition flag set if equal. | 1996 // Return Zero condition flag set if equal. |
| 1997 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint | 1997 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint |
| 1998 // cannot contain a value that fits in Mint or Smi. | 1998 // cannot contain a value that fits in Mint or Smi. |
| 1999 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler, | 1999 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler, |
| 2000 const Register left, | 2000 const Register left, |
| 2001 const Register right, | 2001 const Register right, |
| 2002 const Register unused1, | 2002 const Register unused1, |
| 2003 const Register unused2) { | 2003 const Register unused2) { |
| 2004 Label reference_compare, done, check_mint, check_bigint; | 2004 Label reference_compare, done, check_mint, check_bigint; |
| 2005 // If any of the arguments is Smi do reference compare. | 2005 // If any of the arguments is Smi do reference compare. |
| 2006 __ tsti(left, kSmiTagMask); | 2006 __ tsti(left, Immediate(kSmiTagMask)); |
| 2007 __ b(&reference_compare, EQ); | 2007 __ b(&reference_compare, EQ); |
| 2008 __ tsti(right, kSmiTagMask); | 2008 __ tsti(right, Immediate(kSmiTagMask)); |
| 2009 __ b(&reference_compare, EQ); | 2009 __ b(&reference_compare, EQ); |
| 2010 | 2010 |
| 2011 // Value compare for two doubles. | 2011 // Value compare for two doubles. |
| 2012 __ CompareClassId(left, kDoubleCid, kNoPP); | 2012 __ CompareClassId(left, kDoubleCid, kNoPP); |
| 2013 __ b(&check_mint, NE); | 2013 __ b(&check_mint, NE); |
| 2014 __ CompareClassId(right, kDoubleCid, kNoPP); | 2014 __ CompareClassId(right, kDoubleCid, kNoPP); |
| 2015 __ b(&done, NE); | 2015 __ b(&done, NE); |
| 2016 | 2016 |
| 2017 // Double values bitwise compare. | 2017 // Double values bitwise compare. |
| 2018 __ LoadFieldFromOffset(left, left, Double::value_offset(), kNoPP); | 2018 __ LoadFieldFromOffset(left, left, Double::value_offset(), kNoPP); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2093 const Register right = R0; | 2093 const Register right = R0; |
| 2094 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); | 2094 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); |
| 2095 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); | 2095 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); |
| 2096 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2096 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2097 __ ret(); | 2097 __ ret(); |
| 2098 } | 2098 } |
| 2099 | 2099 |
| 2100 } // namespace dart | 2100 } // namespace dart |
| 2101 | 2101 |
| 2102 #endif // defined TARGET_ARCH_ARM64 | 2102 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |