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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/allocation-site-scopes.h" | 8 #include "src/allocation-site-scopes.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 return fun->IsJSFunction() || | 101 return fun->IsJSFunction() || |
102 (fun->IsHeapObject() && | 102 (fun->IsHeapObject() && |
103 HeapObject::cast(fun)->map()->has_instance_call_handler()); | 103 HeapObject::cast(fun)->map()->has_instance_call_handler()); |
104 } | 104 } |
105 | 105 |
106 | 106 |
107 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) { | 107 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) { |
108 for (; it->IsFound(); it->Next()) { | 108 for (; it->IsFound(); it->Next()) { |
109 switch (it->state()) { | 109 switch (it->state()) { |
110 case LookupIterator::NOT_FOUND: | 110 case LookupIterator::NOT_FOUND: |
| 111 case LookupIterator::TRANSITION: |
111 UNREACHABLE(); | 112 UNREACHABLE(); |
112 case LookupIterator::JSPROXY: | 113 case LookupIterator::JSPROXY: |
113 return JSProxy::GetPropertyWithHandler(it->GetHolder<JSProxy>(), | 114 return JSProxy::GetPropertyWithHandler(it->GetHolder<JSProxy>(), |
114 it->GetReceiver(), it->name()); | 115 it->GetReceiver(), it->name()); |
115 case LookupIterator::INTERCEPTOR: { | 116 case LookupIterator::INTERCEPTOR: { |
116 MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithInterceptor( | 117 MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithInterceptor( |
117 it->GetHolder<JSObject>(), it->GetReceiver(), it->name()); | 118 it->GetHolder<JSObject>(), it->GetReceiver(), it->name()); |
118 if (!maybe_result.is_null()) return maybe_result; | 119 if (!maybe_result.is_null()) return maybe_result; |
119 if (it->isolate()->has_pending_exception()) return maybe_result; | 120 if (it->isolate()->has_pending_exception()) return maybe_result; |
120 break; | 121 break; |
(...skipping 22 matching lines...) Expand all Loading... |
143 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object, | 144 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object, |
144 Handle<Name> key) { | 145 Handle<Name> key) { |
145 LookupIterator it(object, key, LookupIterator::CHECK_DERIVED_PROPERTY); | 146 LookupIterator it(object, key, LookupIterator::CHECK_DERIVED_PROPERTY); |
146 return GetDataProperty(&it); | 147 return GetDataProperty(&it); |
147 } | 148 } |
148 | 149 |
149 | 150 |
150 Handle<Object> JSObject::GetDataProperty(LookupIterator* it) { | 151 Handle<Object> JSObject::GetDataProperty(LookupIterator* it) { |
151 for (; it->IsFound(); it->Next()) { | 152 for (; it->IsFound(); it->Next()) { |
152 switch (it->state()) { | 153 switch (it->state()) { |
153 case LookupIterator::NOT_FOUND: | |
154 case LookupIterator::ACCESS_CHECK: | 154 case LookupIterator::ACCESS_CHECK: |
155 case LookupIterator::INTERCEPTOR: | 155 case LookupIterator::INTERCEPTOR: |
| 156 case LookupIterator::NOT_FOUND: |
| 157 case LookupIterator::TRANSITION: |
156 UNREACHABLE(); | 158 UNREACHABLE(); |
157 case LookupIterator::JSPROXY: | 159 case LookupIterator::JSPROXY: |
158 it->NotFound(); | 160 it->NotFound(); |
159 return it->isolate()->factory()->undefined_value(); | 161 return it->isolate()->factory()->undefined_value(); |
160 case LookupIterator::PROPERTY: | 162 case LookupIterator::PROPERTY: |
161 if (!it->HasProperty()) continue; | 163 if (!it->HasProperty()) continue; |
162 switch (it->property_kind()) { | 164 switch (it->property_kind()) { |
163 case LookupIterator::DATA: | 165 case LookupIterator::DATA: |
164 return it->GetDataValue(); | 166 return it->GetDataValue(); |
165 case LookupIterator::ACCESSOR: | 167 case LookupIterator::ACCESSOR: |
(...skipping 2541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2707 if (proto_map->is_deprecated() && JSObject::TryMigrateInstance(holder)) { | 2709 if (proto_map->is_deprecated() && JSObject::TryMigrateInstance(holder)) { |
2708 proto_map = Handle<Map>(holder->map()); | 2710 proto_map = Handle<Map>(holder->map()); |
2709 } | 2711 } |
2710 } | 2712 } |
2711 return TryUpdateInternal(map); | 2713 return TryUpdateInternal(map); |
2712 } | 2714 } |
2713 | 2715 |
2714 | 2716 |
2715 // static | 2717 // static |
2716 Handle<Map> Map::Update(Handle<Map> map) { | 2718 Handle<Map> Map::Update(Handle<Map> map) { |
| 2719 if (!map->is_deprecated()) return map; |
2717 return GeneralizeRepresentation(map, 0, Representation::None(), | 2720 return GeneralizeRepresentation(map, 0, Representation::None(), |
2718 HeapType::None(map->GetIsolate()), | 2721 HeapType::None(map->GetIsolate()), |
2719 ALLOW_AS_CONSTANT); | 2722 ALLOW_AS_CONSTANT); |
2720 } | 2723 } |
2721 | 2724 |
2722 | 2725 |
2723 // static | 2726 // static |
2724 MaybeHandle<Map> Map::TryUpdateInternal(Handle<Map> old_map) { | 2727 MaybeHandle<Map> Map::TryUpdateInternal(Handle<Map> old_map) { |
2725 DisallowHeapAllocation no_allocation; | 2728 DisallowHeapAllocation no_allocation; |
2726 DisallowDeoptimization no_deoptimization(old_map->GetIsolate()); | 2729 DisallowDeoptimization no_deoptimization(old_map->GetIsolate()); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2887 it->GetAccessors(), strict_mode); | 2890 it->GetAccessors(), strict_mode); |
2888 } | 2891 } |
2889 break; | 2892 break; |
2890 case LookupIterator::DATA: | 2893 case LookupIterator::DATA: |
2891 if (it->HolderIsReceiverOrHiddenPrototype()) { | 2894 if (it->HolderIsReceiverOrHiddenPrototype()) { |
2892 return SetDataProperty(it, value); | 2895 return SetDataProperty(it, value); |
2893 } | 2896 } |
2894 } | 2897 } |
2895 done = true; | 2898 done = true; |
2896 break; | 2899 break; |
| 2900 |
| 2901 case LookupIterator::TRANSITION: |
| 2902 done = true; |
| 2903 break; |
2897 } | 2904 } |
2898 | 2905 |
2899 if (done) break; | 2906 if (done) break; |
2900 } | 2907 } |
2901 | 2908 |
| 2909 // If the receiver is the JSGlobalObject, the store was contextual. In case |
| 2910 // the property did not exist yet on the global object itself, we have to |
| 2911 // throw a reference error in strict mode. |
| 2912 if (it->GetReceiver()->IsJSGlobalObject() && strict_mode == STRICT) { |
| 2913 Handle<Object> args[1] = {it->name()}; |
| 2914 Handle<Object> error = it->isolate()->factory()->NewReferenceError( |
| 2915 "not_defined", HandleVector(args, 1)); |
| 2916 return it->isolate()->Throw<Object>(error); |
| 2917 } |
| 2918 |
2902 return AddDataProperty(it, value, NONE, strict_mode, store_mode); | 2919 return AddDataProperty(it, value, NONE, strict_mode, store_mode); |
2903 } | 2920 } |
2904 | 2921 |
2905 | 2922 |
2906 MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it, | 2923 MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it, |
2907 Handle<Object> value, | 2924 Handle<Object> value, |
2908 StrictMode strict_mode) { | 2925 StrictMode strict_mode) { |
2909 if (strict_mode != STRICT) return value; | 2926 if (strict_mode != STRICT) return value; |
2910 | 2927 |
2911 Handle<Object> args[] = {it->name(), it->GetReceiver()}; | 2928 Handle<Object> args[] = {it->name(), it->GetReceiver()}; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2953 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, | 2970 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
2954 Handle<Object> value, | 2971 Handle<Object> value, |
2955 PropertyAttributes attributes, | 2972 PropertyAttributes attributes, |
2956 StrictMode strict_mode, | 2973 StrictMode strict_mode, |
2957 StoreFromKeyed store_mode) { | 2974 StoreFromKeyed store_mode) { |
2958 DCHECK(!it->GetReceiver()->IsJSProxy()); | 2975 DCHECK(!it->GetReceiver()->IsJSProxy()); |
2959 if (!it->GetReceiver()->IsJSObject()) { | 2976 if (!it->GetReceiver()->IsJSObject()) { |
2960 // TODO(verwaest): Throw a TypeError with a more specific message. | 2977 // TODO(verwaest): Throw a TypeError with a more specific message. |
2961 return WriteToReadOnlyProperty(it, value, strict_mode); | 2978 return WriteToReadOnlyProperty(it, value, strict_mode); |
2962 } | 2979 } |
2963 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 2980 |
| 2981 Handle<JSObject> receiver = it->GetStoreTarget(); |
2964 | 2982 |
2965 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) | 2983 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) |
2966 // instead. If the prototype is Null, the proxy is detached. | 2984 // instead. If the prototype is Null, the proxy is detached. |
2967 if (receiver->IsJSGlobalProxy()) { | 2985 if (receiver->IsJSGlobalProxy()) return value; |
2968 // Trying to assign to a detached proxy. | |
2969 PrototypeIterator iter(it->isolate(), receiver); | |
2970 if (iter.IsAtEnd()) return value; | |
2971 receiver = | |
2972 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
2973 } | |
2974 | 2986 |
2975 if (!it->name().is_identical_to(it->isolate()->factory()->hidden_string()) && | 2987 // Possibly migrate to the most up-to-date map that will be able to store |
2976 !receiver->map()->is_extensible()) { | 2988 // |value| under it->name() with |attributes|. |
| 2989 it->PrepareTransitionToDataProperty(value, attributes, store_mode); |
| 2990 if (it->state() != LookupIterator::TRANSITION) { |
2977 if (strict_mode == SLOPPY) return value; | 2991 if (strict_mode == SLOPPY) return value; |
2978 | 2992 |
2979 Handle<Object> args[1] = {it->name()}; | 2993 Handle<Object> args[1] = {it->name()}; |
2980 Handle<Object> error = it->factory()->NewTypeError( | 2994 Handle<Object> error = it->factory()->NewTypeError( |
2981 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); | 2995 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); |
2982 return it->isolate()->Throw<Object>(error); | 2996 return it->isolate()->Throw<Object>(error); |
2983 } | 2997 } |
2984 | 2998 it->ApplyTransitionToDataProperty(); |
2985 // Possibly migrate to the most up-to-date map that will be able to store | |
2986 // |value| under it->name() with |attributes|. | |
2987 it->TransitionToDataProperty(value, attributes, store_mode); | |
2988 | 2999 |
2989 // TODO(verwaest): Encapsulate dictionary handling better. | 3000 // TODO(verwaest): Encapsulate dictionary handling better. |
2990 if (receiver->map()->is_dictionary_map()) { | 3001 if (receiver->map()->is_dictionary_map()) { |
2991 // TODO(verwaest): Probably should ensure this is done beforehand. | 3002 // TODO(verwaest): Probably should ensure this is done beforehand. |
2992 it->InternalizeName(); | 3003 it->InternalizeName(); |
2993 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); | 3004 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); |
2994 } else { | 3005 } else { |
2995 // Write the property value. | 3006 // Write the property value. |
2996 it->WriteDataValue(value); | 3007 it->WriteDataValue(value); |
2997 } | 3008 } |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3372 } | 3383 } |
3373 | 3384 |
3374 | 3385 |
3375 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, | 3386 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, |
3376 ElementsKind to_kind) { | 3387 ElementsKind to_kind) { |
3377 Handle<Map> map(object->map()); | 3388 Handle<Map> map(object->map()); |
3378 return Map::TransitionElementsTo(map, to_kind); | 3389 return Map::TransitionElementsTo(map, to_kind); |
3379 } | 3390 } |
3380 | 3391 |
3381 | 3392 |
3382 void JSObject::LookupOwnRealNamedProperty(Handle<Name> name, | |
3383 LookupResult* result) { | |
3384 DisallowHeapAllocation no_gc; | |
3385 if (IsJSGlobalProxy()) { | |
3386 PrototypeIterator iter(GetIsolate(), this); | |
3387 if (iter.IsAtEnd()) return result->NotFound(); | |
3388 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); | |
3389 return JSObject::cast(iter.GetCurrent()) | |
3390 ->LookupOwnRealNamedProperty(name, result); | |
3391 } | |
3392 | |
3393 if (HasFastProperties()) { | |
3394 map()->LookupDescriptor(this, *name, result); | |
3395 // A property or a map transition was found. We return all of these result | |
3396 // types because LookupOwnRealNamedProperty is used when setting | |
3397 // properties where map transitions are handled. | |
3398 DCHECK(!result->IsFound() || | |
3399 (result->holder() == this && result->IsFastPropertyType())); | |
3400 return; | |
3401 } | |
3402 | |
3403 int entry = property_dictionary()->FindEntry(name); | |
3404 if (entry != NameDictionary::kNotFound) { | |
3405 Object* value = property_dictionary()->ValueAt(entry); | |
3406 if (IsGlobalObject()) { | |
3407 PropertyDetails d = property_dictionary()->DetailsAt(entry); | |
3408 if (d.IsDeleted() || PropertyCell::cast(value)->value()->IsTheHole()) { | |
3409 result->NotFound(); | |
3410 return; | |
3411 } | |
3412 value = PropertyCell::cast(value)->value(); | |
3413 } | |
3414 result->DictionaryResult(this, entry); | |
3415 return; | |
3416 } | |
3417 | |
3418 result->NotFound(); | |
3419 } | |
3420 | |
3421 | |
3422 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, | 3393 Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, |
3423 Handle<Name> name) { | 3394 Handle<Name> name) { |
3424 Isolate* isolate = proxy->GetIsolate(); | 3395 Isolate* isolate = proxy->GetIsolate(); |
3425 | 3396 |
3426 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3397 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
3427 if (name->IsSymbol()) return maybe(false); | 3398 if (name->IsSymbol()) return maybe(false); |
3428 | 3399 |
3429 Handle<Object> args[] = { name }; | 3400 Handle<Object> args[] = { name }; |
3430 Handle<Object> result; | 3401 Handle<Object> result; |
3431 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 3402 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3840 Handle<Object> value, | 3811 Handle<Object> value, |
3841 PropertyAttributes attributes, | 3812 PropertyAttributes attributes, |
3842 ExecutableAccessorInfoHandling handling) { | 3813 ExecutableAccessorInfoHandling handling) { |
3843 DCHECK(!value->IsTheHole()); | 3814 DCHECK(!value->IsTheHole()); |
3844 LookupIterator it(object, name, | 3815 LookupIterator it(object, name, |
3845 LookupIterator::CHECK_HIDDEN_SKIP_INTERCEPTOR); | 3816 LookupIterator::CHECK_HIDDEN_SKIP_INTERCEPTOR); |
3846 bool is_observed = object->map()->is_observed() && | 3817 bool is_observed = object->map()->is_observed() && |
3847 *name != it.isolate()->heap()->hidden_string(); | 3818 *name != it.isolate()->heap()->hidden_string(); |
3848 for (; it.IsFound(); it.Next()) { | 3819 for (; it.IsFound(); it.Next()) { |
3849 switch (it.state()) { | 3820 switch (it.state()) { |
| 3821 case LookupIterator::INTERCEPTOR: |
| 3822 case LookupIterator::JSPROXY: |
3850 case LookupIterator::NOT_FOUND: | 3823 case LookupIterator::NOT_FOUND: |
3851 case LookupIterator::JSPROXY: | 3824 case LookupIterator::TRANSITION: |
3852 case LookupIterator::INTERCEPTOR: | |
3853 UNREACHABLE(); | 3825 UNREACHABLE(); |
3854 | 3826 |
3855 case LookupIterator::ACCESS_CHECK: | 3827 case LookupIterator::ACCESS_CHECK: |
3856 if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) { | 3828 if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) { |
3857 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY); | 3829 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY); |
3858 } | 3830 } |
3859 break; | 3831 break; |
3860 | 3832 |
3861 case LookupIterator::PROPERTY: { | 3833 case LookupIterator::PROPERTY: { |
3862 if (!it.HasProperty()) break; | 3834 if (!it.HasProperty()) break; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4015 LookupIterator it(object, name, LookupIterator::CHECK_HIDDEN); | 3987 LookupIterator it(object, name, LookupIterator::CHECK_HIDDEN); |
4016 return GetPropertyAttributes(&it); | 3988 return GetPropertyAttributes(&it); |
4017 } | 3989 } |
4018 | 3990 |
4019 | 3991 |
4020 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes( | 3992 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes( |
4021 LookupIterator* it) { | 3993 LookupIterator* it) { |
4022 for (; it->IsFound(); it->Next()) { | 3994 for (; it->IsFound(); it->Next()) { |
4023 switch (it->state()) { | 3995 switch (it->state()) { |
4024 case LookupIterator::NOT_FOUND: | 3996 case LookupIterator::NOT_FOUND: |
| 3997 case LookupIterator::TRANSITION: |
4025 UNREACHABLE(); | 3998 UNREACHABLE(); |
4026 case LookupIterator::JSPROXY: | 3999 case LookupIterator::JSPROXY: |
4027 return JSProxy::GetPropertyAttributesWithHandler( | 4000 return JSProxy::GetPropertyAttributesWithHandler( |
4028 it->GetHolder<JSProxy>(), it->GetReceiver(), it->name()); | 4001 it->GetHolder<JSProxy>(), it->GetReceiver(), it->name()); |
4029 case LookupIterator::INTERCEPTOR: { | 4002 case LookupIterator::INTERCEPTOR: { |
4030 Maybe<PropertyAttributes> result = | 4003 Maybe<PropertyAttributes> result = |
4031 JSObject::GetPropertyAttributesWithInterceptor( | 4004 JSObject::GetPropertyAttributesWithInterceptor( |
4032 it->GetHolder<JSObject>(), it->GetReceiver(), it->name()); | 4005 it->GetHolder<JSObject>(), it->GetReceiver(), it->name()); |
4033 if (!result.has_value) return result; | 4006 if (!result.has_value) return result; |
4034 if (result.value != ABSENT) return result; | 4007 if (result.value != ABSENT) return result; |
(...skipping 919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4954 ? LookupIterator::CHECK_HIDDEN_SKIP_INTERCEPTOR | 4927 ? LookupIterator::CHECK_HIDDEN_SKIP_INTERCEPTOR |
4955 : LookupIterator::CHECK_HIDDEN; | 4928 : LookupIterator::CHECK_HIDDEN; |
4956 | 4929 |
4957 LookupIterator it(object, name, config); | 4930 LookupIterator it(object, name, config); |
4958 | 4931 |
4959 bool is_observed = object->map()->is_observed() && | 4932 bool is_observed = object->map()->is_observed() && |
4960 *name != it.isolate()->heap()->hidden_string(); | 4933 *name != it.isolate()->heap()->hidden_string(); |
4961 | 4934 |
4962 for (; it.IsFound(); it.Next()) { | 4935 for (; it.IsFound(); it.Next()) { |
4963 switch (it.state()) { | 4936 switch (it.state()) { |
| 4937 case LookupIterator::JSPROXY: |
4964 case LookupIterator::NOT_FOUND: | 4938 case LookupIterator::NOT_FOUND: |
4965 case LookupIterator::JSPROXY: | 4939 case LookupIterator::TRANSITION: |
4966 UNREACHABLE(); | 4940 UNREACHABLE(); |
4967 case LookupIterator::ACCESS_CHECK: | 4941 case LookupIterator::ACCESS_CHECK: |
4968 if (it.HasAccess(v8::ACCESS_DELETE)) break; | 4942 if (it.HasAccess(v8::ACCESS_DELETE)) break; |
4969 it.isolate()->ReportFailedAccessCheck(it.GetHolder<JSObject>(), | 4943 it.isolate()->ReportFailedAccessCheck(it.GetHolder<JSObject>(), |
4970 v8::ACCESS_DELETE); | 4944 v8::ACCESS_DELETE); |
4971 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it.isolate(), Object); | 4945 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it.isolate(), Object); |
4972 return it.isolate()->factory()->false_value(); | 4946 return it.isolate()->factory()->false_value(); |
4973 case LookupIterator::INTERCEPTOR: { | 4947 case LookupIterator::INTERCEPTOR: { |
4974 MaybeHandle<Object> maybe_result = | 4948 MaybeHandle<Object> maybe_result = |
4975 JSObject::DeletePropertyWithInterceptor(it.GetHolder<JSObject>(), | 4949 JSObject::DeletePropertyWithInterceptor(it.GetHolder<JSObject>(), |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5703 for (int i = 0; i < number_of_own_descriptors; i++) { | 5677 for (int i = 0; i < number_of_own_descriptors; i++) { |
5704 if (descs->GetType(i) == FIELD) { | 5678 if (descs->GetType(i) == FIELD) { |
5705 int current_index = descs->GetFieldIndex(i); | 5679 int current_index = descs->GetFieldIndex(i); |
5706 if (current_index > max_index) max_index = current_index; | 5680 if (current_index > max_index) max_index = current_index; |
5707 } | 5681 } |
5708 } | 5682 } |
5709 return max_index + 1; | 5683 return max_index + 1; |
5710 } | 5684 } |
5711 | 5685 |
5712 | 5686 |
5713 void JSReceiver::LookupOwn(Handle<Name> name, LookupResult* result) { | |
5714 DisallowHeapAllocation no_gc; | |
5715 DCHECK(name->IsName()); | |
5716 | |
5717 if (IsJSGlobalProxy()) { | |
5718 PrototypeIterator iter(GetIsolate(), this); | |
5719 if (iter.IsAtEnd()) return result->NotFound(); | |
5720 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); | |
5721 return JSReceiver::cast(iter.GetCurrent())->LookupOwn(name, result); | |
5722 } | |
5723 | |
5724 if (IsJSProxy()) { | |
5725 result->HandlerResult(JSProxy::cast(this)); | |
5726 return; | |
5727 } | |
5728 | |
5729 // Do not use inline caching if the object is a non-global object | |
5730 // that requires access checks. | |
5731 if (IsAccessCheckNeeded()) { | |
5732 result->DisallowCaching(); | |
5733 } | |
5734 | |
5735 JSObject* js_object = JSObject::cast(this); | |
5736 | |
5737 // Check for lookup interceptor except when bootstrapping. | |
5738 if (js_object->HasNamedInterceptor() && | |
5739 !GetIsolate()->bootstrapper()->IsActive()) { | |
5740 result->InterceptorResult(js_object); | |
5741 return; | |
5742 } | |
5743 | |
5744 js_object->LookupOwnRealNamedProperty(name, result); | |
5745 } | |
5746 | |
5747 | |
5748 void JSReceiver::Lookup(Handle<Name> name, LookupResult* result) { | |
5749 DisallowHeapAllocation no_gc; | |
5750 // Ecma-262 3rd 8.6.2.4 | |
5751 for (PrototypeIterator iter(GetIsolate(), this, | |
5752 PrototypeIterator::START_AT_RECEIVER); | |
5753 !iter.IsAtEnd(); iter.Advance()) { | |
5754 JSReceiver::cast(iter.GetCurrent())->LookupOwn(name, result); | |
5755 if (result->IsFound()) return; | |
5756 if (name->IsOwn()) { | |
5757 result->NotFound(); | |
5758 return; | |
5759 } | |
5760 } | |
5761 result->NotFound(); | |
5762 } | |
5763 | |
5764 | |
5765 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { | 5687 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { |
5766 int len = array->length(); | 5688 int len = array->length(); |
5767 for (int i = 0; i < len; i++) { | 5689 for (int i = 0; i < len; i++) { |
5768 Object* e = array->get(i); | 5690 Object* e = array->get(i); |
5769 if (!(e->IsString() || e->IsNumber())) return false; | 5691 if (!(e->IsString() || e->IsNumber())) return false; |
5770 } | 5692 } |
5771 return true; | 5693 return true; |
5772 } | 5694 } |
5773 | 5695 |
5774 | 5696 |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6390 isolate); | 6312 isolate); |
6391 } | 6313 } |
6392 } | 6314 } |
6393 } | 6315 } |
6394 } | 6316 } |
6395 } else { | 6317 } else { |
6396 LookupIterator it(object, name, | 6318 LookupIterator it(object, name, |
6397 LookupIterator::CHECK_DERIVED_SKIP_INTERCEPTOR); | 6319 LookupIterator::CHECK_DERIVED_SKIP_INTERCEPTOR); |
6398 for (; it.IsFound(); it.Next()) { | 6320 for (; it.IsFound(); it.Next()) { |
6399 switch (it.state()) { | 6321 switch (it.state()) { |
| 6322 case LookupIterator::INTERCEPTOR: |
6400 case LookupIterator::NOT_FOUND: | 6323 case LookupIterator::NOT_FOUND: |
6401 case LookupIterator::INTERCEPTOR: | 6324 case LookupIterator::TRANSITION: |
6402 UNREACHABLE(); | 6325 UNREACHABLE(); |
6403 | 6326 |
6404 case LookupIterator::ACCESS_CHECK: | 6327 case LookupIterator::ACCESS_CHECK: |
6405 if (it.HasAccess(v8::ACCESS_HAS)) continue; | 6328 if (it.HasAccess(v8::ACCESS_HAS)) continue; |
6406 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>(), | 6329 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>(), |
6407 v8::ACCESS_HAS); | 6330 v8::ACCESS_HAS); |
6408 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 6331 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
6409 return isolate->factory()->undefined_value(); | 6332 return isolate->factory()->undefined_value(); |
6410 | 6333 |
6411 case LookupIterator::JSPROXY: | 6334 case LookupIterator::JSPROXY: |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6828 return false; | 6751 return false; |
6829 } | 6752 } |
6830 | 6753 |
6831 | 6754 |
6832 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, | 6755 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, |
6833 Handle<Object> value) { | 6756 Handle<Object> value) { |
6834 // Dictionaries can store any property value. | 6757 // Dictionaries can store any property value. |
6835 if (map->is_dictionary_map()) return map; | 6758 if (map->is_dictionary_map()) return map; |
6836 | 6759 |
6837 // Migrate to the newest map before storing the property. | 6760 // Migrate to the newest map before storing the property. |
6838 if (map->is_deprecated()) map = Update(map); | 6761 map = Update(map); |
6839 | 6762 |
6840 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 6763 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
6841 | 6764 |
6842 if (descriptors->CanHoldValue(descriptor, *value)) return map; | 6765 if (descriptors->CanHoldValue(descriptor, *value)) return map; |
6843 | 6766 |
6844 Isolate* isolate = map->GetIsolate(); | 6767 Isolate* isolate = map->GetIsolate(); |
6845 Representation representation = value->OptimalRepresentation(); | 6768 Representation representation = value->OptimalRepresentation(); |
6846 Handle<HeapType> type = value->OptimalType(isolate, representation); | 6769 Handle<HeapType> type = value->OptimalType(isolate, representation); |
6847 | 6770 |
6848 return GeneralizeRepresentation(map, descriptor, representation, type, | 6771 return GeneralizeRepresentation(map, descriptor, representation, type, |
6849 FORCE_FIELD); | 6772 FORCE_FIELD); |
6850 } | 6773 } |
6851 | 6774 |
6852 | 6775 |
6853 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, | 6776 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
6854 Handle<Object> value, | 6777 Handle<Object> value, |
6855 PropertyAttributes attributes, | 6778 PropertyAttributes attributes, |
6856 StoreFromKeyed store_mode) { | 6779 StoreFromKeyed store_mode) { |
6857 // Dictionary maps can always have additional data properties. | 6780 // Dictionary maps can always have additional data properties. |
6858 if (map->is_dictionary_map()) return map; | 6781 if (map->is_dictionary_map()) return map; |
6859 | 6782 |
6860 // Migrate to the newest map before transitioning to the new property. | 6783 // Migrate to the newest map before storing the property. |
6861 if (map->is_deprecated()) map = Update(map); | 6784 map = Update(map); |
6862 | 6785 |
6863 int index = map->SearchTransition(*name); | 6786 int index = map->SearchTransition(*name); |
6864 if (index != TransitionArray::kNotFound) { | 6787 if (index != TransitionArray::kNotFound) { |
6865 Handle<Map> transition(map->GetTransition(index)); | 6788 Handle<Map> transition(map->GetTransition(index)); |
6866 int descriptor = transition->LastAdded(); | 6789 int descriptor = transition->LastAdded(); |
6867 | 6790 |
6868 // TODO(verwaest): Handle attributes better. | 6791 // TODO(verwaest): Handle attributes better. |
6869 DescriptorArray* descriptors = transition->instance_descriptors(); | 6792 DescriptorArray* descriptors = transition->instance_descriptors(); |
6870 if (descriptors->GetDetails(descriptor).attributes() != attributes) { | 6793 if (descriptors->GetDetails(descriptor).attributes() != attributes) { |
6871 return CopyGeneralizeAllRepresentations(transition, descriptor, | 6794 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES); |
6872 FORCE_FIELD, attributes, | |
6873 "attributes mismatch"); | |
6874 } | 6795 } |
6875 | 6796 |
6876 return Map::PrepareForDataProperty(transition, descriptor, value); | 6797 return Map::PrepareForDataProperty(transition, descriptor, value); |
6877 } | 6798 } |
6878 | 6799 |
6879 TransitionFlag flag = INSERT_TRANSITION; | 6800 TransitionFlag flag = INSERT_TRANSITION; |
6880 MaybeHandle<Map> maybe_map; | 6801 MaybeHandle<Map> maybe_map; |
6881 if (value->IsJSFunction()) { | 6802 if (value->IsJSFunction()) { |
6882 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); | 6803 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); |
6883 } else if (!map->TooManyFastProperties(store_mode)) { | 6804 } else if (!map->TooManyFastProperties(store_mode)) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6918 | 6839 |
6919 // Dictionary maps can always have additional data properties. | 6840 // Dictionary maps can always have additional data properties. |
6920 if (map->is_dictionary_map()) { | 6841 if (map->is_dictionary_map()) { |
6921 // For global objects, property cells are inlined. We need to change the | 6842 // For global objects, property cells are inlined. We need to change the |
6922 // map. | 6843 // map. |
6923 if (map->IsGlobalObjectMap()) return Copy(map); | 6844 if (map->IsGlobalObjectMap()) return Copy(map); |
6924 return map; | 6845 return map; |
6925 } | 6846 } |
6926 | 6847 |
6927 // Migrate to the newest map before transitioning to the new property. | 6848 // Migrate to the newest map before transitioning to the new property. |
6928 if (map->is_deprecated()) map = Update(map); | 6849 map = Update(map); |
6929 | 6850 |
6930 PropertyNormalizationMode mode = map->is_prototype_map() | 6851 PropertyNormalizationMode mode = map->is_prototype_map() |
6931 ? KEEP_INOBJECT_PROPERTIES | 6852 ? KEEP_INOBJECT_PROPERTIES |
6932 : CLEAR_INOBJECT_PROPERTIES; | 6853 : CLEAR_INOBJECT_PROPERTIES; |
6933 | 6854 |
6934 int index = map->SearchTransition(*name); | 6855 int index = map->SearchTransition(*name); |
6935 if (index != TransitionArray::kNotFound) { | 6856 if (index != TransitionArray::kNotFound) { |
6936 Handle<Map> transition(map->GetTransition(index)); | 6857 Handle<Map> transition(map->GetTransition(index)); |
6937 DescriptorArray* descriptors = transition->instance_descriptors(); | 6858 DescriptorArray* descriptors = transition->instance_descriptors(); |
6938 // Fast path, assume that we're modifying the last added descriptor. | 6859 // Fast path, assume that we're modifying the last added descriptor. |
(...skipping 9612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16551 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16472 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16552 static const char* error_messages_[] = { | 16473 static const char* error_messages_[] = { |
16553 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16474 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16554 }; | 16475 }; |
16555 #undef ERROR_MESSAGES_TEXTS | 16476 #undef ERROR_MESSAGES_TEXTS |
16556 return error_messages_[reason]; | 16477 return error_messages_[reason]; |
16557 } | 16478 } |
16558 | 16479 |
16559 | 16480 |
16560 } } // namespace v8::internal | 16481 } } // namespace v8::internal |
OLD | NEW |