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