| 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" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 // Store the type argument field in the growable array object. | 190 // Store the type argument field in the growable array object. |
| 191 __ ldr(R1, Address(SP, kTypeArgumentsOffset)); // Type argument. | 191 __ ldr(R1, Address(SP, kTypeArgumentsOffset)); // Type argument. |
| 192 __ StoreIntoObjectNoBarrier( | 192 __ StoreIntoObjectNoBarrier( |
| 193 R0, | 193 R0, |
| 194 FieldAddress(R0, GrowableObjectArray::type_arguments_offset()), | 194 FieldAddress(R0, GrowableObjectArray::type_arguments_offset()), |
| 195 R1); | 195 R1); |
| 196 | 196 |
| 197 // Set the length field in the growable array object to 0. | 197 // Set the length field in the growable array object to 0. |
| 198 __ LoadImmediate(R1, 0, kNoPP); | 198 __ LoadImmediate(R1, 0, kNoPP); |
| 199 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); | 199 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); |
| 200 __ UpdateAllocationStats(kGrowableObjectArrayCid, R1, kNoPP); | 200 __ UpdateAllocationStats(kGrowableObjectArrayCid, kNoPP); |
| 201 __ ret(); // Returns the newly allocated object in R0. | 201 __ ret(); // Returns the newly allocated object in R0. |
| 202 | 202 |
| 203 __ Bind(&fall_through); | 203 __ Bind(&fall_through); |
| 204 } | 204 } |
| 205 | 205 |
| 206 | 206 |
| 207 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { | 207 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { |
| 208 __ ldr(R0, Address(SP, 0 * kWordSize)); | 208 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| 209 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset())); | 209 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset())); |
| 210 __ ret(); | 210 __ ret(); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 __ LoadImmediate(R3, heap->EndAddress(), kNoPP); \ | 402 __ LoadImmediate(R3, heap->EndAddress(), kNoPP); \ |
| 403 __ ldr(R3, Address(R3, 0)); \ | 403 __ ldr(R3, Address(R3, 0)); \ |
| 404 __ cmp(R1, Operand(R3)); \ | 404 __ cmp(R1, Operand(R3)); \ |
| 405 __ b(&fall_through, CS); \ | 405 __ b(&fall_through, CS); \ |
| 406 \ | 406 \ |
| 407 /* Successfully allocated the object(s), now update top to point to */ \ | 407 /* Successfully allocated the object(s), now update top to point to */ \ |
| 408 /* next object start and initialize the object. */ \ | 408 /* next object start and initialize the object. */ \ |
| 409 __ LoadImmediate(R3, heap->TopAddress(), kNoPP); \ | 409 __ LoadImmediate(R3, heap->TopAddress(), kNoPP); \ |
| 410 __ str(R1, Address(R3, 0)); \ | 410 __ str(R1, Address(R3, 0)); \ |
| 411 __ AddImmediate(R0, R0, kHeapObjectTag, kNoPP); \ | 411 __ AddImmediate(R0, R0, kHeapObjectTag, kNoPP); \ |
| 412 __ UpdateAllocationStatsWithSize(cid, R2, R4, kNoPP); \ | 412 __ UpdateAllocationStatsWithSize(cid, R2, kNoPP); \ |
| 413 /* Initialize the tags. */ \ | 413 /* Initialize the tags. */ \ |
| 414 /* R0: new object start as a tagged pointer. */ \ | 414 /* R0: new object start as a tagged pointer. */ \ |
| 415 /* R1: new object end address. */ \ | 415 /* R1: new object end address. */ \ |
| 416 /* R2: allocation size. */ \ | 416 /* R2: allocation size. */ \ |
| 417 { \ | 417 { \ |
| 418 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP); \ | 418 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag, kNoPP); \ |
| 419 __ Lsl(R2, R2, RawObject::kSizeTagPos - kObjectAlignmentLog2); \ | 419 __ Lsl(R2, R2, RawObject::kSizeTagPos - kObjectAlignmentLog2); \ |
| 420 __ csel(R2, ZR, R2, HI); \ | 420 __ csel(R2, ZR, R2, HI); \ |
| 421 \ | 421 \ |
| 422 /* Get the class index and insert it into the tags. */ \ | 422 /* Get the class index and insert it into the tags. */ \ |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); | 952 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); |
| 953 switch (kind) { | 953 switch (kind) { |
| 954 case Token::kADD: __ faddd(V0, V0, V1); break; | 954 case Token::kADD: __ faddd(V0, V0, V1); break; |
| 955 case Token::kSUB: __ fsubd(V0, V0, V1); break; | 955 case Token::kSUB: __ fsubd(V0, V0, V1); break; |
| 956 case Token::kMUL: __ fmuld(V0, V0, V1); break; | 956 case Token::kMUL: __ fmuld(V0, V0, V1); break; |
| 957 case Token::kDIV: __ fdivd(V0, V0, V1); break; | 957 case Token::kDIV: __ fdivd(V0, V0, V1); break; |
| 958 default: UNREACHABLE(); | 958 default: UNREACHABLE(); |
| 959 } | 959 } |
| 960 const Class& double_class = Class::Handle( | 960 const Class& double_class = Class::Handle( |
| 961 Isolate::Current()->object_store()->double_class()); | 961 Isolate::Current()->object_store()->double_class()); |
| 962 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP); | 962 __ TryAllocate(double_class, &fall_through, R0, kNoPP); |
| 963 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); | 963 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); |
| 964 __ ret(); | 964 __ ret(); |
| 965 __ Bind(&fall_through); | 965 __ Bind(&fall_through); |
| 966 } | 966 } |
| 967 | 967 |
| 968 | 968 |
| 969 void Intrinsifier::Double_add(Assembler* assembler) { | 969 void Intrinsifier::Double_add(Assembler* assembler) { |
| 970 DoubleArithmeticOperations(assembler, Token::kADD); | 970 DoubleArithmeticOperations(assembler, Token::kADD); |
| 971 } | 971 } |
| 972 | 972 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 994 __ tsti(R0, kSmiTagMask); | 994 __ tsti(R0, kSmiTagMask); |
| 995 __ b(&fall_through, NE); | 995 __ b(&fall_through, NE); |
| 996 // Is Smi. | 996 // Is Smi. |
| 997 __ SmiUntag(R0); | 997 __ SmiUntag(R0); |
| 998 __ scvtfd(V1, R0); | 998 __ scvtfd(V1, R0); |
| 999 __ ldr(R0, Address(SP, 1 * kWordSize)); | 999 __ ldr(R0, Address(SP, 1 * kWordSize)); |
| 1000 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); | 1000 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); |
| 1001 __ fmuld(V0, V0, V1); | 1001 __ fmuld(V0, V0, V1); |
| 1002 const Class& double_class = Class::Handle( | 1002 const Class& double_class = Class::Handle( |
| 1003 Isolate::Current()->object_store()->double_class()); | 1003 Isolate::Current()->object_store()->double_class()); |
| 1004 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP); | 1004 __ TryAllocate(double_class, &fall_through, R0, kNoPP); |
| 1005 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); | 1005 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); |
| 1006 __ ret(); | 1006 __ ret(); |
| 1007 __ Bind(&fall_through); | 1007 __ Bind(&fall_through); |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 | 1010 |
| 1011 void Intrinsifier::Double_fromInteger(Assembler* assembler) { | 1011 void Intrinsifier::Double_fromInteger(Assembler* assembler) { |
| 1012 Label fall_through; | 1012 Label fall_through; |
| 1013 | 1013 |
| 1014 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1014 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| 1015 __ tsti(R0, kSmiTagMask); | 1015 __ tsti(R0, kSmiTagMask); |
| 1016 __ b(&fall_through, NE); | 1016 __ b(&fall_through, NE); |
| 1017 // Is Smi. | 1017 // Is Smi. |
| 1018 __ SmiUntag(R0); | 1018 __ SmiUntag(R0); |
| 1019 __ scvtfd(V0, R0); | 1019 __ scvtfd(V0, R0); |
| 1020 const Class& double_class = Class::Handle( | 1020 const Class& double_class = Class::Handle( |
| 1021 Isolate::Current()->object_store()->double_class()); | 1021 Isolate::Current()->object_store()->double_class()); |
| 1022 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP); | 1022 __ TryAllocate(double_class, &fall_through, R0, kNoPP); |
| 1023 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); | 1023 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); |
| 1024 __ ret(); | 1024 __ ret(); |
| 1025 __ Bind(&fall_through); | 1025 __ Bind(&fall_through); |
| 1026 } | 1026 } |
| 1027 | 1027 |
| 1028 | 1028 |
| 1029 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { | 1029 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { |
| 1030 Label is_true; | 1030 Label is_true; |
| 1031 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1031 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| 1032 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); | 1032 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 | 1092 |
| 1093 void Intrinsifier::Math_sqrt(Assembler* assembler) { | 1093 void Intrinsifier::Math_sqrt(Assembler* assembler) { |
| 1094 Label fall_through, is_smi, double_op; | 1094 Label fall_through, is_smi, double_op; |
| 1095 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1095 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| 1096 // Argument is double and is in R0. | 1096 // Argument is double and is in R0. |
| 1097 __ LoadDFieldFromOffset(V1, R0, Double::value_offset(), kNoPP); | 1097 __ LoadDFieldFromOffset(V1, R0, Double::value_offset(), kNoPP); |
| 1098 __ Bind(&double_op); | 1098 __ Bind(&double_op); |
| 1099 __ fsqrtd(V0, V1); | 1099 __ fsqrtd(V0, V1); |
| 1100 const Class& double_class = Class::Handle( | 1100 const Class& double_class = Class::Handle( |
| 1101 Isolate::Current()->object_store()->double_class()); | 1101 Isolate::Current()->object_store()->double_class()); |
| 1102 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP); | 1102 __ TryAllocate(double_class, &fall_through, R0, kNoPP); |
| 1103 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); | 1103 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); |
| 1104 __ ret(); | 1104 __ ret(); |
| 1105 __ Bind(&is_smi); | 1105 __ Bind(&is_smi); |
| 1106 __ SmiUntag(R0); | 1106 __ SmiUntag(R0); |
| 1107 __ scvtfd(V1, R0); | 1107 __ scvtfd(V1, R0); |
| 1108 __ b(&double_op); | 1108 __ b(&double_op); |
| 1109 __ Bind(&fall_through); | 1109 __ Bind(&fall_through); |
| 1110 } | 1110 } |
| 1111 | 1111 |
| 1112 | 1112 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1315 // R3: heap->Top->Address(). | 1315 // R3: heap->Top->Address(). |
| 1316 __ LoadImmediate(R7, heap->EndAddress(), kNoPP); | 1316 __ LoadImmediate(R7, heap->EndAddress(), kNoPP); |
| 1317 __ ldr(R7, Address(R7)); | 1317 __ ldr(R7, Address(R7)); |
| 1318 __ cmp(R1, Operand(R7)); | 1318 __ cmp(R1, Operand(R7)); |
| 1319 __ b(&fail, CS); | 1319 __ b(&fail, CS); |
| 1320 | 1320 |
| 1321 // Successfully allocated the object(s), now update top to point to | 1321 // Successfully allocated the object(s), now update top to point to |
| 1322 // next object start and initialize the object. | 1322 // next object start and initialize the object. |
| 1323 __ str(R1, Address(R3)); | 1323 __ str(R1, Address(R3)); |
| 1324 __ AddImmediate(R0, R0, kHeapObjectTag, kNoPP); | 1324 __ AddImmediate(R0, R0, kHeapObjectTag, kNoPP); |
| 1325 __ UpdateAllocationStatsWithSize(kOneByteStringCid, R2, R3, kNoPP); | 1325 __ UpdateAllocationStatsWithSize(kOneByteStringCid, R2, kNoPP); |
| 1326 | 1326 |
| 1327 // Initialize the tags. | 1327 // Initialize the tags. |
| 1328 // R0: new object start as a tagged pointer. | 1328 // R0: new object start as a tagged pointer. |
| 1329 // R1: new object end address. | 1329 // R1: new object end address. |
| 1330 // R2: allocation size. | 1330 // R2: allocation size. |
| 1331 { | 1331 { |
| 1332 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 1332 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 1333 const Class& cls = | 1333 const Class& cls = |
| 1334 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1334 Class::Handle(isolate->object_store()->one_byte_string_class()); |
| 1335 | 1335 |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1552 Isolate* isolate = Isolate::Current(); | 1552 Isolate* isolate = Isolate::Current(); |
| 1553 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP); | 1553 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP); |
| 1554 // Set return value to Isolate::current_tag_. | 1554 // Set return value to Isolate::current_tag_. |
| 1555 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); | 1555 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); |
| 1556 __ ret(); | 1556 __ ret(); |
| 1557 } | 1557 } |
| 1558 | 1558 |
| 1559 } // namespace dart | 1559 } // namespace dart |
| 1560 | 1560 |
| 1561 #endif // defined TARGET_ARCH_ARM64 | 1561 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |