| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
| 8 | 8 |
| 9 #include "src/arm64/simulator-arm64.h" | 9 #include "src/arm64/simulator-arm64.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 masm->LeaveFrame(StackFrame::INTERNAL); | 95 masm->LeaveFrame(StackFrame::INTERNAL); |
| 96 ASSERT(masm->has_frame()); | 96 ASSERT(masm->has_frame()); |
| 97 masm->set_has_frame(false); | 97 masm->set_has_frame(false); |
| 98 } | 98 } |
| 99 | 99 |
| 100 | 100 |
| 101 // ------------------------------------------------------------------------- | 101 // ------------------------------------------------------------------------- |
| 102 // Code generators | 102 // Code generators |
| 103 | 103 |
| 104 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | 104 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
| 105 MacroAssembler* masm, AllocationSiteMode mode, | 105 MacroAssembler* masm, |
| 106 Register receiver, |
| 107 Register key, |
| 108 Register value, |
| 109 Register target_map, |
| 110 AllocationSiteMode mode, |
| 106 Label* allocation_memento_found) { | 111 Label* allocation_memento_found) { |
| 107 // ----------- S t a t e ------------- | 112 ASM_LOCATION( |
| 108 // -- x2 : receiver | 113 "ElementsTransitionGenerator::GenerateMapChangeElementsTransition"); |
| 109 // -- x3 : target map | 114 ASSERT(!AreAliased(receiver, key, value, target_map)); |
| 110 // ----------------------------------- | |
| 111 Register receiver = x2; | |
| 112 Register map = x3; | |
| 113 | 115 |
| 114 if (mode == TRACK_ALLOCATION_SITE) { | 116 if (mode == TRACK_ALLOCATION_SITE) { |
| 115 ASSERT(allocation_memento_found != NULL); | 117 ASSERT(allocation_memento_found != NULL); |
| 116 __ JumpIfJSArrayHasAllocationMemento(receiver, x10, x11, | 118 __ JumpIfJSArrayHasAllocationMemento(receiver, x10, x11, |
| 117 allocation_memento_found); | 119 allocation_memento_found); |
| 118 } | 120 } |
| 119 | 121 |
| 120 // Set transitioned map. | 122 // Set transitioned map. |
| 121 __ Str(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 123 __ Str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 122 __ RecordWriteField(receiver, | 124 __ RecordWriteField(receiver, |
| 123 HeapObject::kMapOffset, | 125 HeapObject::kMapOffset, |
| 124 map, | 126 target_map, |
| 125 x10, | 127 x10, |
| 126 kLRHasNotBeenSaved, | 128 kLRHasNotBeenSaved, |
| 127 kDontSaveFPRegs, | 129 kDontSaveFPRegs, |
| 128 EMIT_REMEMBERED_SET, | 130 EMIT_REMEMBERED_SET, |
| 129 OMIT_SMI_CHECK); | 131 OMIT_SMI_CHECK); |
| 130 } | 132 } |
| 131 | 133 |
| 132 | 134 |
| 133 void ElementsTransitionGenerator::GenerateSmiToDouble( | 135 void ElementsTransitionGenerator::GenerateSmiToDouble( |
| 134 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { | 136 MacroAssembler* masm, |
| 137 Register receiver, |
| 138 Register key, |
| 139 Register value, |
| 140 Register target_map, |
| 141 AllocationSiteMode mode, |
| 142 Label* fail) { |
| 135 ASM_LOCATION("ElementsTransitionGenerator::GenerateSmiToDouble"); | 143 ASM_LOCATION("ElementsTransitionGenerator::GenerateSmiToDouble"); |
| 136 // ----------- S t a t e ------------- | 144 Label gc_required, only_change_map; |
| 137 // -- lr : return address | 145 Register elements = x4; |
| 138 // -- x0 : value | 146 Register length = x5; |
| 139 // -- x1 : key | 147 Register array_size = x6; |
| 140 // -- x2 : receiver | 148 Register array = x7; |
| 141 // -- x3 : target map, scratch for subsequent call | |
| 142 // ----------------------------------- | |
| 143 Register receiver = x2; | |
| 144 Register target_map = x3; | |
| 145 | 149 |
| 146 Label gc_required, only_change_map; | 150 Register scratch = x6; |
| 151 |
| 152 // Verify input registers don't conflict with locals. |
| 153 ASSERT(!AreAliased(receiver, key, value, target_map, |
| 154 elements, length, array_size, array)); |
| 147 | 155 |
| 148 if (mode == TRACK_ALLOCATION_SITE) { | 156 if (mode == TRACK_ALLOCATION_SITE) { |
| 149 __ JumpIfJSArrayHasAllocationMemento(receiver, x10, x11, fail); | 157 __ JumpIfJSArrayHasAllocationMemento(receiver, x10, x11, fail); |
| 150 } | 158 } |
| 151 | 159 |
| 152 // Check for empty arrays, which only require a map transition and no changes | 160 // Check for empty arrays, which only require a map transition and no changes |
| 153 // to the backing store. | 161 // to the backing store. |
| 154 Register elements = x4; | |
| 155 __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 162 __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 156 __ JumpIfRoot(elements, Heap::kEmptyFixedArrayRootIndex, &only_change_map); | 163 __ JumpIfRoot(elements, Heap::kEmptyFixedArrayRootIndex, &only_change_map); |
| 157 | 164 |
| 158 __ Push(lr); | 165 __ Push(lr); |
| 159 Register length = x5; | |
| 160 __ Ldrsw(length, UntagSmiFieldMemOperand(elements, | 166 __ Ldrsw(length, UntagSmiFieldMemOperand(elements, |
| 161 FixedArray::kLengthOffset)); | 167 FixedArray::kLengthOffset)); |
| 162 | 168 |
| 163 // Allocate new FixedDoubleArray. | 169 // Allocate new FixedDoubleArray. |
| 164 Register array_size = x6; | |
| 165 Register array = x7; | |
| 166 __ Lsl(array_size, length, kDoubleSizeLog2); | 170 __ Lsl(array_size, length, kDoubleSizeLog2); |
| 167 __ Add(array_size, array_size, FixedDoubleArray::kHeaderSize); | 171 __ Add(array_size, array_size, FixedDoubleArray::kHeaderSize); |
| 168 __ Allocate(array_size, array, x10, x11, &gc_required, DOUBLE_ALIGNMENT); | 172 __ Allocate(array_size, array, x10, x11, &gc_required, DOUBLE_ALIGNMENT); |
| 169 // Register array is non-tagged heap object. | 173 // Register array is non-tagged heap object. |
| 170 | 174 |
| 171 // Set the destination FixedDoubleArray's length and map. | 175 // Set the destination FixedDoubleArray's length and map. |
| 172 Register map_root = x6; | 176 Register map_root = array_size; |
| 173 __ LoadRoot(map_root, Heap::kFixedDoubleArrayMapRootIndex); | 177 __ LoadRoot(map_root, Heap::kFixedDoubleArrayMapRootIndex); |
| 174 __ SmiTag(x11, length); | 178 __ SmiTag(x11, length); |
| 175 __ Str(x11, MemOperand(array, FixedDoubleArray::kLengthOffset)); | 179 __ Str(x11, MemOperand(array, FixedDoubleArray::kLengthOffset)); |
| 176 __ Str(map_root, MemOperand(array, HeapObject::kMapOffset)); | 180 __ Str(map_root, MemOperand(array, HeapObject::kMapOffset)); |
| 177 | 181 |
| 178 __ Str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 182 __ Str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 179 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, x6, | 183 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch, |
| 180 kLRHasBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, | 184 kLRHasBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, |
| 181 OMIT_SMI_CHECK); | 185 OMIT_SMI_CHECK); |
| 182 | 186 |
| 183 // Replace receiver's backing store with newly created FixedDoubleArray. | 187 // Replace receiver's backing store with newly created FixedDoubleArray. |
| 184 __ Add(x10, array, kHeapObjectTag); | 188 __ Add(x10, array, kHeapObjectTag); |
| 185 __ Str(x10, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 189 __ Str(x10, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 186 __ RecordWriteField(receiver, JSObject::kElementsOffset, x10, | 190 __ RecordWriteField(receiver, JSObject::kElementsOffset, x10, |
| 187 x6, kLRHasBeenSaved, kDontSaveFPRegs, | 191 scratch, kLRHasBeenSaved, kDontSaveFPRegs, |
| 188 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 192 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 189 | 193 |
| 190 // Prepare for conversion loop. | 194 // Prepare for conversion loop. |
| 191 Register src_elements = x10; | 195 Register src_elements = x10; |
| 192 Register dst_elements = x11; | 196 Register dst_elements = x11; |
| 193 Register dst_end = x12; | 197 Register dst_end = x12; |
| 194 __ Add(src_elements, elements, FixedArray::kHeaderSize - kHeapObjectTag); | 198 __ Add(src_elements, elements, FixedArray::kHeaderSize - kHeapObjectTag); |
| 195 __ Add(dst_elements, array, FixedDoubleArray::kHeaderSize); | 199 __ Add(dst_elements, array, FixedDoubleArray::kHeaderSize); |
| 196 __ Add(dst_end, dst_elements, Operand(length, LSL, kDoubleSizeLog2)); | 200 __ Add(dst_end, dst_elements, Operand(length, LSL, kDoubleSizeLog2)); |
| 197 | 201 |
| 198 FPRegister nan_d = d1; | 202 FPRegister nan_d = d1; |
| 199 __ Fmov(nan_d, rawbits_to_double(kHoleNanInt64)); | 203 __ Fmov(nan_d, rawbits_to_double(kHoleNanInt64)); |
| 200 | 204 |
| 201 Label entry, done; | 205 Label entry, done; |
| 202 __ B(&entry); | 206 __ B(&entry); |
| 203 | 207 |
| 204 __ Bind(&only_change_map); | 208 __ Bind(&only_change_map); |
| 205 __ Str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 209 __ Str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 206 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, x6, | 210 __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch, |
| 207 kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, | 211 kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET, |
| 208 OMIT_SMI_CHECK); | 212 OMIT_SMI_CHECK); |
| 209 __ B(&done); | 213 __ B(&done); |
| 210 | 214 |
| 211 // Call into runtime if GC is required. | 215 // Call into runtime if GC is required. |
| 212 __ Bind(&gc_required); | 216 __ Bind(&gc_required); |
| 213 __ Pop(lr); | 217 __ Pop(lr); |
| 214 __ B(fail); | 218 __ B(fail); |
| 215 | 219 |
| 216 // Iterate over the array, copying and coverting smis to doubles. If an | 220 // Iterate over the array, copying and coverting smis to doubles. If an |
| (...skipping 11 matching lines...) Expand all Loading... |
| 228 __ Cmp(dst_elements, dst_end); | 232 __ Cmp(dst_elements, dst_end); |
| 229 __ B(lt, &loop); | 233 __ B(lt, &loop); |
| 230 } | 234 } |
| 231 | 235 |
| 232 __ Pop(lr); | 236 __ Pop(lr); |
| 233 __ Bind(&done); | 237 __ Bind(&done); |
| 234 } | 238 } |
| 235 | 239 |
| 236 | 240 |
| 237 void ElementsTransitionGenerator::GenerateDoubleToObject( | 241 void ElementsTransitionGenerator::GenerateDoubleToObject( |
| 238 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { | 242 MacroAssembler* masm, |
| 243 Register receiver, |
| 244 Register key, |
| 245 Register value, |
| 246 Register target_map, |
| 247 AllocationSiteMode mode, |
| 248 Label* fail) { |
| 239 ASM_LOCATION("ElementsTransitionGenerator::GenerateDoubleToObject"); | 249 ASM_LOCATION("ElementsTransitionGenerator::GenerateDoubleToObject"); |
| 240 // ----------- S t a t e ------------- | 250 Register elements = x4; |
| 241 // -- x0 : value | 251 Register array_size = x6; |
| 242 // -- x1 : key | 252 Register array = x7; |
| 243 // -- x2 : receiver | 253 Register length = x5; |
| 244 // -- lr : return address | 254 |
| 245 // -- x3 : target map, scratch for subsequent call | 255 // Verify input registers don't conflict with locals. |
| 246 // -- x4 : scratch (elements) | 256 ASSERT(!AreAliased(receiver, key, value, target_map, |
| 247 // ----------------------------------- | 257 elements, array_size, array, length)); |
| 248 Register value = x0; | |
| 249 Register key = x1; | |
| 250 Register receiver = x2; | |
| 251 Register target_map = x3; | |
| 252 | 258 |
| 253 if (mode == TRACK_ALLOCATION_SITE) { | 259 if (mode == TRACK_ALLOCATION_SITE) { |
| 254 __ JumpIfJSArrayHasAllocationMemento(receiver, x10, x11, fail); | 260 __ JumpIfJSArrayHasAllocationMemento(receiver, x10, x11, fail); |
| 255 } | 261 } |
| 256 | 262 |
| 257 // Check for empty arrays, which only require a map transition and no changes | 263 // Check for empty arrays, which only require a map transition and no changes |
| 258 // to the backing store. | 264 // to the backing store. |
| 259 Label only_change_map; | 265 Label only_change_map; |
| 260 Register elements = x4; | 266 |
| 261 __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 267 __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 262 __ JumpIfRoot(elements, Heap::kEmptyFixedArrayRootIndex, &only_change_map); | 268 __ JumpIfRoot(elements, Heap::kEmptyFixedArrayRootIndex, &only_change_map); |
| 263 | 269 |
| 264 __ Push(lr); | 270 __ Push(lr); |
| 265 // TODO(all): These registers may not need to be pushed. Examine | 271 // TODO(all): These registers may not need to be pushed. Examine |
| 266 // RecordWriteStub and check whether it's needed. | 272 // RecordWriteStub and check whether it's needed. |
| 267 __ Push(target_map, receiver, key, value); | 273 __ Push(target_map, receiver, key, value); |
| 268 Register length = x5; | |
| 269 __ Ldrsw(length, UntagSmiFieldMemOperand(elements, | 274 __ Ldrsw(length, UntagSmiFieldMemOperand(elements, |
| 270 FixedArray::kLengthOffset)); | 275 FixedArray::kLengthOffset)); |
| 271 | |
| 272 // Allocate new FixedArray. | 276 // Allocate new FixedArray. |
| 273 Register array_size = x6; | |
| 274 Register array = x7; | |
| 275 Label gc_required; | 277 Label gc_required; |
| 276 __ Mov(array_size, FixedDoubleArray::kHeaderSize); | 278 __ Mov(array_size, FixedDoubleArray::kHeaderSize); |
| 277 __ Add(array_size, array_size, Operand(length, LSL, kPointerSizeLog2)); | 279 __ Add(array_size, array_size, Operand(length, LSL, kPointerSizeLog2)); |
| 278 __ Allocate(array_size, array, x10, x11, &gc_required, NO_ALLOCATION_FLAGS); | 280 __ Allocate(array_size, array, x10, x11, &gc_required, NO_ALLOCATION_FLAGS); |
| 279 | 281 |
| 280 // Set destination FixedDoubleArray's length and map. | 282 // Set destination FixedDoubleArray's length and map. |
| 281 Register map_root = x6; | 283 Register map_root = array_size; |
| 282 __ LoadRoot(map_root, Heap::kFixedArrayMapRootIndex); | 284 __ LoadRoot(map_root, Heap::kFixedArrayMapRootIndex); |
| 283 __ SmiTag(x11, length); | 285 __ SmiTag(x11, length); |
| 284 __ Str(x11, MemOperand(array, FixedDoubleArray::kLengthOffset)); | 286 __ Str(x11, MemOperand(array, FixedDoubleArray::kLengthOffset)); |
| 285 __ Str(map_root, MemOperand(array, HeapObject::kMapOffset)); | 287 __ Str(map_root, MemOperand(array, HeapObject::kMapOffset)); |
| 286 | 288 |
| 287 // Prepare for conversion loop. | 289 // Prepare for conversion loop. |
| 288 Register src_elements = x10; | 290 Register src_elements = x10; |
| 289 Register dst_elements = x11; | 291 Register dst_elements = x11; |
| 290 Register dst_end = x12; | 292 Register dst_end = x12; |
| 291 __ Add(src_elements, elements, | 293 __ Add(src_elements, elements, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 309 __ B(fail); | 311 __ B(fail); |
| 310 | 312 |
| 311 { | 313 { |
| 312 Label loop, convert_hole; | 314 Label loop, convert_hole; |
| 313 __ Bind(&loop); | 315 __ Bind(&loop); |
| 314 __ Ldr(x13, MemOperand(src_elements, kPointerSize, PostIndex)); | 316 __ Ldr(x13, MemOperand(src_elements, kPointerSize, PostIndex)); |
| 315 __ Cmp(x13, kHoleNanInt64); | 317 __ Cmp(x13, kHoleNanInt64); |
| 316 __ B(eq, &convert_hole); | 318 __ B(eq, &convert_hole); |
| 317 | 319 |
| 318 // Non-hole double, copy value into a heap number. | 320 // Non-hole double, copy value into a heap number. |
| 319 Register heap_num = x5; | 321 Register heap_num = length; |
| 320 __ AllocateHeapNumber(heap_num, &gc_required, x6, x4, | 322 Register scratch = array_size; |
| 323 Register scratch2 = elements; |
| 324 __ AllocateHeapNumber(heap_num, &gc_required, scratch, scratch2, |
| 321 x13, heap_num_map); | 325 x13, heap_num_map); |
| 322 __ Mov(x13, dst_elements); | 326 __ Mov(x13, dst_elements); |
| 323 __ Str(heap_num, MemOperand(dst_elements, kPointerSize, PostIndex)); | 327 __ Str(heap_num, MemOperand(dst_elements, kPointerSize, PostIndex)); |
| 324 __ RecordWrite(array, x13, heap_num, kLRHasBeenSaved, kDontSaveFPRegs, | 328 __ RecordWrite(array, x13, heap_num, kLRHasBeenSaved, kDontSaveFPRegs, |
| 325 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 329 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 326 | 330 |
| 327 __ B(&entry); | 331 __ B(&entry); |
| 328 | 332 |
| 329 // Replace the-hole NaN with the-hole pointer. | 333 // Replace the-hole NaN with the-hole pointer. |
| 330 __ Bind(&convert_hole); | 334 __ Bind(&convert_hole); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 __ Fmul(result, double_temp3, double_temp1); | 616 __ Fmul(result, double_temp3, double_temp1); |
| 613 | 617 |
| 614 __ Bind(&done); | 618 __ Bind(&done); |
| 615 } | 619 } |
| 616 | 620 |
| 617 #undef __ | 621 #undef __ |
| 618 | 622 |
| 619 } } // namespace v8::internal | 623 } } // namespace v8::internal |
| 620 | 624 |
| 621 #endif // V8_TARGET_ARCH_ARM64 | 625 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |