| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/ic-inl.h" | 9 #include "src/ic-inl.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 Register scratch1, | 566 Register scratch1, |
| 567 Register scratch2, | 567 Register scratch2, |
| 568 Label* miss_label) { | 568 Label* miss_label) { |
| 569 // r0 : value | 569 // r0 : value |
| 570 Label exit; | 570 Label exit; |
| 571 | 571 |
| 572 // Stub never generated for non-global objects that require access | 572 // Stub never generated for non-global objects that require access |
| 573 // checks. | 573 // checks. |
| 574 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 574 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 575 | 575 |
| 576 int index = lookup->GetFieldIndex().field_index(); | 576 FieldIndex index = lookup->GetFieldIndex(); |
| 577 | |
| 578 // Adjust for the number of properties stored in the object. Even in the | |
| 579 // face of a transition we can use the old map here because the size of the | |
| 580 // object and the number of in-object properties is not going to change. | |
| 581 index -= object->map()->inobject_properties(); | |
| 582 | 577 |
| 583 Representation representation = lookup->representation(); | 578 Representation representation = lookup->representation(); |
| 584 ASSERT(!representation.IsNone()); | 579 ASSERT(!representation.IsNone()); |
| 585 if (representation.IsSmi()) { | 580 if (representation.IsSmi()) { |
| 586 __ JumpIfNotSmi(value_reg, miss_label); | 581 __ JumpIfNotSmi(value_reg, miss_label); |
| 587 } else if (representation.IsHeapObject()) { | 582 } else if (representation.IsHeapObject()) { |
| 588 __ JumpIfSmi(value_reg, miss_label); | 583 __ JumpIfSmi(value_reg, miss_label); |
| 589 HeapType* field_type = lookup->GetFieldType(); | 584 HeapType* field_type = lookup->GetFieldType(); |
| 590 HeapType::Iterator<Map> it = field_type->Classes(); | 585 HeapType::Iterator<Map> it = field_type->Classes(); |
| 591 if (!it.Done()) { | 586 if (!it.Done()) { |
| 592 __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 587 __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
| 593 Label do_store; | 588 Label do_store; |
| 594 while (true) { | 589 while (true) { |
| 595 __ CompareMap(scratch1, it.Current(), &do_store); | 590 __ CompareMap(scratch1, it.Current(), &do_store); |
| 596 it.Advance(); | 591 it.Advance(); |
| 597 if (it.Done()) { | 592 if (it.Done()) { |
| 598 __ b(ne, miss_label); | 593 __ b(ne, miss_label); |
| 599 break; | 594 break; |
| 600 } | 595 } |
| 601 __ b(eq, &do_store); | 596 __ b(eq, &do_store); |
| 602 } | 597 } |
| 603 __ bind(&do_store); | 598 __ bind(&do_store); |
| 604 } | 599 } |
| 605 } else if (representation.IsDouble()) { | 600 } else if (representation.IsDouble()) { |
| 606 // Load the double storage. | 601 // Load the double storage. |
| 607 if (index < 0) { | 602 if (index.is_inobject()) { |
| 608 int offset = object->map()->instance_size() + (index * kPointerSize); | 603 __ ldr(scratch1, FieldMemOperand(receiver_reg, index.offset())); |
| 609 __ ldr(scratch1, FieldMemOperand(receiver_reg, offset)); | |
| 610 } else { | 604 } else { |
| 611 __ ldr(scratch1, | 605 __ ldr(scratch1, |
| 612 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 606 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 613 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 607 __ ldr(scratch1, FieldMemOperand(scratch1, index.offset())); |
| 614 __ ldr(scratch1, FieldMemOperand(scratch1, offset)); | |
| 615 } | 608 } |
| 616 | 609 |
| 617 // Store the value into the storage. | 610 // Store the value into the storage. |
| 618 Label do_store, heap_number; | 611 Label do_store, heap_number; |
| 619 __ JumpIfNotSmi(value_reg, &heap_number); | 612 __ JumpIfNotSmi(value_reg, &heap_number); |
| 620 __ SmiUntag(scratch2, value_reg); | 613 __ SmiUntag(scratch2, value_reg); |
| 621 __ vmov(s0, scratch2); | 614 __ vmov(s0, scratch2); |
| 622 __ vcvt_f64_s32(d0, s0); | 615 __ vcvt_f64_s32(d0, s0); |
| 623 __ jmp(&do_store); | 616 __ jmp(&do_store); |
| 624 | 617 |
| 625 __ bind(&heap_number); | 618 __ bind(&heap_number); |
| 626 __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, | 619 __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, |
| 627 miss_label, DONT_DO_SMI_CHECK); | 620 miss_label, DONT_DO_SMI_CHECK); |
| 628 __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 621 __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
| 629 | 622 |
| 630 __ bind(&do_store); | 623 __ bind(&do_store); |
| 631 __ vstr(d0, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); | 624 __ vstr(d0, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); |
| 632 // Return the value (register r0). | 625 // Return the value (register r0). |
| 633 ASSERT(value_reg.is(r0)); | 626 ASSERT(value_reg.is(r0)); |
| 634 __ Ret(); | 627 __ Ret(); |
| 635 return; | 628 return; |
| 636 } | 629 } |
| 637 | 630 |
| 638 // TODO(verwaest): Share this code as a code stub. | 631 // TODO(verwaest): Share this code as a code stub. |
| 639 SmiCheck smi_check = representation.IsTagged() | 632 SmiCheck smi_check = representation.IsTagged() |
| 640 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 633 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
| 641 if (index < 0) { | 634 if (index.is_inobject()) { |
| 642 // Set the property straight into the object. | 635 // Set the property straight into the object. |
| 643 int offset = object->map()->instance_size() + (index * kPointerSize); | 636 __ str(value_reg, FieldMemOperand(receiver_reg, index.offset())); |
| 644 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); | |
| 645 | 637 |
| 646 if (!representation.IsSmi()) { | 638 if (!representation.IsSmi()) { |
| 647 // Skip updating write barrier if storing a smi. | 639 // Skip updating write barrier if storing a smi. |
| 648 __ JumpIfSmi(value_reg, &exit); | 640 __ JumpIfSmi(value_reg, &exit); |
| 649 | 641 |
| 650 // Update the write barrier for the array address. | 642 // Update the write barrier for the array address. |
| 651 // Pass the now unused name_reg as a scratch register. | 643 // Pass the now unused name_reg as a scratch register. |
| 652 __ mov(name_reg, value_reg); | 644 __ mov(name_reg, value_reg); |
| 653 __ RecordWriteField(receiver_reg, | 645 __ RecordWriteField(receiver_reg, |
| 654 offset, | 646 index.offset(), |
| 655 name_reg, | 647 name_reg, |
| 656 scratch1, | 648 scratch1, |
| 657 kLRHasNotBeenSaved, | 649 kLRHasNotBeenSaved, |
| 658 kDontSaveFPRegs, | 650 kDontSaveFPRegs, |
| 659 EMIT_REMEMBERED_SET, | 651 EMIT_REMEMBERED_SET, |
| 660 smi_check); | 652 smi_check); |
| 661 } | 653 } |
| 662 } else { | 654 } else { |
| 663 // Write to the properties array. | 655 // Write to the properties array. |
| 664 int offset = index * kPointerSize + FixedArray::kHeaderSize; | |
| 665 // Get the properties array | 656 // Get the properties array |
| 666 __ ldr(scratch1, | 657 __ ldr(scratch1, |
| 667 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 658 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 668 __ str(value_reg, FieldMemOperand(scratch1, offset)); | 659 __ str(value_reg, FieldMemOperand(scratch1, index.offset())); |
| 669 | 660 |
| 670 if (!representation.IsSmi()) { | 661 if (!representation.IsSmi()) { |
| 671 // Skip updating write barrier if storing a smi. | 662 // Skip updating write barrier if storing a smi. |
| 672 __ JumpIfSmi(value_reg, &exit); | 663 __ JumpIfSmi(value_reg, &exit); |
| 673 | 664 |
| 674 // Update the write barrier for the array address. | 665 // Update the write barrier for the array address. |
| 675 // Ok to clobber receiver_reg and name_reg, since we return. | 666 // Ok to clobber receiver_reg and name_reg, since we return. |
| 676 __ mov(name_reg, value_reg); | 667 __ mov(name_reg, value_reg); |
| 677 __ RecordWriteField(scratch1, | 668 __ RecordWriteField(scratch1, |
| 678 offset, | 669 index.offset(), |
| 679 name_reg, | 670 name_reg, |
| 680 receiver_reg, | 671 receiver_reg, |
| 681 kLRHasNotBeenSaved, | 672 kLRHasNotBeenSaved, |
| 682 kDontSaveFPRegs, | 673 kDontSaveFPRegs, |
| 683 EMIT_REMEMBERED_SET, | 674 EMIT_REMEMBERED_SET, |
| 684 smi_check); | 675 smi_check); |
| 685 } | 676 } |
| 686 } | 677 } |
| 687 | 678 |
| 688 // Return the value (register r0). | 679 // Return the value (register r0). |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 __ b(ne, &miss); | 990 __ b(ne, &miss); |
| 1000 } | 991 } |
| 1001 | 992 |
| 1002 HandlerFrontendFooter(name, &miss); | 993 HandlerFrontendFooter(name, &miss); |
| 1003 return reg; | 994 return reg; |
| 1004 } | 995 } |
| 1005 | 996 |
| 1006 | 997 |
| 1007 void LoadStubCompiler::GenerateLoadField(Register reg, | 998 void LoadStubCompiler::GenerateLoadField(Register reg, |
| 1008 Handle<JSObject> holder, | 999 Handle<JSObject> holder, |
| 1009 PropertyIndex field, | 1000 FieldIndex field, |
| 1010 Representation representation) { | 1001 Representation representation) { |
| 1011 if (!reg.is(receiver())) __ mov(receiver(), reg); | 1002 if (!reg.is(receiver())) __ mov(receiver(), reg); |
| 1012 if (kind() == Code::LOAD_IC) { | 1003 if (kind() == Code::LOAD_IC) { |
| 1013 LoadFieldStub stub(isolate(), | 1004 LoadFieldStub stub(isolate(), field); |
| 1014 field.is_inobject(holder), | |
| 1015 field.translate(holder), | |
| 1016 representation); | |
| 1017 GenerateTailCall(masm(), stub.GetCode()); | 1005 GenerateTailCall(masm(), stub.GetCode()); |
| 1018 } else { | 1006 } else { |
| 1019 KeyedLoadFieldStub stub(isolate(), | 1007 KeyedLoadFieldStub stub(isolate(), field); |
| 1020 field.is_inobject(holder), | |
| 1021 field.translate(holder), | |
| 1022 representation); | |
| 1023 GenerateTailCall(masm(), stub.GetCode()); | 1008 GenerateTailCall(masm(), stub.GetCode()); |
| 1024 } | 1009 } |
| 1025 } | 1010 } |
| 1026 | 1011 |
| 1027 | 1012 |
| 1028 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 1013 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { |
| 1029 // Return the constant value. | 1014 // Return the constant value. |
| 1030 __ Move(r0, value); | 1015 __ Move(r0, value); |
| 1031 __ Ret(); | 1016 __ Ret(); |
| 1032 } | 1017 } |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1522 // ----------------------------------- | 1507 // ----------------------------------- |
| 1523 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1508 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1524 } | 1509 } |
| 1525 | 1510 |
| 1526 | 1511 |
| 1527 #undef __ | 1512 #undef __ |
| 1528 | 1513 |
| 1529 } } // namespace v8::internal | 1514 } } // namespace v8::internal |
| 1530 | 1515 |
| 1531 #endif // V8_TARGET_ARCH_ARM | 1516 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |