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 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 | 449 |
450 // Check that the map of the object hasn't changed. | 450 // Check that the map of the object hasn't changed. |
451 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label, | 451 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label, |
452 DO_SMI_CHECK, REQUIRE_EXACT_MAP); | 452 DO_SMI_CHECK, REQUIRE_EXACT_MAP); |
453 | 453 |
454 // Perform global security token check if needed. | 454 // Perform global security token check if needed. |
455 if (object->IsJSGlobalProxy()) { | 455 if (object->IsJSGlobalProxy()) { |
456 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); | 456 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); |
457 } | 457 } |
458 | 458 |
| 459 int descriptor = transition->LastAdded(); |
| 460 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 461 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 462 Representation representation = details.representation(); |
| 463 ASSERT(!representation.IsNone()); |
| 464 |
| 465 // Ensure no transitions to deprecated maps are followed. |
| 466 __ CheckMapDeprecated(transition, scratch1, miss_label); |
| 467 |
| 468 if (FLAG_track_fields && representation.IsSmi()) { |
| 469 __ JumpIfNotSmi(value_reg, miss_label); |
| 470 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 471 Label do_store; |
| 472 __ JumpIfSmi(value_reg, &do_store); |
| 473 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
| 474 miss_label, DONT_DO_SMI_CHECK); |
| 475 __ bind(&do_store); |
| 476 } |
| 477 |
459 // Check that we are allowed to write this. | 478 // Check that we are allowed to write this. |
460 if (object->GetPrototype()->IsJSObject()) { | 479 if (object->GetPrototype()->IsJSObject()) { |
461 JSObject* holder; | 480 JSObject* holder; |
462 // holder == object indicates that no property was found. | 481 // holder == object indicates that no property was found. |
463 if (lookup->holder() != *object) { | 482 if (lookup->holder() != *object) { |
464 holder = lookup->holder(); | 483 holder = lookup->holder(); |
465 } else { | 484 } else { |
466 // Find the top object. | 485 // Find the top object. |
467 holder = *object; | 486 holder = *object; |
468 do { | 487 do { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 // face of a transition we can use the old map here because the size of the | 549 // face of a transition we can use the old map here because the size of the |
531 // object and the number of in-object properties is not going to change. | 550 // object and the number of in-object properties is not going to change. |
532 index -= object->map()->inobject_properties(); | 551 index -= object->map()->inobject_properties(); |
533 | 552 |
534 // TODO(verwaest): Share this code as a code stub. | 553 // TODO(verwaest): Share this code as a code stub. |
535 if (index < 0) { | 554 if (index < 0) { |
536 // Set the property straight into the object. | 555 // Set the property straight into the object. |
537 int offset = object->map()->instance_size() + (index * kPointerSize); | 556 int offset = object->map()->instance_size() + (index * kPointerSize); |
538 __ sw(value_reg, FieldMemOperand(receiver_reg, offset)); | 557 __ sw(value_reg, FieldMemOperand(receiver_reg, offset)); |
539 | 558 |
540 // Skip updating write barrier if storing a smi. | 559 if (!FLAG_track_fields || !representation.IsSmi()) { |
541 __ JumpIfSmi(value_reg, &exit); | 560 // Skip updating write barrier if storing a smi. |
| 561 __ JumpIfSmi(value_reg, &exit); |
542 | 562 |
543 // Update the write barrier for the array address. | 563 // Update the write barrier for the array address. |
544 // Pass the now unused name_reg as a scratch register. | 564 // Pass the now unused name_reg as a scratch register. |
545 __ mov(name_reg, value_reg); | 565 __ mov(name_reg, value_reg); |
546 __ RecordWriteField(receiver_reg, | 566 __ RecordWriteField(receiver_reg, |
547 offset, | 567 offset, |
548 name_reg, | 568 name_reg, |
549 scratch1, | 569 scratch1, |
550 kRAHasNotBeenSaved, | 570 kRAHasNotBeenSaved, |
551 kDontSaveFPRegs); | 571 kDontSaveFPRegs); |
| 572 } |
552 } else { | 573 } else { |
553 // Write to the properties array. | 574 // Write to the properties array. |
554 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 575 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
555 // Get the properties array | 576 // Get the properties array |
556 __ lw(scratch1, | 577 __ lw(scratch1, |
557 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 578 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
558 __ sw(value_reg, FieldMemOperand(scratch1, offset)); | 579 __ sw(value_reg, FieldMemOperand(scratch1, offset)); |
559 | 580 |
560 // Skip updating write barrier if storing a smi. | 581 if (!FLAG_track_fields || !representation.IsSmi()) { |
561 __ JumpIfSmi(value_reg, &exit); | 582 // Skip updating write barrier if storing a smi. |
| 583 __ JumpIfSmi(value_reg, &exit); |
562 | 584 |
563 // Update the write barrier for the array address. | 585 // Update the write barrier for the array address. |
564 // Ok to clobber receiver_reg and name_reg, since we return. | 586 // Ok to clobber receiver_reg and name_reg, since we return. |
565 __ mov(name_reg, value_reg); | 587 __ mov(name_reg, value_reg); |
566 __ RecordWriteField(scratch1, | 588 __ RecordWriteField(scratch1, |
567 offset, | 589 offset, |
568 name_reg, | 590 name_reg, |
569 receiver_reg, | 591 receiver_reg, |
570 kRAHasNotBeenSaved, | 592 kRAHasNotBeenSaved, |
571 kDontSaveFPRegs); | 593 kDontSaveFPRegs); |
| 594 } |
572 } | 595 } |
573 | 596 |
574 // Return the value (register v0). | 597 // Return the value (register v0). |
575 ASSERT(value_reg.is(a0)); | 598 ASSERT(value_reg.is(a0)); |
576 __ bind(&exit); | 599 __ bind(&exit); |
577 __ mov(v0, a0); | 600 __ mov(v0, a0); |
578 __ Ret(); | 601 __ Ret(); |
579 } | 602 } |
580 | 603 |
581 | 604 |
(...skipping 26 matching lines...) Expand all Loading... |
608 // checks. | 631 // checks. |
609 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 632 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
610 | 633 |
611 int index = lookup->GetFieldIndex().field_index(); | 634 int index = lookup->GetFieldIndex().field_index(); |
612 | 635 |
613 // Adjust for the number of properties stored in the object. Even in the | 636 // Adjust for the number of properties stored in the object. Even in the |
614 // face of a transition we can use the old map here because the size of the | 637 // face of a transition we can use the old map here because the size of the |
615 // object and the number of in-object properties is not going to change. | 638 // object and the number of in-object properties is not going to change. |
616 index -= object->map()->inobject_properties(); | 639 index -= object->map()->inobject_properties(); |
617 | 640 |
| 641 Representation representation = lookup->representation(); |
| 642 ASSERT(!representation.IsNone()); |
| 643 if (FLAG_track_fields && representation.IsSmi()) { |
| 644 __ JumpIfNotSmi(value_reg, miss_label); |
| 645 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 646 Label do_store; |
| 647 __ JumpIfSmi(value_reg, &do_store); |
| 648 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
| 649 miss_label, DONT_DO_SMI_CHECK); |
| 650 __ bind(&do_store); |
| 651 } |
| 652 |
618 // TODO(verwaest): Share this code as a code stub. | 653 // TODO(verwaest): Share this code as a code stub. |
619 if (index < 0) { | 654 if (index < 0) { |
620 // Set the property straight into the object. | 655 // Set the property straight into the object. |
621 int offset = object->map()->instance_size() + (index * kPointerSize); | 656 int offset = object->map()->instance_size() + (index * kPointerSize); |
622 __ sw(value_reg, FieldMemOperand(receiver_reg, offset)); | 657 __ sw(value_reg, FieldMemOperand(receiver_reg, offset)); |
623 | 658 |
624 // Skip updating write barrier if storing a smi. | 659 if (!FLAG_track_fields || !representation.IsSmi()) { |
625 __ JumpIfSmi(value_reg, &exit); | 660 // Skip updating write barrier if storing a smi. |
| 661 __ JumpIfSmi(value_reg, &exit); |
626 | 662 |
627 // Update the write barrier for the array address. | 663 // Update the write barrier for the array address. |
628 // Pass the now unused name_reg as a scratch register. | 664 // Pass the now unused name_reg as a scratch register. |
629 __ mov(name_reg, value_reg); | 665 __ mov(name_reg, value_reg); |
630 __ RecordWriteField(receiver_reg, | 666 __ RecordWriteField(receiver_reg, |
631 offset, | 667 offset, |
632 name_reg, | 668 name_reg, |
633 scratch1, | 669 scratch1, |
634 kRAHasNotBeenSaved, | 670 kRAHasNotBeenSaved, |
635 kDontSaveFPRegs); | 671 kDontSaveFPRegs); |
| 672 } |
636 } else { | 673 } else { |
637 // Write to the properties array. | 674 // Write to the properties array. |
638 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 675 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
639 // Get the properties array. | 676 // Get the properties array. |
640 __ lw(scratch1, | 677 __ lw(scratch1, |
641 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 678 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
642 __ sw(value_reg, FieldMemOperand(scratch1, offset)); | 679 __ sw(value_reg, FieldMemOperand(scratch1, offset)); |
643 | 680 |
644 // Skip updating write barrier if storing a smi. | 681 if (!FLAG_track_fields || !representation.IsSmi()) { |
645 __ JumpIfSmi(value_reg, &exit); | 682 // Skip updating write barrier if storing a smi. |
| 683 __ JumpIfSmi(value_reg, &exit); |
646 | 684 |
647 // Update the write barrier for the array address. | 685 // Update the write barrier for the array address. |
648 // Ok to clobber receiver_reg and name_reg, since we return. | 686 // Ok to clobber receiver_reg and name_reg, since we return. |
649 __ mov(name_reg, value_reg); | 687 __ mov(name_reg, value_reg); |
650 __ RecordWriteField(scratch1, | 688 __ RecordWriteField(scratch1, |
651 offset, | 689 offset, |
652 name_reg, | 690 name_reg, |
653 receiver_reg, | 691 receiver_reg, |
654 kRAHasNotBeenSaved, | 692 kRAHasNotBeenSaved, |
655 kDontSaveFPRegs); | 693 kDontSaveFPRegs); |
| 694 } |
656 } | 695 } |
657 | 696 |
658 // Return the value (register v0). | 697 // Return the value (register v0). |
659 ASSERT(value_reg.is(a0)); | 698 ASSERT(value_reg.is(a0)); |
660 __ bind(&exit); | 699 __ bind(&exit); |
661 __ mov(v0, a0); | 700 __ mov(v0, a0); |
662 __ Ret(); | 701 __ Ret(); |
663 } | 702 } |
664 | 703 |
665 | 704 |
(...skipping 2262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2928 Label miss; | 2967 Label miss; |
2929 | 2968 |
2930 if (check == PROPERTY) { | 2969 if (check == PROPERTY) { |
2931 GenerateNameCheck(name, this->name(), &miss); | 2970 GenerateNameCheck(name, this->name(), &miss); |
2932 } | 2971 } |
2933 | 2972 |
2934 __ JumpIfSmi(receiver(), &miss); | 2973 __ JumpIfSmi(receiver(), &miss); |
2935 Register map_reg = scratch1(); | 2974 Register map_reg = scratch1(); |
2936 | 2975 |
2937 int receiver_count = receiver_maps->length(); | 2976 int receiver_count = receiver_maps->length(); |
| 2977 int number_of_handled_maps = 0; |
2938 __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 2978 __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
2939 for (int current = 0; current < receiver_count; ++current) { | 2979 for (int current = 0; current < receiver_count; ++current) { |
2940 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, | 2980 Handle<Map> map = receiver_maps->at(current); |
2941 eq, map_reg, Operand(receiver_maps->at(current))); | 2981 if (!map->is_deprecated()) { |
| 2982 number_of_handled_maps++; |
| 2983 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, |
| 2984 eq, map_reg, Operand(receiver_maps->at(current))); |
| 2985 } |
2942 } | 2986 } |
| 2987 ASSERT(number_of_handled_maps != 0); |
2943 | 2988 |
2944 __ bind(&miss); | 2989 __ bind(&miss); |
2945 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2990 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2946 | 2991 |
2947 // Return the generated code. | 2992 // Return the generated code. |
2948 InlineCacheState state = | 2993 InlineCacheState state = |
2949 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; | 2994 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
2950 return GetICCode(kind(), type, name, state); | 2995 return GetICCode(kind(), type, name, state); |
2951 } | 2996 } |
2952 | 2997 |
2953 | 2998 |
2954 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 2999 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
2955 MapHandleList* receiver_maps, | 3000 MapHandleList* receiver_maps, |
2956 CodeHandleList* handler_stubs, | 3001 CodeHandleList* handler_stubs, |
2957 MapHandleList* transitioned_maps) { | 3002 MapHandleList* transitioned_maps) { |
2958 Label miss; | 3003 Label miss; |
2959 __ JumpIfSmi(receiver(), &miss); | 3004 __ JumpIfSmi(receiver(), &miss); |
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3742 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3787 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3743 } | 3788 } |
3744 } | 3789 } |
3745 | 3790 |
3746 | 3791 |
3747 #undef __ | 3792 #undef __ |
3748 | 3793 |
3749 } } // namespace v8::internal | 3794 } } // namespace v8::internal |
3750 | 3795 |
3751 #endif // V8_TARGET_ARCH_MIPS | 3796 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |