OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 | 458 |
459 // Check that the map of the object hasn't changed. | 459 // Check that the map of the object hasn't changed. |
460 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label, | 460 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label, |
461 DO_SMI_CHECK, REQUIRE_EXACT_MAP); | 461 DO_SMI_CHECK, REQUIRE_EXACT_MAP); |
462 | 462 |
463 // Perform global security token check if needed. | 463 // Perform global security token check if needed. |
464 if (object->IsJSGlobalProxy()) { | 464 if (object->IsJSGlobalProxy()) { |
465 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); | 465 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); |
466 } | 466 } |
467 | 467 |
| 468 int descriptor = transition->LastAdded(); |
| 469 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 470 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 471 Representation representation = details.representation(); |
| 472 ASSERT(!representation.IsNone()); |
| 473 |
| 474 // Ensure no transitions to deprecated maps are followed. |
| 475 __ CheckMapDeprecated(transition, scratch1, miss_label); |
| 476 |
| 477 if (FLAG_track_fields && representation.IsSmi()) { |
| 478 __ JumpIfNotSmi(value_reg, miss_label); |
| 479 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 480 Label do_store; |
| 481 __ JumpIfSmi(value_reg, &do_store); |
| 482 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
| 483 miss_label, DONT_DO_SMI_CHECK); |
| 484 __ bind(&do_store); |
| 485 } |
| 486 |
468 // Check that we are allowed to write this. | 487 // Check that we are allowed to write this. |
469 if (object->GetPrototype()->IsJSObject()) { | 488 if (object->GetPrototype()->IsJSObject()) { |
470 JSObject* holder; | 489 JSObject* holder; |
471 // holder == object indicates that no property was found. | 490 // holder == object indicates that no property was found. |
472 if (lookup->holder() != *object) { | 491 if (lookup->holder() != *object) { |
473 holder = lookup->holder(); | 492 holder = lookup->holder(); |
474 } else { | 493 } else { |
475 // Find the top object. | 494 // Find the top object. |
476 holder = *object; | 495 holder = *object; |
477 do { | 496 do { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 // face of a transition we can use the old map here because the size of the | 559 // face of a transition we can use the old map here because the size of the |
541 // object and the number of in-object properties is not going to change. | 560 // object and the number of in-object properties is not going to change. |
542 index -= object->map()->inobject_properties(); | 561 index -= object->map()->inobject_properties(); |
543 | 562 |
544 // TODO(verwaest): Share this code as a code stub. | 563 // TODO(verwaest): Share this code as a code stub. |
545 if (index < 0) { | 564 if (index < 0) { |
546 // Set the property straight into the object. | 565 // Set the property straight into the object. |
547 int offset = object->map()->instance_size() + (index * kPointerSize); | 566 int offset = object->map()->instance_size() + (index * kPointerSize); |
548 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); | 567 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); |
549 | 568 |
550 // Skip updating write barrier if storing a smi. | 569 if (!FLAG_track_fields || !representation.IsSmi()) { |
551 __ JumpIfSmi(value_reg, &exit); | 570 // Skip updating write barrier if storing a smi. |
| 571 __ JumpIfSmi(value_reg, &exit); |
552 | 572 |
553 // Update the write barrier for the array address. | 573 // Update the write barrier for the array address. |
554 // Pass the now unused name_reg as a scratch register. | 574 // Pass the now unused name_reg as a scratch register. |
555 __ mov(name_reg, value_reg); | 575 __ mov(name_reg, value_reg); |
556 __ RecordWriteField(receiver_reg, | 576 __ RecordWriteField(receiver_reg, |
557 offset, | 577 offset, |
558 name_reg, | 578 name_reg, |
559 scratch1, | 579 scratch1, |
560 kLRHasNotBeenSaved, | 580 kLRHasNotBeenSaved, |
561 kDontSaveFPRegs); | 581 kDontSaveFPRegs); |
| 582 } |
562 } else { | 583 } else { |
563 // Write to the properties array. | 584 // Write to the properties array. |
564 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 585 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
565 // Get the properties array | 586 // Get the properties array |
566 __ ldr(scratch1, | 587 __ ldr(scratch1, |
567 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 588 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
568 __ str(value_reg, FieldMemOperand(scratch1, offset)); | 589 __ str(value_reg, FieldMemOperand(scratch1, offset)); |
569 | 590 |
570 // Skip updating write barrier if storing a smi. | 591 if (!FLAG_track_fields || !representation.IsSmi()) { |
571 __ JumpIfSmi(value_reg, &exit); | 592 // Skip updating write barrier if storing a smi. |
| 593 __ JumpIfSmi(value_reg, &exit); |
572 | 594 |
573 // Update the write barrier for the array address. | 595 // Update the write barrier for the array address. |
574 // Ok to clobber receiver_reg and name_reg, since we return. | 596 // Ok to clobber receiver_reg and name_reg, since we return. |
575 __ mov(name_reg, value_reg); | 597 __ mov(name_reg, value_reg); |
576 __ RecordWriteField(scratch1, | 598 __ RecordWriteField(scratch1, |
577 offset, | 599 offset, |
578 name_reg, | 600 name_reg, |
579 receiver_reg, | 601 receiver_reg, |
580 kLRHasNotBeenSaved, | 602 kLRHasNotBeenSaved, |
581 kDontSaveFPRegs); | 603 kDontSaveFPRegs); |
| 604 } |
582 } | 605 } |
583 | 606 |
584 // Return the value (register r0). | 607 // Return the value (register r0). |
585 ASSERT(value_reg.is(r0)); | 608 ASSERT(value_reg.is(r0)); |
586 __ bind(&exit); | 609 __ bind(&exit); |
587 __ Ret(); | 610 __ Ret(); |
588 } | 611 } |
589 | 612 |
590 | 613 |
591 // Generate StoreField code, value is passed in r0 register. | 614 // Generate StoreField code, value is passed in r0 register. |
(...skipping 25 matching lines...) Expand all Loading... |
617 // checks. | 640 // checks. |
618 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 641 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
619 | 642 |
620 int index = lookup->GetFieldIndex().field_index(); | 643 int index = lookup->GetFieldIndex().field_index(); |
621 | 644 |
622 // Adjust for the number of properties stored in the object. Even in the | 645 // Adjust for the number of properties stored in the object. Even in the |
623 // face of a transition we can use the old map here because the size of the | 646 // face of a transition we can use the old map here because the size of the |
624 // object and the number of in-object properties is not going to change. | 647 // object and the number of in-object properties is not going to change. |
625 index -= object->map()->inobject_properties(); | 648 index -= object->map()->inobject_properties(); |
626 | 649 |
| 650 Representation representation = lookup->representation(); |
| 651 ASSERT(!representation.IsNone()); |
| 652 if (FLAG_track_fields && representation.IsSmi()) { |
| 653 __ JumpIfNotSmi(value_reg, miss_label); |
| 654 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 655 Label do_store; |
| 656 __ JumpIfSmi(value_reg, &do_store); |
| 657 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
| 658 miss_label, DONT_DO_SMI_CHECK); |
| 659 __ bind(&do_store); |
| 660 } |
| 661 |
627 // TODO(verwaest): Share this code as a code stub. | 662 // TODO(verwaest): Share this code as a code stub. |
628 if (index < 0) { | 663 if (index < 0) { |
629 // Set the property straight into the object. | 664 // Set the property straight into the object. |
630 int offset = object->map()->instance_size() + (index * kPointerSize); | 665 int offset = object->map()->instance_size() + (index * kPointerSize); |
631 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); | 666 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); |
632 | 667 |
633 // Skip updating write barrier if storing a smi. | 668 if (!FLAG_track_fields || !representation.IsSmi()) { |
634 __ JumpIfSmi(value_reg, &exit); | 669 // Skip updating write barrier if storing a smi. |
| 670 __ JumpIfSmi(value_reg, &exit); |
635 | 671 |
636 // Update the write barrier for the array address. | 672 // Update the write barrier for the array address. |
637 // Pass the now unused name_reg as a scratch register. | 673 // Pass the now unused name_reg as a scratch register. |
638 __ mov(name_reg, value_reg); | 674 __ mov(name_reg, value_reg); |
639 __ RecordWriteField(receiver_reg, | 675 __ RecordWriteField(receiver_reg, |
640 offset, | 676 offset, |
641 name_reg, | 677 name_reg, |
642 scratch1, | 678 scratch1, |
643 kLRHasNotBeenSaved, | 679 kLRHasNotBeenSaved, |
644 kDontSaveFPRegs); | 680 kDontSaveFPRegs); |
| 681 } |
645 } else { | 682 } else { |
646 // Write to the properties array. | 683 // Write to the properties array. |
647 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 684 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
648 // Get the properties array | 685 // Get the properties array |
649 __ ldr(scratch1, | 686 __ ldr(scratch1, |
650 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 687 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
651 __ str(value_reg, FieldMemOperand(scratch1, offset)); | 688 __ str(value_reg, FieldMemOperand(scratch1, offset)); |
652 | 689 |
653 // Skip updating write barrier if storing a smi. | 690 if (!FLAG_track_fields || !representation.IsSmi()) { |
654 __ JumpIfSmi(value_reg, &exit); | 691 // Skip updating write barrier if storing a smi. |
| 692 __ JumpIfSmi(value_reg, &exit); |
655 | 693 |
656 // Update the write barrier for the array address. | 694 // Update the write barrier for the array address. |
657 // Ok to clobber receiver_reg and name_reg, since we return. | 695 // Ok to clobber receiver_reg and name_reg, since we return. |
658 __ mov(name_reg, value_reg); | 696 __ mov(name_reg, value_reg); |
659 __ RecordWriteField(scratch1, | 697 __ RecordWriteField(scratch1, |
660 offset, | 698 offset, |
661 name_reg, | 699 name_reg, |
662 receiver_reg, | 700 receiver_reg, |
663 kLRHasNotBeenSaved, | 701 kLRHasNotBeenSaved, |
664 kDontSaveFPRegs); | 702 kDontSaveFPRegs); |
| 703 } |
665 } | 704 } |
666 | 705 |
667 // Return the value (register r0). | 706 // Return the value (register r0). |
668 ASSERT(value_reg.is(r0)); | 707 ASSERT(value_reg.is(r0)); |
669 __ bind(&exit); | 708 __ bind(&exit); |
670 __ Ret(); | 709 __ Ret(); |
671 } | 710 } |
672 | 711 |
673 | 712 |
674 void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 713 void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
(...skipping 2228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2903 Label miss; | 2942 Label miss; |
2904 | 2943 |
2905 if (check == PROPERTY) { | 2944 if (check == PROPERTY) { |
2906 GenerateNameCheck(name, this->name(), &miss); | 2945 GenerateNameCheck(name, this->name(), &miss); |
2907 } | 2946 } |
2908 | 2947 |
2909 __ JumpIfSmi(receiver(), &miss); | 2948 __ JumpIfSmi(receiver(), &miss); |
2910 Register map_reg = scratch1(); | 2949 Register map_reg = scratch1(); |
2911 | 2950 |
2912 int receiver_count = receiver_maps->length(); | 2951 int receiver_count = receiver_maps->length(); |
| 2952 int number_of_handled_maps = 0; |
2913 __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 2953 __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
2914 for (int current = 0; current < receiver_count; ++current) { | 2954 for (int current = 0; current < receiver_count; ++current) { |
2915 __ mov(ip, Operand(receiver_maps->at(current))); | 2955 Handle<Map> map = receiver_maps->at(current); |
2916 __ cmp(map_reg, ip); | 2956 if (!map->is_deprecated()) { |
2917 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq); | 2957 number_of_handled_maps++; |
| 2958 __ mov(ip, Operand(receiver_maps->at(current))); |
| 2959 __ cmp(map_reg, ip); |
| 2960 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq); |
| 2961 } |
2918 } | 2962 } |
| 2963 ASSERT(number_of_handled_maps != 0); |
2919 | 2964 |
2920 __ bind(&miss); | 2965 __ bind(&miss); |
2921 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2966 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2922 | 2967 |
2923 // Return the generated code. | 2968 // Return the generated code. |
2924 InlineCacheState state = | 2969 InlineCacheState state = |
2925 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; | 2970 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
2926 return GetICCode(kind(), type, name, state); | 2971 return GetICCode(kind(), type, name, state); |
2927 } | 2972 } |
2928 | 2973 |
2929 | 2974 |
2930 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 2975 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
2931 MapHandleList* receiver_maps, | 2976 MapHandleList* receiver_maps, |
2932 CodeHandleList* handler_stubs, | 2977 CodeHandleList* handler_stubs, |
2933 MapHandleList* transitioned_maps) { | 2978 MapHandleList* transitioned_maps) { |
2934 Label miss; | 2979 Label miss; |
2935 __ JumpIfSmi(receiver(), &miss); | 2980 __ JumpIfSmi(receiver(), &miss); |
(...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3684 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3729 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3685 } | 3730 } |
3686 } | 3731 } |
3687 | 3732 |
3688 | 3733 |
3689 #undef __ | 3734 #undef __ |
3690 | 3735 |
3691 } } // namespace v8::internal | 3736 } } // namespace v8::internal |
3692 | 3737 |
3693 #endif // V8_TARGET_ARCH_ARM | 3738 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |