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