Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Side by Side Diff: src/objects.cc

Issue 392243002: Reimplement SetProperty using the LookupIterator (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 if (getter->IsSpecFunction()) { 455 if (getter->IsSpecFunction()) {
456 // TODO(rossberg): nicer would be to cast to some JSCallable here... 456 // TODO(rossberg): nicer would be to cast to some JSCallable here...
457 return Object::GetPropertyWithDefinedGetter( 457 return Object::GetPropertyWithDefinedGetter(
458 receiver, Handle<JSReceiver>::cast(getter)); 458 receiver, Handle<JSReceiver>::cast(getter));
459 } 459 }
460 // Getter is not a function. 460 // Getter is not a function.
461 return isolate->factory()->undefined_value(); 461 return isolate->factory()->undefined_value();
462 } 462 }
463 463
464 464
465 MaybeHandle<Object> Object::SetPropertyWithCallback(Handle<Object> receiver, 465 MaybeHandle<Object> Object::SetPropertyWithAccessor(
466 Handle<Name> name, 466 Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
467 Handle<Object> value, 467 Handle<JSObject> holder, Handle<Object> structure, StrictMode strict_mode) {
468 Handle<JSObject> holder,
469 Handle<Object> structure,
470 StrictMode strict_mode) {
471 Isolate* isolate = name->GetIsolate(); 468 Isolate* isolate = name->GetIsolate();
472 469
473 // We should never get here to initialize a const with the hole 470 // We should never get here to initialize a const with the hole
474 // value since a const declaration would conflict with the setter. 471 // value since a const declaration would conflict with the setter.
475 ASSERT(!structure->IsForeign()); 472 ASSERT(!structure->IsForeign());
476 if (structure->IsExecutableAccessorInfo()) { 473 if (structure->IsExecutableAccessorInfo()) {
477 // api style callbacks 474 // api style callbacks
478 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure); 475 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure);
479 if (!data->IsCompatibleReceiver(*receiver)) { 476 if (!data->IsCompatibleReceiver(*receiver)) {
480 Handle<Object> args[2] = { name, receiver }; 477 Handle<Object> args[2] = { name, receiver };
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 PropertyAttributes JSObject::GetPropertyAttributesWithFailedAccessCheck( 595 PropertyAttributes JSObject::GetPropertyAttributesWithFailedAccessCheck(
599 LookupIterator* it) { 596 LookupIterator* it) {
600 Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder()); 597 Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder());
601 if (FindAllCanReadHolder(it)) return it->property_details().attributes(); 598 if (FindAllCanReadHolder(it)) return it->property_details().attributes();
602 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS); 599 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
603 // TODO(yangguo): Issue 3269, check for scheduled exception missing? 600 // TODO(yangguo): Issue 3269, check for scheduled exception missing?
604 return ABSENT; 601 return ABSENT;
605 } 602 }
606 603
607 604
608 static bool FindAllCanWriteHolder(LookupResult* result, 605 static bool FindAllCanWriteHolder(LookupIterator* it) {
609 Handle<Name> name, 606 it->skip_interceptor();
610 bool check_prototype) { 607 it->skip_access_check();
611 if (result->IsInterceptor()) { 608 for (; it->IsFound(); it->Next()) {
612 result->holder()->LookupOwnRealNamedProperty(name, result); 609 if (it->state() == LookupIterator::PROPERTY && it->HasProperty() &&
613 } 610 it->property_kind() == LookupIterator::ACCESSOR) {
614 611 Handle<Object> accessors = it->GetAccessors();
615 while (result->IsProperty()) { 612 if (accessors->IsAccessorInfo()) {
616 if (result->type() == CALLBACKS) { 613 if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
617 Object* callback_obj = result->GetCallbackObject();
618 if (callback_obj->IsAccessorInfo()) {
619 if (AccessorInfo::cast(callback_obj)->all_can_write()) return true;
620 } 614 }
621 } 615 }
622 if (!check_prototype) break;
623 result->holder()->LookupRealNamedPropertyInPrototypes(name, result);
624 } 616 }
625 return false; 617 return false;
626 } 618 }
627 619
628 620
629 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( 621 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
630 Handle<JSObject> object, 622 LookupIterator* it, Handle<Object> value, StrictMode strict_mode) {
631 LookupResult* result, 623 Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder());
632 Handle<Name> name, 624 if (FindAllCanWriteHolder(it)) {
633 Handle<Object> value, 625 return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
634 bool check_prototype, 626 it->GetHolder(), it->GetAccessors(),
635 StrictMode strict_mode) { 627 strict_mode);
636 if (check_prototype && !result->IsProperty()) {
637 object->LookupRealNamedPropertyInPrototypes(name, result);
638 } 628 }
639 629
640 if (FindAllCanWriteHolder(result, name, check_prototype)) { 630 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_SET);
641 Handle<JSObject> holder(result->holder()); 631 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
642 Handle<Object> callbacks(result->GetCallbackObject(), result->isolate());
643 return SetPropertyWithCallback(
644 object, name, value, holder, callbacks, strict_mode);
645 }
646
647 Isolate* isolate = object->GetIsolate();
648 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
649 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
650 return value; 632 return value;
651 } 633 }
652 634
653 635
654 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { 636 Object* JSObject::GetNormalizedProperty(const LookupResult* result) {
655 ASSERT(!HasFastProperties()); 637 ASSERT(!HasFastProperties());
656 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); 638 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
657 if (IsGlobalObject()) { 639 if (IsGlobalObject()) {
658 value = PropertyCell::cast(value)->value(); 640 value = PropertyCell::cast(value)->value();
659 } 641 }
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1828 Handle<Object> value, 1810 Handle<Object> value,
1829 PropertyAttributes attributes, 1811 PropertyAttributes attributes,
1830 StoreFromKeyed store_mode, 1812 StoreFromKeyed store_mode,
1831 TransitionFlag flag) { 1813 TransitionFlag flag) {
1832 ASSERT(!object->IsJSGlobalProxy()); 1814 ASSERT(!object->IsJSGlobalProxy());
1833 1815
1834 MaybeHandle<Map> maybe_map; 1816 MaybeHandle<Map> maybe_map;
1835 if (value->IsJSFunction()) { 1817 if (value->IsJSFunction()) {
1836 maybe_map = Map::CopyWithConstant( 1818 maybe_map = Map::CopyWithConstant(
1837 handle(object->map()), name, value, attributes, flag); 1819 handle(object->map()), name, value, attributes, flag);
1838 } else if (!object->TooManyFastProperties(store_mode)) { 1820 } else if (!object->map()->TooManyFastProperties(store_mode)) {
1839 Isolate* isolate = object->GetIsolate(); 1821 Isolate* isolate = object->GetIsolate();
1840 Representation representation = value->OptimalRepresentation(); 1822 Representation representation = value->OptimalRepresentation();
1841 maybe_map = Map::CopyWithField( 1823 maybe_map = Map::CopyWithField(
1842 handle(object->map(), isolate), name, 1824 handle(object->map(), isolate), name,
1843 value->OptimalType(isolate, representation), 1825 value->OptimalType(isolate, representation),
1844 attributes, representation, flag); 1826 attributes, representation, flag);
1845 } 1827 }
1846 1828
1847 Handle<Map> new_map; 1829 Handle<Map> new_map;
1848 if (!maybe_map.ToHandle(&new_map)) { 1830 if (!maybe_map.ToHandle(&new_map)) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1962 Handle<Object> args[] = { type, object, name, old_value }; 1944 Handle<Object> args[] = { type, object, name, old_value };
1963 int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4; 1945 int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
1964 1946
1965 Execution::Call(isolate, 1947 Execution::Call(isolate,
1966 Handle<JSFunction>(isolate->observers_notify_change()), 1948 Handle<JSFunction>(isolate->observers_notify_change()),
1967 isolate->factory()->undefined_value(), 1949 isolate->factory()->undefined_value(),
1968 argc, args).Assert(); 1950 argc, args).Assert();
1969 } 1951 }
1970 1952
1971 1953
1972 MaybeHandle<Object> JSObject::SetPropertyPostInterceptor(
1973 Handle<JSObject> object,
1974 Handle<Name> name,
1975 Handle<Object> value,
1976 StrictMode strict_mode) {
1977 // Check own property, ignore interceptor.
1978 Isolate* isolate = object->GetIsolate();
1979 LookupResult result(isolate);
1980 object->LookupOwnRealNamedProperty(name, &result);
1981 if (!result.IsFound()) {
1982 object->map()->LookupTransition(*object, *name, &result);
1983 }
1984 return SetPropertyForResult(object, &result, name, value, strict_mode,
1985 MAY_BE_STORE_FROM_KEYED);
1986 }
1987
1988
1989 static void ReplaceSlowProperty(Handle<JSObject> object, 1954 static void ReplaceSlowProperty(Handle<JSObject> object,
1990 Handle<Name> name, 1955 Handle<Name> name,
1991 Handle<Object> value, 1956 Handle<Object> value,
1992 PropertyAttributes attributes) { 1957 PropertyAttributes attributes) {
1993 NameDictionary* dictionary = object->property_dictionary(); 1958 NameDictionary* dictionary = object->property_dictionary();
1994 int old_index = dictionary->FindEntry(name); 1959 int old_index = dictionary->FindEntry(name);
1995 int new_enumeration_index = 0; // 0 means "Use the next available index." 1960 int new_enumeration_index = 0; // 0 means "Use the next available index."
1996 if (old_index != -1) { 1961 if (old_index != -1) {
1997 // All calls to ReplaceSlowProperty have had all transitions removed. 1962 // All calls to ReplaceSlowProperty have had all transitions removed.
1998 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); 1963 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index();
(...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after
2965 case INTERCEPTOR: 2930 case INTERCEPTOR:
2966 case NONEXISTENT: 2931 case NONEXISTENT:
2967 UNREACHABLE(); 2932 UNREACHABLE();
2968 } 2933 }
2969 } 2934 }
2970 if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>(); 2935 if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
2971 return handle(new_map); 2936 return handle(new_map);
2972 } 2937 }
2973 2938
2974 2939
2975 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor( 2940 MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
2976 Handle<JSObject> object, 2941 Handle<Object> value) {
2977 Handle<Name> name,
2978 Handle<Object> value,
2979 StrictMode strict_mode) {
2980 // TODO(rossberg): Support symbols in the API. 2942 // TODO(rossberg): Support symbols in the API.
2981 if (name->IsSymbol()) return value; 2943 if (it->name()->IsSymbol()) return value;
2982 Isolate* isolate = object->GetIsolate(); 2944
2983 Handle<String> name_string = Handle<String>::cast(name); 2945 Handle<String> name_string = Handle<String>::cast(it->name());
2984 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); 2946 Handle<JSObject> holder = it->GetHolder();
2985 if (!interceptor->setter()->IsUndefined()) { 2947 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
2986 LOG(isolate, 2948 if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>();
2987 ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); 2949
2988 PropertyCallbackArguments args( 2950 LOG(it->isolate(),
2989 isolate, interceptor->data(), *object, *object); 2951 ApiNamedPropertyAccess("interceptor-named-set", *holder, *name_string));
2990 v8::NamedPropertySetterCallback setter = 2952 PropertyCallbackArguments args(it->isolate(), interceptor->data(), *holder,
2991 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); 2953 *holder);
2992 v8::Handle<v8::Value> result = args.Call( 2954 v8::NamedPropertySetterCallback setter =
2993 setter, v8::Utils::ToLocal(name_string), v8::Utils::ToLocal(value)); 2955 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter());
2994 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 2956 v8::Handle<v8::Value> result = args.Call(
2995 if (!result.IsEmpty()) return value; 2957 setter, v8::Utils::ToLocal(name_string), v8::Utils::ToLocal(value));
2996 } 2958 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
2997 return SetPropertyPostInterceptor(object, name, value, strict_mode); 2959 if (!result.IsEmpty()) return value;
2960
2961 return MaybeHandle<Object>();
2998 } 2962 }
2999 2963
3000 2964
3001 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, 2965 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
3002 Handle<Name> name, 2966 Handle<Name> name,
3003 Handle<Object> value, 2967 Handle<Object> value,
3004 StrictMode strict_mode, 2968 StrictMode strict_mode,
3005 StoreFromKeyed store_mode) { 2969 StoreFromKeyed store_mode) {
3006 LookupResult result(object->GetIsolate()); 2970 LookupIterator it(object, name);
3007 object->LookupOwn(name, &result, true); 2971 return Object::SetProperty(&it, value, strict_mode, store_mode);
3008 if (!result.IsFound()) {
3009 object->map()->LookupTransition(JSObject::cast(*object), *name, &result);
3010 }
3011 return SetProperty(object, &result, name, value, strict_mode, store_mode);
3012 } 2972 }
3013 2973
3014 2974
2975 MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
2976 Handle<Object> value,
2977 StrictMode strict_mode,
2978 StoreFromKeyed store_mode) {
2979 // Make sure that the top context does not change when doing callbacks or
2980 // interceptor calls.
2981 AssertNoContextChange ncc(it->isolate());
2982
2983 bool done = false;
2984 for (; it->IsFound(); it->Next()) {
2985 switch (it->state()) {
2986 case LookupIterator::NOT_FOUND:
2987 UNREACHABLE();
2988
2989 case LookupIterator::ACCESS_CHECK:
2990 // TODO(verwaest): Remove the distinction. This is mostly bogus since we
2991 // don't know whether we'll want to fetch attributes or call a setter
2992 // until we find the property.
2993 if (it->HasAccess(v8::ACCESS_SET)) break;
2994 return JSObject::SetPropertyWithFailedAccessCheck(it, value,
2995 strict_mode);
2996
2997 case LookupIterator::JSPROXY:
2998 if (it->HolderIsReceiver()) {
2999 return JSProxy::SetPropertyWithHandler(it->GetJSProxy(),
3000 it->GetReceiver(), it->name(),
3001 value, strict_mode);
3002 } else {
3003 // TODO(verwaest): Use the MaybeHandle to indicate result.
3004 bool has_result = false;
3005 MaybeHandle<Object> maybe_result =
3006 JSProxy::SetPropertyViaPrototypesWithHandler(
3007 it->GetJSProxy(), it->GetReceiver(), it->name(), value,
3008 strict_mode, &has_result);
3009 if (has_result) return maybe_result;
3010 done = true;
3011 }
3012 break;
3013
3014 case LookupIterator::INTERCEPTOR:
3015 if (it->HolderIsReceiver()) {
3016 MaybeHandle<Object> maybe_result =
3017 JSObject::SetPropertyWithInterceptor(it, value);
3018 if (!maybe_result.is_null()) return maybe_result;
3019 if (it->isolate()->has_pending_exception()) return maybe_result;
3020 } else {
3021 Maybe<PropertyAttributes> maybe_attributes =
3022 JSObject::GetPropertyAttributesWithInterceptor(
3023 it->GetHolder(), it->GetReceiver(), it->name());
3024 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
3025 done = maybe_attributes.has_value;
3026 if (done && (maybe_attributes.value & READ_ONLY) != 0) {
3027 return WriteToReadOnlyProperty(it, value, strict_mode);
3028 }
3029 }
3030 break;
3031
3032 case LookupIterator::PROPERTY:
3033 if (!it->HasProperty()) break;
3034 if (it->property_details().IsReadOnly()) {
3035 return WriteToReadOnlyProperty(it, value, strict_mode);
3036 }
3037 switch (it->property_kind()) {
3038 case LookupIterator::ACCESSOR:
3039 if (it->HolderIsReceiver() ||
3040 !it->GetAccessors()->IsDeclaredAccessorInfo()) {
3041 return SetPropertyWithAccessor(it->GetReceiver(), it->name(),
3042 value, it->GetHolder(),
3043 it->GetAccessors(), strict_mode);
3044 }
3045 break;
3046 case LookupIterator::DATA:
3047 if (it->HolderIsReceiver()) return SetDataProperty(it, value);
3048 }
3049 done = true;
3050 break;
3051 }
3052
3053 if (done) break;
3054 }
3055
3056 return AddDataProperty(it, value, NONE, strict_mode, store_mode);
3057 }
3058
3059
3060 MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it,
3061 Handle<Object> value,
3062 StrictMode strict_mode) {
3063 if (strict_mode != STRICT) return value;
3064
3065 Handle<Object> args[] = {it->name(), it->GetReceiver()};
3066 Handle<Object> error = it->factory()->NewTypeError(
3067 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3068 return it->isolate()->Throw<Object>(error);
3069 }
3070
3071
3072 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
3073 Handle<Object> value) {
3074 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3075 // have own properties.
3076 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3077
3078 // Store on the holder which may be hidden behind the receiver.
3079 ASSERT(it->HolderIsReceiver());
3080
3081 // Old value for the observation change record.
3082 // Fetch before transforming the object since the encoding may become
3083 // incompatible with what's cached in |it|.
3084 bool is_observed =
3085 receiver->map()->is_observed() &&
3086 !it->name().is_identical_to(it->factory()->hidden_string());
3087 MaybeHandle<Object> maybe_old;
3088 if (is_observed) maybe_old = it->GetDataValue();
3089
3090 // Possibly migrate to the most up-to-date map that will be able to store
3091 // |value| under it->name().
3092 it->PrepareForDataProperty(value);
3093
3094 // Write the property value.
3095 it->WriteDataValue(value);
3096
3097 // Send the change record if there are observers.
3098 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
3099 JSObject::EnqueueChangeRecord(receiver, "update", it->name(),
3100 maybe_old.ToHandleChecked());
3101 }
3102
3103 return value;
3104 }
3105
3106
3107 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3108 Handle<Object> value,
3109 PropertyAttributes attributes,
3110 StrictMode strict_mode,
3111 StoreFromKeyed store_mode) {
3112 ASSERT(!it->GetReceiver()->IsJSProxy());
3113 // Transitions to data properties of value wrappers are not observable.
3114 if (!it->GetReceiver()->IsJSObject()) return value;
3115 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3116
3117 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3118 // instead. If the prototype is Null, the proxy is detached.
3119 if (receiver->IsJSGlobalProxy()) {
3120 // Trying to assign to a detached proxy.
3121 PrototypeIterator iter(it->isolate(), receiver);
3122 if (iter.IsAtEnd()) return value;
3123 receiver =
3124 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter));
3125 }
3126
3127 if (!receiver->map()->is_extensible()) {
3128 if (strict_mode == SLOPPY) return value;
3129
3130 Handle<Object> args[1] = {it->name()};
3131 Handle<Object> error = it->factory()->NewTypeError(
3132 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
3133 return it->isolate()->Throw<Object>(error);
3134 }
3135
3136 // Possibly migrate to the most up-to-date map that will be able to store
3137 // |value| under it->name() with |attributes|.
3138 it->TransitionToDataProperty(value, attributes, store_mode);
3139
3140 // TODO(verwaest): Encapsulate dictionary handling better.
3141 if (receiver->map()->is_dictionary_map()) {
3142 // TODO(verwaest): Probably should ensure this is done beforehand.
3143 it->InternalizeName();
3144 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3145 } else {
3146 // Write the property value.
3147 it->WriteDataValue(value);
3148 }
3149
3150 // Send the change record if there are observers.
3151 if (receiver->map()->is_observed() &&
3152 !it->name().is_identical_to(it->factory()->hidden_string())) {
3153 JSObject::EnqueueChangeRecord(receiver, "add", it->name(),
3154 it->factory()->the_hole_value());
3155 }
3156
3157 return value;
3158 }
3159
3160
3015 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( 3161 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3016 Handle<JSObject> object, 3162 Handle<JSObject> object,
3017 uint32_t index, 3163 uint32_t index,
3018 Handle<Object> value, 3164 Handle<Object> value,
3019 bool* found, 3165 bool* found,
3020 StrictMode strict_mode) { 3166 StrictMode strict_mode) {
3021 Isolate *isolate = object->GetIsolate(); 3167 Isolate *isolate = object->GetIsolate();
3022 for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd(); 3168 for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
3023 iter.Advance()) { 3169 iter.Advance()) {
3024 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 3170 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
(...skipping 17 matching lines...) Expand all
3042 return SetElementWithCallback(object, structure, index, value, js_proto, 3188 return SetElementWithCallback(object, structure, index, value, js_proto,
3043 strict_mode); 3189 strict_mode);
3044 } 3190 }
3045 } 3191 }
3046 } 3192 }
3047 *found = false; 3193 *found = false;
3048 return isolate->factory()->the_hole_value(); 3194 return isolate->factory()->the_hole_value();
3049 } 3195 }
3050 3196
3051 3197
3052 MaybeHandle<Object> JSObject::SetPropertyViaPrototypes(
3053 Handle<JSObject> object,
3054 Handle<Name> name,
3055 Handle<Object> value,
3056 StrictMode strict_mode,
3057 bool* done) {
3058 Isolate* isolate = object->GetIsolate();
3059
3060 *done = false;
3061 // We could not find an own property, so let's check whether there is an
3062 // accessor that wants to handle the property, or whether the property is
3063 // read-only on the prototype chain.
3064 LookupResult result(isolate);
3065 object->LookupRealNamedPropertyInPrototypes(name, &result);
3066 if (result.IsFound()) {
3067 switch (result.type()) {
3068 case NORMAL:
3069 case FIELD:
3070 case CONSTANT:
3071 *done = result.IsReadOnly();
3072 break;
3073 case INTERCEPTOR: {
3074 LookupIterator it(object, name, handle(result.holder()));
3075 PropertyAttributes attr = GetPropertyAttributes(&it);
3076 *done = !!(attr & READ_ONLY);
3077 break;
3078 }
3079 case CALLBACKS: {
3080 *done = true;
3081 if (!result.IsReadOnly()) {
3082 Handle<Object> callback_object(result.GetCallbackObject(), isolate);
3083 return SetPropertyWithCallback(object, name, value,
3084 handle(result.holder()),
3085 callback_object, strict_mode);
3086 }
3087 break;
3088 }
3089 case HANDLER: {
3090 Handle<JSProxy> proxy(result.proxy());
3091 return JSProxy::SetPropertyViaPrototypesWithHandler(
3092 proxy, object, name, value, strict_mode, done);
3093 }
3094 case NONEXISTENT:
3095 UNREACHABLE();
3096 break;
3097 }
3098 }
3099
3100 // If we get here with *done true, we have encountered a read-only property.
3101 if (*done) {
3102 if (strict_mode == SLOPPY) return value;
3103 Handle<Object> args[] = { name, object };
3104 Handle<Object> error = isolate->factory()->NewTypeError(
3105 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3106 return isolate->Throw<Object>(error);
3107 }
3108 return isolate->factory()->the_hole_value();
3109 }
3110
3111
3112 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { 3198 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3113 // Only supports adding slack to owned descriptors. 3199 // Only supports adding slack to owned descriptors.
3114 ASSERT(map->owns_descriptors()); 3200 ASSERT(map->owns_descriptors());
3115 3201
3116 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 3202 Handle<DescriptorArray> descriptors(map->instance_descriptors());
3117 int old_size = map->NumberOfOwnDescriptors(); 3203 int old_size = map->NumberOfOwnDescriptors();
3118 if (slack <= descriptors->NumberOfSlackDescriptors()) return; 3204 if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3119 3205
3120 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( 3206 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3121 descriptors, old_size, slack); 3207 descriptors, old_size, slack);
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
3501 return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); 3587 return result->HandlerResult(JSProxy::cast(iter.GetCurrent()));
3502 } 3588 }
3503 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); 3589 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result);
3504 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); 3590 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
3505 if (result->IsFound()) return; 3591 if (result->IsFound()) return;
3506 } 3592 }
3507 result->NotFound(); 3593 result->NotFound();
3508 } 3594 }
3509 3595
3510 3596
3511 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
3512 LookupResult* result,
3513 Handle<Name> key,
3514 Handle<Object> value,
3515 StrictMode strict_mode,
3516 StoreFromKeyed store_mode) {
3517 if (result->IsHandler()) {
3518 return JSProxy::SetPropertyWithHandler(handle(result->proxy()), object, key,
3519 value, strict_mode);
3520 } else {
3521 return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object),
3522 result, key, value, strict_mode,
3523 store_mode);
3524 }
3525 }
3526
3527
3528 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) { 3597 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) {
3529 Isolate* isolate = proxy->GetIsolate(); 3598 Isolate* isolate = proxy->GetIsolate();
3530 3599
3531 // TODO(rossberg): adjust once there is a story for symbols vs proxies. 3600 // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3532 if (name->IsSymbol()) return false; 3601 if (name->IsSymbol()) return false;
3533 3602
3534 Handle<Object> args[] = { name }; 3603 Handle<Object> args[] = { name };
3535 Handle<Object> result; 3604 Handle<Object> result;
3536 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3605 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3537 isolate, result, 3606 isolate, result,
3538 CallTrap(proxy, 3607 CallTrap(proxy,
3539 "has", 3608 "has",
3540 isolate->derived_has_trap(), 3609 isolate->derived_has_trap(),
3541 ARRAY_SIZE(args), 3610 ARRAY_SIZE(args),
3542 args), 3611 args),
3543 false); 3612 false);
3544 3613
3545 return result->BooleanValue(); 3614 return result->BooleanValue();
3546 } 3615 }
3547 3616
3548 3617
3549 MaybeHandle<Object> JSProxy::SetPropertyWithHandler( 3618 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy,
3550 Handle<JSProxy> proxy, 3619 Handle<Object> receiver,
3551 Handle<JSReceiver> receiver, 3620 Handle<Name> name,
3552 Handle<Name> name, 3621 Handle<Object> value,
3553 Handle<Object> value, 3622 StrictMode strict_mode) {
3554 StrictMode strict_mode) {
3555 Isolate* isolate = proxy->GetIsolate(); 3623 Isolate* isolate = proxy->GetIsolate();
3556 3624
3557 // TODO(rossberg): adjust once there is a story for symbols vs proxies. 3625 // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3558 if (name->IsSymbol()) return value; 3626 if (name->IsSymbol()) return value;
3559 3627
3560 Handle<Object> args[] = { receiver, name, value }; 3628 Handle<Object> args[] = { receiver, name, value };
3561 RETURN_ON_EXCEPTION( 3629 RETURN_ON_EXCEPTION(
3562 isolate, 3630 isolate,
3563 CallTrap(proxy, 3631 CallTrap(proxy,
3564 "set", 3632 "set",
3565 isolate->derived_set_trap(), 3633 isolate->derived_set_trap(),
3566 ARRAY_SIZE(args), 3634 ARRAY_SIZE(args),
3567 args), 3635 args),
3568 Object); 3636 Object);
3569 3637
3570 return value; 3638 return value;
3571 } 3639 }
3572 3640
3573 3641
3574 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( 3642 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3575 Handle<JSProxy> proxy, 3643 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3576 Handle<JSReceiver> receiver, 3644 Handle<Object> value, StrictMode strict_mode, bool* done) {
3577 Handle<Name> name,
3578 Handle<Object> value,
3579 StrictMode strict_mode,
3580 bool* done) {
3581 Isolate* isolate = proxy->GetIsolate(); 3645 Isolate* isolate = proxy->GetIsolate();
3582 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. 3646 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy.
3583 3647
3584 // TODO(rossberg): adjust once there is a story for symbols vs proxies. 3648 // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3585 if (name->IsSymbol()) { 3649 if (name->IsSymbol()) {
3586 *done = false; 3650 *done = false;
3587 return isolate->factory()->the_hole_value(); 3651 return isolate->factory()->the_hole_value();
3588 } 3652 }
3589 3653
3590 *done = true; // except where redefined... 3654 *done = true; // except where redefined...
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
3989 } 4053 }
3990 lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value); 4054 lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value);
3991 } 4055 }
3992 4056
3993 4057
3994 void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup, 4058 void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup,
3995 Handle<Name> name, 4059 Handle<Name> name,
3996 Handle<Object> value, 4060 Handle<Object> value,
3997 PropertyAttributes attributes) { 4061 PropertyAttributes attributes) {
3998 Handle<JSObject> object(lookup->holder()); 4062 Handle<JSObject> object(lookup->holder());
3999 if (object->TooManyFastProperties()) { 4063 if (object->map()->TooManyFastProperties(Object::MAY_BE_STORE_FROM_KEYED)) {
4000 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); 4064 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
4001 } 4065 }
4002 4066
4003 if (!object->HasFastProperties()) { 4067 if (!object->HasFastProperties()) {
4004 ReplaceSlowProperty(object, name, value, attributes); 4068 ReplaceSlowProperty(object, name, value, attributes);
4005 return; 4069 return;
4006 } 4070 }
4007 4071
4008 int descriptor_index = lookup->GetDescriptorIndex(); 4072 int descriptor_index = lookup->GetDescriptorIndex();
4009 if (lookup->GetAttributes() == attributes) { 4073 if (lookup->GetAttributes() == attributes) {
(...skipping 17 matching lines...) Expand all
4027 PropertyAttributes attributes) { 4091 PropertyAttributes attributes) {
4028 if (lookup->GetAttributes() == attributes) { 4092 if (lookup->GetAttributes() == attributes) {
4029 if (value->IsUninitialized()) return; 4093 if (value->IsUninitialized()) return;
4030 SetPropertyToField(lookup, value); 4094 SetPropertyToField(lookup, value);
4031 } else { 4095 } else {
4032 ConvertAndSetOwnProperty(lookup, name, value, attributes); 4096 ConvertAndSetOwnProperty(lookup, name, value, attributes);
4033 } 4097 }
4034 } 4098 }
4035 4099
4036 4100
4037 MaybeHandle<Object> JSObject::SetPropertyForResult(
4038 Handle<JSObject> object,
4039 LookupResult* lookup,
4040 Handle<Name> name,
4041 Handle<Object> value,
4042 StrictMode strict_mode,
4043 StoreFromKeyed store_mode) {
4044 ASSERT(!value->IsTheHole());
4045 Isolate* isolate = object->GetIsolate();
4046
4047 // Make sure that the top context does not change when doing callbacks or
4048 // interceptor calls.
4049 AssertNoContextChange ncc(isolate);
4050
4051 // Optimization for 2-byte strings often used as keys in a decompression
4052 // dictionary. We internalize these short keys to avoid constantly
4053 // reallocating them.
4054 if (name->IsString() && !name->IsInternalizedString() &&
4055 Handle<String>::cast(name)->length() <= 2) {
4056 name = isolate->factory()->InternalizeString(Handle<String>::cast(name));
4057 }
4058
4059 // Check access rights if needed.
4060 if (object->IsAccessCheckNeeded()) {
4061 if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4062 return SetPropertyWithFailedAccessCheck(object, lookup, name, value,
4063 true, strict_mode);
4064 }
4065 }
4066
4067 if (object->IsJSGlobalProxy()) {
4068 PrototypeIterator iter(isolate, object);
4069 if (iter.IsAtEnd()) return value;
4070 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4071 return SetPropertyForResult(
4072 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), lookup,
4073 name, value, strict_mode, store_mode);
4074 }
4075
4076 ASSERT(!lookup->IsFound() || lookup->holder() == *object ||
4077 lookup->holder()->map()->is_hidden_prototype());
4078
4079 if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) {
4080 bool done = false;
4081 Handle<Object> result_object;
4082 ASSIGN_RETURN_ON_EXCEPTION(
4083 isolate, result_object,
4084 SetPropertyViaPrototypes(object, name, value, strict_mode, &done),
4085 Object);
4086 if (done) return result_object;
4087 }
4088
4089 if (!lookup->IsFound()) {
4090 // Neither properties nor transitions found.
4091 return AddPropertyInternal(object, name, value, NONE, strict_mode,
4092 store_mode);
4093 }
4094
4095 if (lookup->IsProperty() && lookup->IsReadOnly()) {
4096 if (strict_mode == STRICT) {
4097 Handle<Object> args[] = { name, object };
4098 Handle<Object> error = isolate->factory()->NewTypeError(
4099 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
4100 return isolate->Throw<Object>(error);
4101 } else {
4102 return value;
4103 }
4104 }
4105
4106 Handle<Object> old_value = isolate->factory()->the_hole_value();
4107 bool is_observed = object->map()->is_observed() &&
4108 *name != isolate->heap()->hidden_string();
4109 if (is_observed && lookup->IsDataProperty()) {
4110 old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked();
4111 }
4112
4113 // This is a real property that is not read-only, or it is a
4114 // transition or null descriptor and there are no setters in the prototypes.
4115 MaybeHandle<Object> maybe_result = value;
4116 if (lookup->IsTransition()) {
4117 maybe_result = SetPropertyUsingTransition(handle(lookup->holder()), lookup,
4118 name, value, NONE);
4119 } else {
4120 switch (lookup->type()) {
4121 case NORMAL:
4122 SetNormalizedProperty(handle(lookup->holder()), lookup, value);
4123 break;
4124 case FIELD:
4125 SetPropertyToField(lookup, value);
4126 break;
4127 case CONSTANT:
4128 // Only replace the constant if necessary.
4129 if (*value == lookup->GetConstant()) return value;
4130 SetPropertyToField(lookup, value);
4131 break;
4132 case CALLBACKS: {
4133 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
4134 return SetPropertyWithCallback(object, name, value,
4135 handle(lookup->holder()),
4136 callback_object, strict_mode);
4137 }
4138 case INTERCEPTOR:
4139 maybe_result = SetPropertyWithInterceptor(handle(lookup->holder()),
4140 name, value, strict_mode);
4141 break;
4142 case HANDLER:
4143 case NONEXISTENT:
4144 UNREACHABLE();
4145 }
4146 }
4147
4148 Handle<Object> result;
4149 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
4150
4151 if (is_observed) {
4152 if (lookup->IsTransition()) {
4153 EnqueueChangeRecord(object, "add", name, old_value);
4154 } else {
4155 LookupResult new_lookup(isolate);
4156 object->LookupOwn(name, &new_lookup, true);
4157 if (new_lookup.IsDataProperty()) {
4158 Handle<Object> new_value =
4159 Object::GetPropertyOrElement(object, name).ToHandleChecked();
4160 if (!new_value->SameValue(*old_value)) {
4161 EnqueueChangeRecord(object, "update", name, old_value);
4162 }
4163 }
4164 }
4165 }
4166
4167 return result;
4168 }
4169
4170
4171 void JSObject::AddProperty( 4101 void JSObject::AddProperty(
4172 Handle<JSObject> object, 4102 Handle<JSObject> object,
4173 Handle<Name> name, 4103 Handle<Name> name,
4174 Handle<Object> value, 4104 Handle<Object> value,
4175 PropertyAttributes attributes, 4105 PropertyAttributes attributes,
4176 StoreMode store_mode) { 4106 StoreMode store_mode) {
4177 #ifdef DEBUG 4107 #ifdef DEBUG
4178 uint32_t index; 4108 uint32_t index;
4179 ASSERT(!object->IsJSProxy()); 4109 ASSERT(!object->IsJSProxy());
4180 ASSERT(!name->AsArrayIndex(&index)); 4110 ASSERT(!name->AsArrayIndex(&index));
(...skipping 27 matching lines...) Expand all
4208 4138
4209 LookupResult lookup(isolate); 4139 LookupResult lookup(isolate);
4210 object->LookupOwn(name, &lookup, true); 4140 object->LookupOwn(name, &lookup, true);
4211 if (!lookup.IsFound()) { 4141 if (!lookup.IsFound()) {
4212 object->map()->LookupTransition(*object, *name, &lookup); 4142 object->map()->LookupTransition(*object, *name, &lookup);
4213 } 4143 }
4214 4144
4215 // Check access rights if needed. 4145 // Check access rights if needed.
4216 if (object->IsAccessCheckNeeded()) { 4146 if (object->IsAccessCheckNeeded()) {
4217 if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { 4147 if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4218 return SetPropertyWithFailedAccessCheck(object, &lookup, name, value, 4148 LookupIterator it(object, name, LookupIterator::CHECK_OWN);
4219 false, SLOPPY); 4149 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4220 } 4150 }
4221 } 4151 }
4222 4152
4223 if (object->IsJSGlobalProxy()) { 4153 if (object->IsJSGlobalProxy()) {
4224 PrototypeIterator iter(isolate, object); 4154 PrototypeIterator iter(isolate, object);
4225 if (iter.IsAtEnd()) return value; 4155 if (iter.IsAtEnd()) return value;
4226 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); 4156 ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4227 return SetOwnPropertyIgnoreAttributes( 4157 return SetOwnPropertyIgnoreAttributes(
4228 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), name, 4158 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), name,
4229 value, attributes, mode, extensibility_check); 4159 value, attributes, mode, extensibility_check);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
4281 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); 4211 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4282 } 4212 }
4283 break; 4213 break;
4284 case CALLBACKS: 4214 case CALLBACKS:
4285 { 4215 {
4286 Handle<Object> callback(lookup.GetCallbackObject(), isolate); 4216 Handle<Object> callback(lookup.GetCallbackObject(), isolate);
4287 if (callback->IsExecutableAccessorInfo() && 4217 if (callback->IsExecutableAccessorInfo() &&
4288 handling == DONT_FORCE_FIELD) { 4218 handling == DONT_FORCE_FIELD) {
4289 Handle<Object> result; 4219 Handle<Object> result;
4290 ASSIGN_RETURN_ON_EXCEPTION( 4220 ASSIGN_RETURN_ON_EXCEPTION(
4291 isolate, result, 4221 isolate, result, JSObject::SetPropertyWithAccessor(
4292 JSObject::SetPropertyWithCallback(object, 4222 object, name, value, handle(lookup.holder()),
4293 name, 4223 callback, STRICT),
4294 value,
4295 handle(lookup.holder()),
4296 callback,
4297 STRICT),
4298 Object); 4224 Object);
4299 4225
4300 if (attributes != lookup.GetAttributes()) { 4226 if (attributes != lookup.GetAttributes()) {
4301 Handle<ExecutableAccessorInfo> new_data = 4227 Handle<ExecutableAccessorInfo> new_data =
4302 Accessors::CloneAccessor( 4228 Accessors::CloneAccessor(
4303 isolate, Handle<ExecutableAccessorInfo>::cast(callback)); 4229 isolate, Handle<ExecutableAccessorInfo>::cast(callback));
4304 new_data->set_property_attributes(attributes); 4230 new_data->set_property_attributes(attributes);
4305 if (attributes & READ_ONLY) { 4231 if (attributes & READ_ONLY) {
4306 // This way we don't have to introduce a lookup to the setter, 4232 // This way we don't have to introduce a lookup to the setter,
4307 // simply make it unavailable to reflect the attributes. 4233 // simply make it unavailable to reflect the attributes.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
4356 4282
4357 return value; 4283 return value;
4358 } 4284 }
4359 4285
4360 4286
4361 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( 4287 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4362 Handle<JSObject> holder, 4288 Handle<JSObject> holder,
4363 Handle<Object> receiver, 4289 Handle<Object> receiver,
4364 Handle<Name> name) { 4290 Handle<Name> name) {
4365 // TODO(rossberg): Support symbols in the API. 4291 // TODO(rossberg): Support symbols in the API.
4366 if (name->IsSymbol()) return Maybe<PropertyAttributes>(ABSENT); 4292 if (name->IsSymbol()) return Maybe<PropertyAttributes>();
4367 4293
4368 Isolate* isolate = holder->GetIsolate(); 4294 Isolate* isolate = holder->GetIsolate();
4369 HandleScope scope(isolate); 4295 HandleScope scope(isolate);
4370 4296
4371 // Make sure that the top context does not change when doing 4297 // Make sure that the top context does not change when doing
4372 // callbacks or interceptor calls. 4298 // callbacks or interceptor calls.
4373 AssertNoContextChange ncc(isolate); 4299 AssertNoContextChange ncc(isolate);
4374 4300
4375 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); 4301 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
4376 PropertyCallbackArguments args( 4302 PropertyCallbackArguments args(
(...skipping 2983 matching lines...) Expand 10 before | Expand all | Expand 10 after
7360 handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN); 7286 handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN);
7361 Handle<Map> new_map = CopyReplaceDescriptors( 7287 Handle<Map> new_map = CopyReplaceDescriptors(
7362 map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol()); 7288 map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol());
7363 new_map->freeze(); 7289 new_map->freeze();
7364 new_map->set_is_extensible(false); 7290 new_map->set_is_extensible(false);
7365 new_map->set_elements_kind(DICTIONARY_ELEMENTS); 7291 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
7366 return new_map; 7292 return new_map;
7367 } 7293 }
7368 7294
7369 7295
7296 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
7297 PropertyDetails details = GetDetails(descriptor);
7298 switch (details.type()) {
7299 case FIELD:
7300 return value->FitsRepresentation(details.representation()) &&
7301 GetFieldType(descriptor)->NowContains(value);
7302
7303 case CONSTANT:
7304 ASSERT(GetConstant(descriptor) != value ||
7305 value->FitsRepresentation(details.representation()));
7306 return GetConstant(descriptor) == value;
7307
7308 case CALLBACKS:
7309 return false;
7310
7311 case NORMAL:
7312 case INTERCEPTOR:
7313 case HANDLER:
7314 case NONEXISTENT:
7315 break;
7316 }
7317
7318 UNREACHABLE();
7319 return false;
7320 }
7321
7322
7323 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
7324 Handle<Object> value) {
7325 // Dictionaries can store any property value.
7326 if (map->is_dictionary_map()) return map;
7327
7328 Handle<DescriptorArray> descriptors(map->instance_descriptors());
7329
7330 if (descriptors->CanHoldValue(descriptor, *value)) return map;
7331
7332 Isolate* isolate = map->GetIsolate();
7333 Representation representation = value->OptimalRepresentation();
7334 Handle<HeapType> type = value->OptimalType(isolate, representation);
7335
7336 return GeneralizeRepresentation(map, descriptor, representation, type,
7337 FORCE_FIELD);
7338 }
7339
7340
7341 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
7342 Handle<Object> value,
7343 PropertyAttributes attributes,
7344 StoreFromKeyed store_mode) {
7345 // Cannot currently handle deprecated maps.
7346 ASSERT(!map->is_deprecated());
7347 // Dictionary maps can always have additional data properties.
7348 if (map->is_dictionary_map()) return map;
7349
7350 int index = map->SearchTransition(*name);
7351 if (index != TransitionArray::kNotFound) {
7352 Handle<Map> transition(map->GetTransition(index));
7353 int descriptor = transition->LastAdded();
7354
7355 // TODO(verwaest): Handle attributes better.
7356 DescriptorArray* descriptors = transition->instance_descriptors();
7357 if (descriptors->GetDetails(descriptor).attributes() != attributes) {
7358 return CopyGeneralizeAllRepresentations(transition, descriptor,
7359 FORCE_FIELD, attributes,
7360 "attributes mismatch");
7361 }
7362
7363 return Map::PrepareForDataProperty(transition, descriptor, value);
7364 }
7365
7366 TransitionFlag flag = INSERT_TRANSITION;
7367 MaybeHandle<Map> maybe_map;
7368 if (value->IsJSFunction()) {
7369 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
7370 } else if (!map->TooManyFastProperties(store_mode)) {
7371 Isolate* isolate = name->GetIsolate();
7372 Representation representation = value->OptimalRepresentation();
7373 Handle<HeapType> type = value->OptimalType(isolate, representation);
7374 maybe_map =
7375 Map::CopyWithField(map, name, type, attributes, representation, flag);
7376 }
7377
7378 Handle<Map> result;
7379 if (!maybe_map.ToHandle(&result)) {
7380 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES);
7381 }
7382
7383 return result;
7384 }
7385
7386
7370 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, 7387 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7371 Descriptor* descriptor, 7388 Descriptor* descriptor,
7372 TransitionFlag flag) { 7389 TransitionFlag flag) {
7373 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 7390 Handle<DescriptorArray> descriptors(map->instance_descriptors());
7374 7391
7375 // Ensure the key is unique. 7392 // Ensure the key is unique.
7376 descriptor->KeyToUniqueName(); 7393 descriptor->KeyToUniqueName();
7377 7394
7378 if (flag == INSERT_TRANSITION && 7395 if (flag == INSERT_TRANSITION &&
7379 map->owns_descriptors() && 7396 map->owns_descriptors() &&
(...skipping 9530 matching lines...) Expand 10 before | Expand all | Expand 10 after
16910 #define ERROR_MESSAGES_TEXTS(C, T) T, 16927 #define ERROR_MESSAGES_TEXTS(C, T) T,
16911 static const char* error_messages_[] = { 16928 static const char* error_messages_[] = {
16912 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16929 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16913 }; 16930 };
16914 #undef ERROR_MESSAGES_TEXTS 16931 #undef ERROR_MESSAGES_TEXTS
16915 return error_messages_[reason]; 16932 return error_messages_[reason];
16916 } 16933 }
16917 16934
16918 16935
16919 } } // namespace v8::internal 16936 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698