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_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
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/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 // R6: allocation stats address. | 910 // R6: allocation stats address. |
911 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); | 911 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); |
912 | 912 |
913 // Setup the parent field. | 913 // Setup the parent field. |
914 // R0: new object. | 914 // R0: new object. |
915 // R1: number of context variables. | 915 // R1: number of context variables. |
916 // R2: object size. | 916 // R2: object size. |
917 // R3: next object start. | 917 // R3: next object start. |
918 // R6: allocation stats address. | 918 // R6: allocation stats address. |
919 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null())); | 919 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null())); |
920 __ str(R4, FieldAddress(R0, Context::parent_offset())); | 920 __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Context::parent_offset()), |
| 921 R4); |
921 | 922 |
922 // Initialize the context variables. | 923 // Initialize the context variables. |
923 // R0: new object. | 924 // R0: new object. |
924 // R1: number of context variables. | 925 // R1: number of context variables. |
925 // R2: object size. | 926 // R2: object size. |
926 // R3: next object start. | 927 // R3: next object start. |
927 // R4, R5: raw null. | 928 // R4, R5: raw null. |
928 // R6: allocation stats address. | 929 // R6: allocation stats address. |
929 Label loop; | 930 Label loop; |
930 __ AddImmediate(R7, R0, Context::variable_offset(0) - kHeapObjectTag); | 931 __ AddImmediate(R7, R0, Context::variable_offset(0) - kHeapObjectTag); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 | 1094 |
1094 // Initialize the remaining words of the object. | 1095 // Initialize the remaining words of the object. |
1095 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); | 1096 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); |
1096 | 1097 |
1097 // R2: raw null. | 1098 // R2: raw null. |
1098 // R0: new object (tagged). | 1099 // R0: new object (tagged). |
1099 // R1: next object start. | 1100 // R1: next object start. |
1100 // R5: allocation stats table. | 1101 // R5: allocation stats table. |
1101 // First try inlining the initialization without a loop. | 1102 // First try inlining the initialization without a loop. |
1102 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1103 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
1103 // Check if the object contains any non-header fields. | |
1104 // Small objects are initialized using a consecutive set of writes. | 1104 // Small objects are initialized using a consecutive set of writes. |
1105 intptr_t current_offset = Instance::NextFieldOffset(); | 1105 intptr_t begin_offset = Instance::NextFieldOffset() - kHeapObjectTag; |
1106 // Write two nulls at a time. | 1106 intptr_t end_offset = instance_size - kHeapObjectTag; |
1107 if (instance_size >= 2 * kWordSize) { | 1107 // Save one move if less than two fields. |
| 1108 if ((end_offset - begin_offset) >= (2 * kWordSize)) { |
1108 __ mov(R3, Operand(R2)); | 1109 __ mov(R3, Operand(R2)); |
1109 while (current_offset + kWordSize < instance_size) { | |
1110 __ StoreToOffset(kWordPair, R2, R0, current_offset - kHeapObjectTag); | |
1111 current_offset += 2 * kWordSize; | |
1112 } | |
1113 } | 1110 } |
1114 // Write remainder. | 1111 __ InitializeFieldsNoBarrierUnrolled(R0, R0, begin_offset, end_offset, |
1115 while (current_offset < instance_size) { | 1112 R2, R3); |
1116 __ StoreToOffset(kWord, R2, R0, current_offset - kHeapObjectTag); | |
1117 current_offset += kWordSize; | |
1118 } | |
1119 } else { | 1113 } else { |
1120 // There are more than kInlineInstanceSize(12) fields | 1114 // There are more than kInlineInstanceSize(12) fields |
1121 __ add(R4, R0, Operand(Instance::NextFieldOffset() - kHeapObjectTag)); | 1115 __ add(R4, R0, Operand(Instance::NextFieldOffset() - kHeapObjectTag)); |
1122 __ mov(R3, Operand(R2)); | 1116 __ mov(R3, Operand(R2)); |
1123 // Loop until the whole object is initialized. | 1117 // Loop until the whole object is initialized. |
1124 // R2: raw null. | 1118 // R2: raw null. |
1125 // R3: raw null. | 1119 // R3: raw null. |
1126 // R0: new object (tagged). | 1120 // R0: new object (tagged). |
1127 // R1: next object start. | 1121 // R1: next object start. |
1128 // R4: next word to be initialized. | 1122 // R4: next word to be initialized. |
1129 // R5: allocation stats table. | 1123 // R5: allocation stats table. |
1130 __ InitializeFieldsNoBarrier(R0, R4, R1, R2, R3); | 1124 __ InitializeFieldsNoBarrier(R0, R4, R1, R2, R3); |
1131 } | 1125 } |
1132 if (is_cls_parameterized) { | 1126 if (is_cls_parameterized) { |
1133 // Set the type arguments in the new object. | 1127 // Set the type arguments in the new object. |
1134 __ ldr(R4, Address(SP, 0)); | 1128 __ ldr(R4, Address(SP, 0)); |
1135 __ StoreToOffset(kWord, R4, | 1129 FieldAddress type_args(R0, cls.type_arguments_field_offset()); |
1136 R0, cls.type_arguments_field_offset() - kHeapObjectTag); | 1130 __ StoreIntoObjectNoBarrier(R0, type_args, R4); |
1137 } | 1131 } |
1138 | 1132 |
1139 // Done allocating and initializing the instance. | 1133 // Done allocating and initializing the instance. |
1140 // R0: new object (tagged). | 1134 // R0: new object (tagged). |
1141 // R5: allocation stats table. | 1135 // R5: allocation stats table. |
1142 | 1136 |
1143 // Update allocation stats. | 1137 // Update allocation stats. |
1144 __ IncrementAllocationStats(R5, cls.id(), space); | 1138 __ IncrementAllocationStats(R5, cls.id(), space); |
1145 | 1139 |
1146 // R0: new object (tagged). | 1140 // R0: new object (tagged). |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1296 __ b(&ok, EQ); | 1290 __ b(&ok, EQ); |
1297 __ Bind(&error); | 1291 __ Bind(&error); |
1298 __ Stop("Incorrect IC data"); | 1292 __ Stop("Incorrect IC data"); |
1299 __ Bind(&ok); | 1293 __ Bind(&ok); |
1300 #endif | 1294 #endif |
1301 // Update counter. | 1295 // Update counter. |
1302 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1296 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1303 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1297 __ LoadFromOffset(kWord, R1, R6, count_offset); |
1304 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1298 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
1305 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. | 1299 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
1306 __ StoreToOffset(kWord, R1, R6, count_offset); | 1300 __ StoreIntoSmiField(Address(R6, count_offset), R1); |
1307 __ Ret(); | 1301 __ Ret(); |
1308 } | 1302 } |
1309 | 1303 |
1310 | 1304 |
1311 // Generate inline cache check for 'num_args'. | 1305 // Generate inline cache check for 'num_args'. |
1312 // LR: return address. | 1306 // LR: return address. |
1313 // R5: inline cache data object. | 1307 // R5: inline cache data object. |
1314 // Control flow: | 1308 // Control flow: |
1315 // - If receiver is null -> jump to IC miss. | 1309 // - If receiver is null -> jump to IC miss. |
1316 // - If receiver is Smi -> load Smi class. | 1310 // - If receiver is Smi -> load Smi class. |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1440 __ Bind(&found); | 1434 __ Bind(&found); |
1441 // R6: pointer to an IC data check group. | 1435 // R6: pointer to an IC data check group. |
1442 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1436 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
1443 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1437 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1444 __ LoadFromOffset(kWord, R0, R6, target_offset); | 1438 __ LoadFromOffset(kWord, R0, R6, target_offset); |
1445 | 1439 |
1446 // Update counter. | 1440 // Update counter. |
1447 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1441 __ LoadFromOffset(kWord, R1, R6, count_offset); |
1448 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1442 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
1449 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. | 1443 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
1450 __ StoreToOffset(kWord, R1, R6, count_offset); | 1444 __ StoreIntoSmiField(Address(R6, count_offset), R1); |
1451 | 1445 |
1452 __ Bind(&call_target_function); | 1446 __ Bind(&call_target_function); |
1453 // R0: target function. | 1447 // R0: target function. |
1454 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1448 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); |
1455 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | 1449 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
1456 __ bx(R2); | 1450 __ bx(R2); |
1457 | 1451 |
1458 __ Bind(&stepping); | 1452 __ Bind(&stepping); |
1459 __ EnterStubFrame(); | 1453 __ EnterStubFrame(); |
1460 __ Push(R5); // Preserve IC data. | 1454 __ Push(R5); // Preserve IC data. |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 // R6: ic_data_array with entries: target functions and count. | 1567 // R6: ic_data_array with entries: target functions and count. |
1574 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1568 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
1575 // R6: points directly to the first ic data array element. | 1569 // R6: points directly to the first ic data array element. |
1576 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1570 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1577 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1571 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1578 | 1572 |
1579 // Increment count for this call. | 1573 // Increment count for this call. |
1580 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1574 __ LoadFromOffset(kWord, R1, R6, count_offset); |
1581 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1575 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
1582 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. | 1576 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
1583 __ StoreToOffset(kWord, R1, R6, count_offset); | 1577 __ StoreIntoSmiField(Address(R6, count_offset), R1); |
1584 | 1578 |
1585 // Load arguments descriptor into R4. | 1579 // Load arguments descriptor into R4. |
1586 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1580 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
1587 | 1581 |
1588 // Get function and call it, if possible. | 1582 // Get function and call it, if possible. |
1589 __ LoadFromOffset(kWord, R0, R6, target_offset); | 1583 __ LoadFromOffset(kWord, R0, R6, target_offset); |
1590 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1584 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); |
1591 | 1585 |
1592 // R0: function. | 1586 // R0: function. |
1593 // R2: target instructions. | 1587 // R2: target instructions. |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1977 const Register right = R0; | 1971 const Register right = R0; |
1978 __ ldr(left, Address(SP, 1 * kWordSize)); | 1972 __ ldr(left, Address(SP, 1 * kWordSize)); |
1979 __ ldr(right, Address(SP, 0 * kWordSize)); | 1973 __ ldr(right, Address(SP, 0 * kWordSize)); |
1980 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1974 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
1981 __ Ret(); | 1975 __ Ret(); |
1982 } | 1976 } |
1983 | 1977 |
1984 } // namespace dart | 1978 } // namespace dart |
1985 | 1979 |
1986 #endif // defined TARGET_ARCH_ARM | 1980 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |