| 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 |