| 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/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 Label* miss_label) { | 541 Label* miss_label) { |
| 542 // x0 : value | 542 // x0 : value |
| 543 Label exit; | 543 Label exit; |
| 544 | 544 |
| 545 // Stub never generated for objects that require access checks. | 545 // Stub never generated for objects that require access checks. |
| 546 DCHECK(!object->IsAccessCheckNeeded()); | 546 DCHECK(!object->IsAccessCheckNeeded()); |
| 547 DCHECK(!object->IsJSGlobalProxy()); | 547 DCHECK(!object->IsJSGlobalProxy()); |
| 548 | 548 |
| 549 FieldIndex index = lookup->GetFieldIndex(); | 549 FieldIndex index = lookup->GetFieldIndex(); |
| 550 | 550 |
| 551 Representation representation = lookup->representation(); | 551 DCHECK(lookup->representation().IsHeapObject()); |
| 552 DCHECK(!representation.IsNone()); | 552 __ JumpIfSmi(value_reg, miss_label); |
| 553 if (representation.IsSmi()) { | 553 HeapType* field_type = lookup->GetFieldType(); |
| 554 __ JumpIfNotSmi(value_reg, miss_label); | 554 HeapType::Iterator<Map> it = field_type->Classes(); |
| 555 } else if (representation.IsHeapObject()) { | 555 if (!it.Done()) { |
| 556 __ JumpIfSmi(value_reg, miss_label); | 556 __ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
| 557 HeapType* field_type = lookup->GetFieldType(); | 557 Label do_store; |
| 558 HeapType::Iterator<Map> it = field_type->Classes(); | 558 while (true) { |
| 559 if (!it.Done()) { | 559 __ CompareMap(scratch1, it.Current()); |
| 560 __ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 560 it.Advance(); |
| 561 Label do_store; | 561 if (it.Done()) { |
| 562 while (true) { | 562 __ B(ne, miss_label); |
| 563 __ CompareMap(scratch1, it.Current()); | 563 break; |
| 564 it.Advance(); | |
| 565 if (it.Done()) { | |
| 566 __ B(ne, miss_label); | |
| 567 break; | |
| 568 } | |
| 569 __ B(eq, &do_store); | |
| 570 } | 564 } |
| 571 __ Bind(&do_store); | 565 __ B(eq, &do_store); |
| 572 } | 566 } |
| 573 } else if (representation.IsDouble()) { | |
| 574 UseScratchRegisterScope temps(masm()); | |
| 575 DoubleRegister temp_double = temps.AcquireD(); | |
| 576 | |
| 577 __ SmiUntagToDouble(temp_double, value_reg, kSpeculativeUntag); | |
| 578 | |
| 579 // Load the double storage. | |
| 580 if (index.is_inobject()) { | |
| 581 __ Ldr(scratch1, FieldMemOperand(receiver_reg, index.offset())); | |
| 582 } else { | |
| 583 __ Ldr(scratch1, | |
| 584 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | |
| 585 __ Ldr(scratch1, FieldMemOperand(scratch1, index.offset())); | |
| 586 } | |
| 587 | |
| 588 // Store the value into the storage. | |
| 589 Label do_store, heap_number; | |
| 590 | |
| 591 __ JumpIfSmi(value_reg, &do_store); | |
| 592 | |
| 593 __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, | |
| 594 miss_label, DONT_DO_SMI_CHECK); | |
| 595 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | |
| 596 | |
| 597 __ Bind(&do_store); | 567 __ Bind(&do_store); |
| 598 __ Str(temp_double, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); | |
| 599 | |
| 600 // Return the value (register x0). | |
| 601 DCHECK(value_reg.is(x0)); | |
| 602 __ Ret(); | |
| 603 return; | |
| 604 } | 568 } |
| 605 | 569 |
| 606 // TODO(verwaest): Share this code as a code stub. | |
| 607 SmiCheck smi_check = representation.IsTagged() | |
| 608 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | |
| 609 if (index.is_inobject()) { | 570 if (index.is_inobject()) { |
| 610 // Set the property straight into the object. | 571 // Set the property straight into the object. |
| 611 __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset())); | 572 __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset())); |
| 612 | 573 |
| 613 if (!representation.IsSmi()) { | 574 // Skip updating write barrier if storing a smi. |
| 614 // Skip updating write barrier if storing a smi. | 575 __ JumpIfSmi(value_reg, &exit); |
| 615 __ JumpIfSmi(value_reg, &exit); | |
| 616 | 576 |
| 617 // Update the write barrier for the array address. | 577 // Update the write barrier for the array address. |
| 618 // Pass the now unused name_reg as a scratch register. | 578 // Pass the now unused name_reg as a scratch register. |
| 619 __ Mov(name_reg, value_reg); | 579 __ Mov(name_reg, value_reg); |
| 620 __ RecordWriteField(receiver_reg, | 580 __ RecordWriteField(receiver_reg, index.offset(), name_reg, scratch1, |
| 621 index.offset(), | 581 kLRHasNotBeenSaved, kDontSaveFPRegs, |
| 622 name_reg, | 582 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 623 scratch1, | |
| 624 kLRHasNotBeenSaved, | |
| 625 kDontSaveFPRegs, | |
| 626 EMIT_REMEMBERED_SET, | |
| 627 smi_check); | |
| 628 } | |
| 629 } else { | 583 } else { |
| 630 // Write to the properties array. | 584 // Write to the properties array. |
| 631 // Get the properties array | 585 // Get the properties array |
| 632 __ Ldr(scratch1, | 586 __ Ldr(scratch1, |
| 633 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 587 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 634 __ Str(value_reg, FieldMemOperand(scratch1, index.offset())); | 588 __ Str(value_reg, FieldMemOperand(scratch1, index.offset())); |
| 635 | 589 |
| 636 if (!representation.IsSmi()) { | 590 // Skip updating write barrier if storing a smi. |
| 637 // Skip updating write barrier if storing a smi. | 591 __ JumpIfSmi(value_reg, &exit); |
| 638 __ JumpIfSmi(value_reg, &exit); | |
| 639 | 592 |
| 640 // Update the write barrier for the array address. | 593 // Update the write barrier for the array address. |
| 641 // Ok to clobber receiver_reg and name_reg, since we return. | 594 // Ok to clobber receiver_reg and name_reg, since we return. |
| 642 __ Mov(name_reg, value_reg); | 595 __ Mov(name_reg, value_reg); |
| 643 __ RecordWriteField(scratch1, | 596 __ RecordWriteField(scratch1, index.offset(), name_reg, receiver_reg, |
| 644 index.offset(), | 597 kLRHasNotBeenSaved, kDontSaveFPRegs, |
| 645 name_reg, | 598 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 646 receiver_reg, | |
| 647 kLRHasNotBeenSaved, | |
| 648 kDontSaveFPRegs, | |
| 649 EMIT_REMEMBERED_SET, | |
| 650 smi_check); | |
| 651 } | |
| 652 } | 599 } |
| 653 | 600 |
| 654 __ Bind(&exit); | 601 __ Bind(&exit); |
| 655 // Return the value (register x0). | 602 // Return the value (register x0). |
| 656 DCHECK(value_reg.is(x0)); | 603 DCHECK(value_reg.is(x0)); |
| 657 __ Ret(); | 604 __ Ret(); |
| 658 } | 605 } |
| 659 | 606 |
| 660 | 607 |
| 661 Register PropertyHandlerCompiler::CheckPrototypes( | 608 Register PropertyHandlerCompiler::CheckPrototypes( |
| (...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1248 | 1195 |
| 1249 // Miss case, call the runtime. | 1196 // Miss case, call the runtime. |
| 1250 __ Bind(&miss); | 1197 __ Bind(&miss); |
| 1251 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1198 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1252 } | 1199 } |
| 1253 | 1200 |
| 1254 | 1201 |
| 1255 } } // namespace v8::internal | 1202 } } // namespace v8::internal |
| 1256 | 1203 |
| 1257 #endif // V8_TARGET_ARCH_ARM64 | 1204 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |