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/deoptimizer.h" | 5 #include "src/deoptimizer.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/ast/prettyprinter.h" | 10 #include "src/ast/prettyprinter.h" |
(...skipping 3596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3607 void TranslatedState::Prepare(bool has_adapted_arguments, | 3607 void TranslatedState::Prepare(bool has_adapted_arguments, |
3608 Address stack_frame_pointer) { | 3608 Address stack_frame_pointer) { |
3609 for (auto& frame : frames_) frame.Handlify(); | 3609 for (auto& frame : frames_) frame.Handlify(); |
3610 | 3610 |
3611 stack_frame_pointer_ = stack_frame_pointer; | 3611 stack_frame_pointer_ = stack_frame_pointer; |
3612 has_adapted_arguments_ = has_adapted_arguments; | 3612 has_adapted_arguments_ = has_adapted_arguments; |
3613 | 3613 |
3614 UpdateFromPreviouslyMaterializedObjects(); | 3614 UpdateFromPreviouslyMaterializedObjects(); |
3615 } | 3615 } |
3616 | 3616 |
| 3617 class TranslatedState::CapturedObjectMaterializer { |
| 3618 public: |
| 3619 CapturedObjectMaterializer(TranslatedState* state, int frame_index, |
| 3620 int field_count) |
| 3621 : state_(state), frame_index_(frame_index), field_count_(field_count) {} |
| 3622 |
| 3623 Handle<Object> FieldAt(int* value_index) { |
| 3624 CHECK(field_count_ > 0); |
| 3625 --field_count_; |
| 3626 return state_->MaterializeAt(frame_index_, value_index); |
| 3627 } |
| 3628 |
| 3629 ~CapturedObjectMaterializer() { CHECK_EQ(0, field_count_); } |
| 3630 |
| 3631 private: |
| 3632 TranslatedState* state_; |
| 3633 int frame_index_; |
| 3634 int field_count_; |
| 3635 }; |
| 3636 |
| 3637 Handle<Object> TranslatedState::MaterializeCapturedObjectAt( |
| 3638 TranslatedValue* slot, int frame_index, int* value_index) { |
| 3639 int length = slot->GetChildrenCount(); |
| 3640 |
| 3641 CapturedObjectMaterializer materializer(this, frame_index, length); |
| 3642 |
| 3643 Handle<Object> result; |
| 3644 if (slot->value_.ToHandle(&result)) { |
| 3645 // This has been previously materialized, return the previous value. |
| 3646 // We still need to skip all the nested objects. |
| 3647 for (int i = 0; i < length; i++) { |
| 3648 materializer.FieldAt(value_index); |
| 3649 } |
| 3650 |
| 3651 return result; |
| 3652 } |
| 3653 |
| 3654 Handle<Object> map_object = materializer.FieldAt(value_index); |
| 3655 Handle<Map> map = Map::GeneralizeAllFields(Handle<Map>::cast(map_object)); |
| 3656 switch (map->instance_type()) { |
| 3657 case MUTABLE_HEAP_NUMBER_TYPE: |
| 3658 case HEAP_NUMBER_TYPE: { |
| 3659 // Reuse the HeapNumber value directly as it is already properly |
| 3660 // tagged and skip materializing the HeapNumber explicitly. |
| 3661 Handle<Object> object = materializer.FieldAt(value_index); |
| 3662 slot->value_ = object; |
| 3663 // On 32-bit architectures, there is an extra slot there because |
| 3664 // the escape analysis calculates the number of slots as |
| 3665 // object-size/pointer-size. To account for this, we read out |
| 3666 // any extra slots. |
| 3667 for (int i = 0; i < length - 2; i++) { |
| 3668 materializer.FieldAt(value_index); |
| 3669 } |
| 3670 return object; |
| 3671 } |
| 3672 case JS_OBJECT_TYPE: |
| 3673 case JS_ERROR_TYPE: |
| 3674 case JS_ARGUMENTS_TYPE: { |
| 3675 Handle<JSObject> object = |
| 3676 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED); |
| 3677 slot->value_ = object; |
| 3678 Handle<Object> properties = materializer.FieldAt(value_index); |
| 3679 Handle<Object> elements = materializer.FieldAt(value_index); |
| 3680 object->set_properties(FixedArray::cast(*properties)); |
| 3681 object->set_elements(FixedArrayBase::cast(*elements)); |
| 3682 for (int i = 0; i < length - 3; ++i) { |
| 3683 Handle<Object> value = materializer.FieldAt(value_index); |
| 3684 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i); |
| 3685 object->FastPropertyAtPut(index, *value); |
| 3686 } |
| 3687 return object; |
| 3688 } |
| 3689 case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE: |
| 3690 case JS_FAST_ARRAY_KEY_ITERATOR_TYPE: |
| 3691 case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE: |
| 3692 case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3693 case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3694 case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3695 case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3696 case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3697 case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3698 case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3699 case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3700 case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3701 case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3702 case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3703 case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3704 case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3705 case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3706 case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3707 case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE: |
| 3708 case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE: |
| 3709 case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE: |
| 3710 case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE: |
| 3711 case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE: |
| 3712 case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE: |
| 3713 case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE: |
| 3714 case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE: |
| 3715 case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE: |
| 3716 case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE: |
| 3717 case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE: |
| 3718 case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE: |
| 3719 case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE: |
| 3720 case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE: |
| 3721 case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE: |
| 3722 case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE: |
| 3723 case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE: { |
| 3724 Handle<JSArrayIterator> object = Handle<JSArrayIterator>::cast( |
| 3725 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED)); |
| 3726 slot->value_ = object; |
| 3727 Handle<Object> properties = materializer.FieldAt(value_index); |
| 3728 Handle<Object> elements = materializer.FieldAt(value_index); |
| 3729 Handle<Object> iterated_object = materializer.FieldAt(value_index); |
| 3730 Handle<Object> next_index = materializer.FieldAt(value_index); |
| 3731 Handle<Object> iterated_object_map = materializer.FieldAt(value_index); |
| 3732 object->set_properties(FixedArray::cast(*properties)); |
| 3733 object->set_elements(FixedArrayBase::cast(*elements)); |
| 3734 object->set_object(*iterated_object); |
| 3735 object->set_index(*next_index); |
| 3736 object->set_object_map(*iterated_object_map); |
| 3737 return object; |
| 3738 } |
| 3739 case JS_ARRAY_TYPE: { |
| 3740 Handle<JSArray> object = Handle<JSArray>::cast( |
| 3741 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED)); |
| 3742 slot->value_ = object; |
| 3743 Handle<Object> properties = materializer.FieldAt(value_index); |
| 3744 Handle<Object> elements = materializer.FieldAt(value_index); |
| 3745 Handle<Object> length = materializer.FieldAt(value_index); |
| 3746 object->set_properties(FixedArray::cast(*properties)); |
| 3747 object->set_elements(FixedArrayBase::cast(*elements)); |
| 3748 object->set_length(*length); |
| 3749 return object; |
| 3750 } |
| 3751 case JS_FUNCTION_TYPE: { |
| 3752 Handle<SharedFunctionInfo> temporary_shared = |
| 3753 isolate_->factory()->NewSharedFunctionInfo( |
| 3754 isolate_->factory()->empty_string(), MaybeHandle<Code>(), false); |
| 3755 Handle<JSFunction> object = |
| 3756 isolate_->factory()->NewFunctionFromSharedFunctionInfo( |
| 3757 map, temporary_shared, isolate_->factory()->undefined_value(), |
| 3758 NOT_TENURED); |
| 3759 slot->value_ = object; |
| 3760 Handle<Object> properties = materializer.FieldAt(value_index); |
| 3761 Handle<Object> elements = materializer.FieldAt(value_index); |
| 3762 Handle<Object> prototype = materializer.FieldAt(value_index); |
| 3763 Handle<Object> shared = materializer.FieldAt(value_index); |
| 3764 Handle<Object> context = materializer.FieldAt(value_index); |
| 3765 Handle<Object> literals = materializer.FieldAt(value_index); |
| 3766 Handle<Object> entry = materializer.FieldAt(value_index); |
| 3767 Handle<Object> next_link = materializer.FieldAt(value_index); |
| 3768 object->ReplaceCode(*isolate_->builtins()->CompileLazy()); |
| 3769 object->set_map(*map); |
| 3770 object->set_properties(FixedArray::cast(*properties)); |
| 3771 object->set_elements(FixedArrayBase::cast(*elements)); |
| 3772 object->set_prototype_or_initial_map(*prototype); |
| 3773 object->set_shared(SharedFunctionInfo::cast(*shared)); |
| 3774 object->set_context(Context::cast(*context)); |
| 3775 object->set_literals(LiteralsArray::cast(*literals)); |
| 3776 CHECK(entry->IsNumber()); // Entry to compile lazy stub. |
| 3777 CHECK(next_link->IsUndefined(isolate_)); |
| 3778 return object; |
| 3779 } |
| 3780 case CONS_STRING_TYPE: { |
| 3781 Handle<ConsString> object = Handle<ConsString>::cast( |
| 3782 isolate_->factory() |
| 3783 ->NewConsString(isolate_->factory()->undefined_string(), |
| 3784 isolate_->factory()->undefined_string()) |
| 3785 .ToHandleChecked()); |
| 3786 slot->value_ = object; |
| 3787 Handle<Object> hash = materializer.FieldAt(value_index); |
| 3788 Handle<Object> length = materializer.FieldAt(value_index); |
| 3789 Handle<Object> first = materializer.FieldAt(value_index); |
| 3790 Handle<Object> second = materializer.FieldAt(value_index); |
| 3791 object->set_map(*map); |
| 3792 object->set_length(Smi::cast(*length)->value()); |
| 3793 object->set_first(String::cast(*first)); |
| 3794 object->set_second(String::cast(*second)); |
| 3795 CHECK(hash->IsNumber()); // The {Name::kEmptyHashField} value. |
| 3796 return object; |
| 3797 } |
| 3798 case CONTEXT_EXTENSION_TYPE: { |
| 3799 Handle<ContextExtension> object = |
| 3800 isolate_->factory()->NewContextExtension( |
| 3801 isolate_->factory()->NewScopeInfo(1), |
| 3802 isolate_->factory()->undefined_value()); |
| 3803 slot->value_ = object; |
| 3804 Handle<Object> scope_info = materializer.FieldAt(value_index); |
| 3805 Handle<Object> extension = materializer.FieldAt(value_index); |
| 3806 object->set_scope_info(ScopeInfo::cast(*scope_info)); |
| 3807 object->set_extension(*extension); |
| 3808 return object; |
| 3809 } |
| 3810 case FIXED_ARRAY_TYPE: { |
| 3811 Handle<Object> lengthObject = materializer.FieldAt(value_index); |
| 3812 int32_t length = 0; |
| 3813 CHECK(lengthObject->ToInt32(&length)); |
| 3814 Handle<FixedArray> object = isolate_->factory()->NewFixedArray(length); |
| 3815 // We need to set the map, because the fixed array we are |
| 3816 // materializing could be a context or an arguments object, |
| 3817 // in which case we must retain that information. |
| 3818 object->set_map(*map); |
| 3819 slot->value_ = object; |
| 3820 for (int i = 0; i < length; ++i) { |
| 3821 Handle<Object> value = materializer.FieldAt(value_index); |
| 3822 object->set(i, *value); |
| 3823 } |
| 3824 return object; |
| 3825 } |
| 3826 case FIXED_DOUBLE_ARRAY_TYPE: { |
| 3827 DCHECK_EQ(*map, isolate_->heap()->fixed_double_array_map()); |
| 3828 Handle<Object> lengthObject = materializer.FieldAt(value_index); |
| 3829 int32_t length = 0; |
| 3830 CHECK(lengthObject->ToInt32(&length)); |
| 3831 Handle<FixedArrayBase> object = |
| 3832 isolate_->factory()->NewFixedDoubleArray(length); |
| 3833 slot->value_ = object; |
| 3834 if (length > 0) { |
| 3835 Handle<FixedDoubleArray> double_array = |
| 3836 Handle<FixedDoubleArray>::cast(object); |
| 3837 for (int i = 0; i < length; ++i) { |
| 3838 Handle<Object> value = materializer.FieldAt(value_index); |
| 3839 CHECK(value->IsNumber()); |
| 3840 double_array->set(i, value->Number()); |
| 3841 } |
| 3842 } |
| 3843 return object; |
| 3844 } |
| 3845 case STRING_TYPE: |
| 3846 case ONE_BYTE_STRING_TYPE: |
| 3847 case CONS_ONE_BYTE_STRING_TYPE: |
| 3848 case SLICED_STRING_TYPE: |
| 3849 case SLICED_ONE_BYTE_STRING_TYPE: |
| 3850 case EXTERNAL_STRING_TYPE: |
| 3851 case EXTERNAL_ONE_BYTE_STRING_TYPE: |
| 3852 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: |
| 3853 case SHORT_EXTERNAL_STRING_TYPE: |
| 3854 case SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE: |
| 3855 case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: |
| 3856 case INTERNALIZED_STRING_TYPE: |
| 3857 case ONE_BYTE_INTERNALIZED_STRING_TYPE: |
| 3858 case EXTERNAL_INTERNALIZED_STRING_TYPE: |
| 3859 case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE: |
| 3860 case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: |
| 3861 case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE: |
| 3862 case SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE: |
| 3863 case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: |
| 3864 case SYMBOL_TYPE: |
| 3865 case ODDBALL_TYPE: |
| 3866 case SIMD128_VALUE_TYPE: |
| 3867 case JS_GLOBAL_OBJECT_TYPE: |
| 3868 case JS_GLOBAL_PROXY_TYPE: |
| 3869 case JS_API_OBJECT_TYPE: |
| 3870 case JS_SPECIAL_API_OBJECT_TYPE: |
| 3871 case JS_VALUE_TYPE: |
| 3872 case JS_MESSAGE_OBJECT_TYPE: |
| 3873 case JS_DATE_TYPE: |
| 3874 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 3875 case JS_GENERATOR_OBJECT_TYPE: |
| 3876 case JS_MODULE_NAMESPACE_TYPE: |
| 3877 case JS_ARRAY_BUFFER_TYPE: |
| 3878 case JS_REGEXP_TYPE: |
| 3879 case JS_TYPED_ARRAY_TYPE: |
| 3880 case JS_DATA_VIEW_TYPE: |
| 3881 case JS_SET_TYPE: |
| 3882 case JS_MAP_TYPE: |
| 3883 case JS_SET_ITERATOR_TYPE: |
| 3884 case JS_MAP_ITERATOR_TYPE: |
| 3885 case JS_STRING_ITERATOR_TYPE: |
| 3886 case JS_WEAK_MAP_TYPE: |
| 3887 case JS_WEAK_SET_TYPE: |
| 3888 case JS_PROMISE_CAPABILITY_TYPE: |
| 3889 case JS_PROMISE_TYPE: |
| 3890 case JS_BOUND_FUNCTION_TYPE: |
| 3891 case JS_PROXY_TYPE: |
| 3892 case MAP_TYPE: |
| 3893 case ALLOCATION_SITE_TYPE: |
| 3894 case ACCESSOR_INFO_TYPE: |
| 3895 case SHARED_FUNCTION_INFO_TYPE: |
| 3896 case FUNCTION_TEMPLATE_INFO_TYPE: |
| 3897 case ACCESSOR_PAIR_TYPE: |
| 3898 case BYTE_ARRAY_TYPE: |
| 3899 case BYTECODE_ARRAY_TYPE: |
| 3900 case TRANSITION_ARRAY_TYPE: |
| 3901 case FOREIGN_TYPE: |
| 3902 case SCRIPT_TYPE: |
| 3903 case CODE_TYPE: |
| 3904 case PROPERTY_CELL_TYPE: |
| 3905 case MODULE_TYPE: |
| 3906 case MODULE_INFO_ENTRY_TYPE: |
| 3907 case FREE_SPACE_TYPE: |
| 3908 #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 3909 case FIXED_##TYPE##_ARRAY_TYPE: |
| 3910 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE) |
| 3911 #undef FIXED_TYPED_ARRAY_CASE |
| 3912 case FILLER_TYPE: |
| 3913 case ACCESS_CHECK_INFO_TYPE: |
| 3914 case INTERCEPTOR_INFO_TYPE: |
| 3915 case CALL_HANDLER_INFO_TYPE: |
| 3916 case OBJECT_TEMPLATE_INFO_TYPE: |
| 3917 case ALLOCATION_MEMENTO_TYPE: |
| 3918 case TYPE_FEEDBACK_INFO_TYPE: |
| 3919 case ALIASED_ARGUMENTS_ENTRY_TYPE: |
| 3920 case BOX_TYPE: |
| 3921 case PROMISE_RESOLVE_THENABLE_JOB_INFO_TYPE: |
| 3922 case PROMISE_REACTION_JOB_INFO_TYPE: |
| 3923 case DEBUG_INFO_TYPE: |
| 3924 case BREAK_POINT_INFO_TYPE: |
| 3925 case CELL_TYPE: |
| 3926 case WEAK_CELL_TYPE: |
| 3927 case PROTOTYPE_INFO_TYPE: |
| 3928 case TUPLE2_TYPE: |
| 3929 case TUPLE3_TYPE: |
| 3930 case CONSTANT_ELEMENTS_PAIR_TYPE: |
| 3931 OFStream os(stderr); |
| 3932 os << "[couldn't handle instance type " << map->instance_type() << "]" |
| 3933 << std::endl; |
| 3934 UNREACHABLE(); |
| 3935 break; |
| 3936 } |
| 3937 UNREACHABLE(); |
| 3938 return Handle<Object>::null(); |
| 3939 } |
3617 | 3940 |
3618 Handle<Object> TranslatedState::MaterializeAt(int frame_index, | 3941 Handle<Object> TranslatedState::MaterializeAt(int frame_index, |
3619 int* value_index) { | 3942 int* value_index) { |
3620 CHECK_LT(static_cast<size_t>(frame_index), frames().size()); | 3943 CHECK_LT(static_cast<size_t>(frame_index), frames().size()); |
3621 TranslatedFrame* frame = &(frames_[frame_index]); | 3944 TranslatedFrame* frame = &(frames_[frame_index]); |
3622 CHECK_LT(static_cast<size_t>(*value_index), frame->values_.size()); | 3945 CHECK_LT(static_cast<size_t>(*value_index), frame->values_.size()); |
3623 | 3946 |
3624 TranslatedValue* slot = &(frame->values_[*value_index]); | 3947 TranslatedValue* slot = &(frame->values_[*value_index]); |
3625 (*value_index)++; | 3948 (*value_index)++; |
3626 | 3949 |
(...skipping 29 matching lines...) Expand all Loading... |
3656 arguments->set_elements(*array); | 3979 arguments->set_elements(*array); |
3657 for (int i = 0; i < length; ++i) { | 3980 for (int i = 0; i < length; ++i) { |
3658 Handle<Object> value = MaterializeAt(frame_index, value_index); | 3981 Handle<Object> value = MaterializeAt(frame_index, value_index); |
3659 array->set(i, *value); | 3982 array->set(i, *value); |
3660 } | 3983 } |
3661 } | 3984 } |
3662 slot->value_ = arguments; | 3985 slot->value_ = arguments; |
3663 return arguments; | 3986 return arguments; |
3664 } | 3987 } |
3665 case TranslatedValue::kCapturedObject: { | 3988 case TranslatedValue::kCapturedObject: { |
3666 int length = slot->GetChildrenCount(); | |
3667 | |
3668 class FieldMaterializer { | |
3669 public: | |
3670 FieldMaterializer(TranslatedState* state, int frame_index, | |
3671 int field_count) | |
3672 : state_(state), | |
3673 frame_index_(frame_index), | |
3674 field_count_(field_count) {} | |
3675 | |
3676 Handle<Object> At(int* value_index) { | |
3677 CHECK(field_count_ > 0); | |
3678 --field_count_; | |
3679 return state_->MaterializeAt(frame_index_, value_index); | |
3680 } | |
3681 | |
3682 ~FieldMaterializer() { CHECK_EQ(0, field_count_); } | |
3683 | |
3684 private: | |
3685 TranslatedState* state_; | |
3686 int frame_index_; | |
3687 int field_count_; | |
3688 }; | |
3689 FieldMaterializer materializer(this, frame_index, length); | |
3690 | |
3691 // The map must be a tagged object. | 3989 // The map must be a tagged object. |
3692 CHECK(frame->values_[*value_index].kind() == TranslatedValue::kTagged); | 3990 CHECK(frame->values_[*value_index].kind() == TranslatedValue::kTagged); |
3693 | 3991 CHECK(frame->values_[*value_index].GetValue()->IsMap()); |
3694 Handle<Object> result; | 3992 return MaterializeCapturedObjectAt(slot, frame_index, value_index); |
3695 if (slot->value_.ToHandle(&result)) { | |
3696 // This has been previously materialized, return the previous value. | |
3697 // We still need to skip all the nested objects. | |
3698 for (int i = 0; i < length; i++) { | |
3699 materializer.At(value_index); | |
3700 } | |
3701 | |
3702 return result; | |
3703 } | |
3704 | |
3705 Handle<Object> map_object = materializer.At(value_index); | |
3706 Handle<Map> map = Map::GeneralizeAllFields(Handle<Map>::cast(map_object)); | |
3707 switch (map->instance_type()) { | |
3708 case MUTABLE_HEAP_NUMBER_TYPE: | |
3709 case HEAP_NUMBER_TYPE: { | |
3710 // Reuse the HeapNumber value directly as it is already properly | |
3711 // tagged and skip materializing the HeapNumber explicitly. | |
3712 Handle<Object> object = materializer.At(value_index); | |
3713 slot->value_ = object; | |
3714 // On 32-bit architectures, there is an extra slot there because | |
3715 // the escape analysis calculates the number of slots as | |
3716 // object-size/pointer-size. To account for this, we read out | |
3717 // any extra slots. | |
3718 for (int i = 0; i < length - 2; i++) { | |
3719 materializer.At(value_index); | |
3720 } | |
3721 return object; | |
3722 } | |
3723 case JS_OBJECT_TYPE: | |
3724 case JS_ERROR_TYPE: | |
3725 case JS_ARGUMENTS_TYPE: { | |
3726 Handle<JSObject> object = | |
3727 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED); | |
3728 slot->value_ = object; | |
3729 Handle<Object> properties = materializer.At(value_index); | |
3730 Handle<Object> elements = materializer.At(value_index); | |
3731 object->set_properties(FixedArray::cast(*properties)); | |
3732 object->set_elements(FixedArrayBase::cast(*elements)); | |
3733 for (int i = 0; i < length - 3; ++i) { | |
3734 Handle<Object> value = materializer.At(value_index); | |
3735 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i); | |
3736 object->FastPropertyAtPut(index, *value); | |
3737 } | |
3738 return object; | |
3739 } | |
3740 case JS_ARRAY_TYPE: { | |
3741 Handle<JSArray> object = Handle<JSArray>::cast( | |
3742 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED)); | |
3743 slot->value_ = object; | |
3744 Handle<Object> properties = materializer.At(value_index); | |
3745 Handle<Object> elements = materializer.At(value_index); | |
3746 Handle<Object> length = materializer.At(value_index); | |
3747 object->set_properties(FixedArray::cast(*properties)); | |
3748 object->set_elements(FixedArrayBase::cast(*elements)); | |
3749 object->set_length(*length); | |
3750 return object; | |
3751 } | |
3752 case JS_FUNCTION_TYPE: { | |
3753 Handle<SharedFunctionInfo> temporary_shared = | |
3754 isolate_->factory()->NewSharedFunctionInfo( | |
3755 isolate_->factory()->empty_string(), MaybeHandle<Code>(), | |
3756 false); | |
3757 Handle<JSFunction> object = | |
3758 isolate_->factory()->NewFunctionFromSharedFunctionInfo( | |
3759 map, temporary_shared, isolate_->factory()->undefined_value(), | |
3760 NOT_TENURED); | |
3761 slot->value_ = object; | |
3762 Handle<Object> properties = materializer.At(value_index); | |
3763 Handle<Object> elements = materializer.At(value_index); | |
3764 Handle<Object> prototype = materializer.At(value_index); | |
3765 Handle<Object> shared = materializer.At(value_index); | |
3766 Handle<Object> context = materializer.At(value_index); | |
3767 Handle<Object> literals = materializer.At(value_index); | |
3768 Handle<Object> entry = materializer.At(value_index); | |
3769 Handle<Object> next_link = materializer.At(value_index); | |
3770 object->ReplaceCode(*isolate_->builtins()->CompileLazy()); | |
3771 object->set_map(*map); | |
3772 object->set_properties(FixedArray::cast(*properties)); | |
3773 object->set_elements(FixedArrayBase::cast(*elements)); | |
3774 object->set_prototype_or_initial_map(*prototype); | |
3775 object->set_shared(SharedFunctionInfo::cast(*shared)); | |
3776 object->set_context(Context::cast(*context)); | |
3777 object->set_literals(LiteralsArray::cast(*literals)); | |
3778 CHECK(entry->IsNumber()); // Entry to compile lazy stub. | |
3779 CHECK(next_link->IsUndefined(isolate_)); | |
3780 return object; | |
3781 } | |
3782 case CONS_STRING_TYPE: { | |
3783 Handle<ConsString> object = Handle<ConsString>::cast( | |
3784 isolate_->factory() | |
3785 ->NewConsString(isolate_->factory()->undefined_string(), | |
3786 isolate_->factory()->undefined_string()) | |
3787 .ToHandleChecked()); | |
3788 slot->value_ = object; | |
3789 Handle<Object> hash = materializer.At(value_index); | |
3790 Handle<Object> length = materializer.At(value_index); | |
3791 Handle<Object> first = materializer.At(value_index); | |
3792 Handle<Object> second = materializer.At(value_index); | |
3793 object->set_map(*map); | |
3794 object->set_length(Smi::cast(*length)->value()); | |
3795 object->set_first(String::cast(*first)); | |
3796 object->set_second(String::cast(*second)); | |
3797 CHECK(hash->IsNumber()); // The {Name::kEmptyHashField} value. | |
3798 return object; | |
3799 } | |
3800 case CONTEXT_EXTENSION_TYPE: { | |
3801 Handle<ContextExtension> object = | |
3802 isolate_->factory()->NewContextExtension( | |
3803 isolate_->factory()->NewScopeInfo(1), | |
3804 isolate_->factory()->undefined_value()); | |
3805 slot->value_ = object; | |
3806 Handle<Object> scope_info = materializer.At(value_index); | |
3807 Handle<Object> extension = materializer.At(value_index); | |
3808 object->set_scope_info(ScopeInfo::cast(*scope_info)); | |
3809 object->set_extension(*extension); | |
3810 return object; | |
3811 } | |
3812 case FIXED_ARRAY_TYPE: { | |
3813 Handle<Object> lengthObject = materializer.At(value_index); | |
3814 int32_t length = 0; | |
3815 CHECK(lengthObject->ToInt32(&length)); | |
3816 Handle<FixedArray> object = | |
3817 isolate_->factory()->NewFixedArray(length); | |
3818 // We need to set the map, because the fixed array we are | |
3819 // materializing could be a context or an arguments object, | |
3820 // in which case we must retain that information. | |
3821 object->set_map(*map); | |
3822 slot->value_ = object; | |
3823 for (int i = 0; i < length; ++i) { | |
3824 Handle<Object> value = materializer.At(value_index); | |
3825 object->set(i, *value); | |
3826 } | |
3827 return object; | |
3828 } | |
3829 case FIXED_DOUBLE_ARRAY_TYPE: { | |
3830 DCHECK_EQ(*map, isolate_->heap()->fixed_double_array_map()); | |
3831 Handle<Object> lengthObject = materializer.At(value_index); | |
3832 int32_t length = 0; | |
3833 CHECK(lengthObject->ToInt32(&length)); | |
3834 Handle<FixedArrayBase> object = | |
3835 isolate_->factory()->NewFixedDoubleArray(length); | |
3836 slot->value_ = object; | |
3837 if (length > 0) { | |
3838 Handle<FixedDoubleArray> double_array = | |
3839 Handle<FixedDoubleArray>::cast(object); | |
3840 for (int i = 0; i < length; ++i) { | |
3841 Handle<Object> value = materializer.At(value_index); | |
3842 CHECK(value->IsNumber()); | |
3843 double_array->set(i, value->Number()); | |
3844 } | |
3845 } | |
3846 return object; | |
3847 } | |
3848 default: | |
3849 PrintF(stderr, "[couldn't handle instance type %d]\n", | |
3850 map->instance_type()); | |
3851 FATAL("unreachable"); | |
3852 return Handle<Object>::null(); | |
3853 } | |
3854 UNREACHABLE(); | |
3855 break; | |
3856 } | 3993 } |
3857 | |
3858 case TranslatedValue::kDuplicatedObject: { | 3994 case TranslatedValue::kDuplicatedObject: { |
3859 int object_index = slot->object_index(); | 3995 int object_index = slot->object_index(); |
3860 TranslatedState::ObjectPosition pos = object_positions_[object_index]; | 3996 TranslatedState::ObjectPosition pos = object_positions_[object_index]; |
3861 | 3997 |
3862 // Make sure the duplicate is refering to a previous object. | 3998 // Make sure the duplicate is refering to a previous object. |
3863 CHECK(pos.frame_index_ < frame_index || | 3999 CHECK(pos.frame_index_ < frame_index || |
3864 (pos.frame_index_ == frame_index && | 4000 (pos.frame_index_ == frame_index && |
3865 pos.value_index_ < *value_index - 1)); | 4001 pos.value_index_ < *value_index - 1)); |
3866 | 4002 |
3867 Handle<Object> object = | 4003 Handle<Object> object = |
3868 frames_[pos.frame_index_].values_[pos.value_index_].GetValue(); | 4004 frames_[pos.frame_index_].values_[pos.value_index_].GetValue(); |
3869 | 4005 |
3870 // The object should have a (non-sentinel) value. | 4006 // The object should have a (non-sentinel) value. |
3871 CHECK(!object.is_null() && | 4007 CHECK(!object.is_null() && |
3872 !object.is_identical_to(isolate_->factory()->arguments_marker())); | 4008 !object.is_identical_to(isolate_->factory()->arguments_marker())); |
3873 | 4009 |
3874 slot->value_ = object; | 4010 slot->value_ = object; |
3875 return object; | 4011 return object; |
3876 } | 4012 } |
3877 | 4013 |
3878 case TranslatedValue::kInvalid: | 4014 case TranslatedValue::kInvalid: |
3879 UNREACHABLE(); | 4015 UNREACHABLE(); |
3880 break; | 4016 break; |
3881 } | 4017 } |
3882 | 4018 |
3883 FATAL("We should never get here - unexpected deopt slot kind."); | 4019 FATAL("We should never get here - unexpected deopt slot kind."); |
3884 return Handle<Object>::null(); | 4020 return Handle<Object>::null(); |
3885 } | 4021 } |
3886 | 4022 |
3887 | |
3888 Handle<Object> TranslatedState::MaterializeObjectAt(int object_index) { | 4023 Handle<Object> TranslatedState::MaterializeObjectAt(int object_index) { |
3889 CHECK_LT(static_cast<size_t>(object_index), object_positions_.size()); | 4024 CHECK_LT(static_cast<size_t>(object_index), object_positions_.size()); |
3890 TranslatedState::ObjectPosition pos = object_positions_[object_index]; | 4025 TranslatedState::ObjectPosition pos = object_positions_[object_index]; |
3891 return MaterializeAt(pos.frame_index_, &(pos.value_index_)); | 4026 return MaterializeAt(pos.frame_index_, &(pos.value_index_)); |
3892 } | 4027 } |
3893 | 4028 |
3894 | |
3895 bool TranslatedState::GetAdaptedArguments(Handle<JSObject>* result, | 4029 bool TranslatedState::GetAdaptedArguments(Handle<JSObject>* result, |
3896 int frame_index) { | 4030 int frame_index) { |
3897 if (frame_index == 0) { | 4031 if (frame_index == 0) { |
3898 // Top level frame -> we need to go to the parent frame on the stack. | 4032 // Top level frame -> we need to go to the parent frame on the stack. |
3899 if (!has_adapted_arguments_) return false; | 4033 if (!has_adapted_arguments_) return false; |
3900 | 4034 |
3901 // This is top level frame, so we need to go to the stack to get | 4035 // This is top level frame, so we need to go to the stack to get |
3902 // this function's argument. (Note that this relies on not inlining | 4036 // this function's argument. (Note that this relies on not inlining |
3903 // recursive functions!) | 4037 // recursive functions!) |
3904 Handle<JSFunction> function = | 4038 Handle<JSFunction> function = |
(...skipping 19 matching lines...) Expand all Loading... |
3924 Handle<Object> value = arg_iterator->GetValue(); | 4058 Handle<Object> value = arg_iterator->GetValue(); |
3925 array->set(i, *value); | 4059 array->set(i, *value); |
3926 arg_iterator++; | 4060 arg_iterator++; |
3927 } | 4061 } |
3928 CHECK(arg_iterator == previous_frame->end()); | 4062 CHECK(arg_iterator == previous_frame->end()); |
3929 *result = arguments; | 4063 *result = arguments; |
3930 return true; | 4064 return true; |
3931 } | 4065 } |
3932 } | 4066 } |
3933 | 4067 |
3934 | |
3935 TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex( | 4068 TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex( |
3936 int jsframe_index, int* args_count) { | 4069 int jsframe_index, int* args_count) { |
3937 for (size_t i = 0; i < frames_.size(); i++) { | 4070 for (size_t i = 0; i < frames_.size(); i++) { |
3938 if (frames_[i].kind() == TranslatedFrame::kFunction || | 4071 if (frames_[i].kind() == TranslatedFrame::kFunction || |
3939 frames_[i].kind() == TranslatedFrame::kInterpretedFunction) { | 4072 frames_[i].kind() == TranslatedFrame::kInterpretedFunction) { |
3940 if (jsframe_index > 0) { | 4073 if (jsframe_index > 0) { |
3941 jsframe_index--; | 4074 jsframe_index--; |
3942 } else { | 4075 } else { |
3943 // We have the JS function frame, now check if it has arguments adaptor. | 4076 // We have the JS function frame, now check if it has arguments |
| 4077 // adaptor. |
3944 if (i > 0 && | 4078 if (i > 0 && |
3945 frames_[i - 1].kind() == TranslatedFrame::kArgumentsAdaptor) { | 4079 frames_[i - 1].kind() == TranslatedFrame::kArgumentsAdaptor) { |
3946 *args_count = frames_[i - 1].height(); | 4080 *args_count = frames_[i - 1].height(); |
3947 return &(frames_[i - 1]); | 4081 return &(frames_[i - 1]); |
3948 } | 4082 } |
3949 *args_count = | 4083 *args_count = |
3950 frames_[i].shared_info()->internal_formal_parameter_count() + 1; | 4084 frames_[i].shared_info()->internal_formal_parameter_count() + 1; |
3951 return &(frames_[i]); | 4085 return &(frames_[i]); |
3952 } | 4086 } |
3953 } | 4087 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3999 materialized_store->Set(stack_frame_pointer_, | 4133 materialized_store->Set(stack_frame_pointer_, |
4000 previously_materialized_objects); | 4134 previously_materialized_objects); |
4001 CHECK(frames_[0].kind() == TranslatedFrame::kFunction || | 4135 CHECK(frames_[0].kind() == TranslatedFrame::kFunction || |
4002 frames_[0].kind() == TranslatedFrame::kInterpretedFunction || | 4136 frames_[0].kind() == TranslatedFrame::kInterpretedFunction || |
4003 frames_[0].kind() == TranslatedFrame::kTailCallerFunction); | 4137 frames_[0].kind() == TranslatedFrame::kTailCallerFunction); |
4004 CHECK_EQ(frame->function(), frames_[0].front().GetRawValue()); | 4138 CHECK_EQ(frame->function(), frames_[0].front().GetRawValue()); |
4005 Deoptimizer::DeoptimizeFunction(frame->function(), frame->LookupCode()); | 4139 Deoptimizer::DeoptimizeFunction(frame->function(), frame->LookupCode()); |
4006 } | 4140 } |
4007 } | 4141 } |
4008 | 4142 |
4009 | |
4010 void TranslatedState::UpdateFromPreviouslyMaterializedObjects() { | 4143 void TranslatedState::UpdateFromPreviouslyMaterializedObjects() { |
4011 MaterializedObjectStore* materialized_store = | 4144 MaterializedObjectStore* materialized_store = |
4012 isolate_->materialized_object_store(); | 4145 isolate_->materialized_object_store(); |
4013 Handle<FixedArray> previously_materialized_objects = | 4146 Handle<FixedArray> previously_materialized_objects = |
4014 materialized_store->Get(stack_frame_pointer_); | 4147 materialized_store->Get(stack_frame_pointer_); |
4015 | 4148 |
4016 // If we have no previously materialized objects, there is nothing to do. | 4149 // If we have no previously materialized objects, there is nothing to do. |
4017 if (previously_materialized_objects.is_null()) return; | 4150 if (previously_materialized_objects.is_null()) return; |
4018 | 4151 |
4019 Handle<Object> marker = isolate_->factory()->arguments_marker(); | 4152 Handle<Object> marker = isolate_->factory()->arguments_marker(); |
(...skipping 11 matching lines...) Expand all Loading... |
4031 CHECK(value_info->IsMaterializedObject()); | 4164 CHECK(value_info->IsMaterializedObject()); |
4032 | 4165 |
4033 value_info->value_ = | 4166 value_info->value_ = |
4034 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 4167 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
4035 } | 4168 } |
4036 } | 4169 } |
4037 } | 4170 } |
4038 | 4171 |
4039 } // namespace internal | 4172 } // namespace internal |
4040 } // namespace v8 | 4173 } // namespace v8 |
OLD | NEW |