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

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
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(!value->IsTheHole()); 472 ASSERT(!value->IsTheHole());
476 ASSERT(!structure->IsForeign()); 473 ASSERT(!structure->IsForeign());
477 if (structure->IsExecutableAccessorInfo()) { 474 if (structure->IsExecutableAccessorInfo()) {
478 // api style callbacks 475 // api style callbacks
479 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure); 476 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure);
480 if (!data->IsCompatibleReceiver(*receiver)) { 477 if (!data->IsCompatibleReceiver(*receiver)) {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 PropertyAttributes JSObject::GetPropertyAttributesWithFailedAccessCheck( 596 PropertyAttributes JSObject::GetPropertyAttributesWithFailedAccessCheck(
600 LookupIterator* it) { 597 LookupIterator* it) {
601 Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder()); 598 Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder());
602 if (FindAllCanReadHolder(it)) return it->property_details().attributes(); 599 if (FindAllCanReadHolder(it)) return it->property_details().attributes();
603 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS); 600 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
604 // TODO(yangguo): Issue 3269, check for scheduled exception missing? 601 // TODO(yangguo): Issue 3269, check for scheduled exception missing?
605 return ABSENT; 602 return ABSENT;
606 } 603 }
607 604
608 605
609 static bool FindAllCanWriteHolder(LookupResult* result, 606 static bool FindAllCanWriteHolder(LookupIterator* it) {
610 Handle<Name> name, 607 it->skip_interceptor();
611 bool check_prototype) { 608 it->skip_access_check();
612 if (result->IsInterceptor()) { 609 for (; it->IsFound(); it->Next()) {
613 result->holder()->LookupOwnRealNamedProperty(name, result); 610 if (it->state() == LookupIterator::PROPERTY && it->HasProperty() &&
614 } 611 it->property_kind() == LookupIterator::ACCESSOR) {
615 612 Handle<Object> accessors = it->GetAccessors();
616 while (result->IsProperty()) { 613 if (accessors->IsAccessorInfo()) {
617 if (result->type() == CALLBACKS) { 614 if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
618 Object* callback_obj = result->GetCallbackObject();
619 if (callback_obj->IsAccessorInfo()) {
620 if (AccessorInfo::cast(callback_obj)->all_can_write()) return true;
621 } 615 }
622 } 616 }
623 if (!check_prototype) break;
624 result->holder()->LookupRealNamedPropertyInPrototypes(name, result);
625 } 617 }
626 return false; 618 return false;
627 } 619 }
628 620
629 621
630 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( 622 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
631 Handle<JSObject> object, 623 LookupIterator* it, Handle<Object> value, StrictMode strict_mode) {
632 LookupResult* result, 624 Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder());
633 Handle<Name> name, 625 if (FindAllCanWriteHolder(it)) {
634 Handle<Object> value, 626 return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
635 bool check_prototype, 627 it->GetHolder(), it->GetAccessors(),
636 StrictMode strict_mode) { 628 strict_mode);
637 if (check_prototype && !result->IsProperty()) {
638 object->LookupRealNamedPropertyInPrototypes(name, result);
639 } 629 }
640 630
641 if (FindAllCanWriteHolder(result, name, check_prototype)) { 631 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_SET);
642 Handle<JSObject> holder(result->holder()); 632 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
643 Handle<Object> callbacks(result->GetCallbackObject(), result->isolate());
644 return SetPropertyWithCallback(
645 object, name, value, holder, callbacks, strict_mode);
646 }
647
648 Isolate* isolate = object->GetIsolate();
649 isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
650 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
651 return value; 633 return value;
652 } 634 }
653 635
654 636
655 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { 637 Object* JSObject::GetNormalizedProperty(const LookupResult* result) {
656 ASSERT(!HasFastProperties()); 638 ASSERT(!HasFastProperties());
657 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); 639 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
658 if (IsGlobalObject()) { 640 if (IsGlobalObject()) {
659 value = PropertyCell::cast(value)->value(); 641 value = PropertyCell::cast(value)->value();
660 } 642 }
(...skipping 1167 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 Handle<Object> value_unhole = value->IsTheHole() 2954 v8::NamedPropertySetterCallback setter =
2993 ? Handle<Object>(isolate->factory()->undefined_value()) : value; 2955 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter());
2994 v8::Handle<v8::Value> result = args.Call(setter, 2956 Handle<Object> value_unhole =
2995 v8::Utils::ToLocal(name_string), 2957 value->IsTheHole()
2996 v8::Utils::ToLocal(value_unhole)); 2958 ? Handle<Object>::cast(it->factory()->undefined_value())
2997 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 2959 : value;
2998 if (!result.IsEmpty()) return value; 2960 v8::Handle<v8::Value> result =
2999 } 2961 args.Call(setter, v8::Utils::ToLocal(name_string),
3000 return SetPropertyPostInterceptor(object, name, value, strict_mode); 2962 v8::Utils::ToLocal(value_unhole));
2963 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
2964 if (!result.IsEmpty()) return value;
2965
2966 return MaybeHandle<Object>();
3001 } 2967 }
3002 2968
3003 2969
3004 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, 2970 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
3005 Handle<Name> name, 2971 Handle<Name> name,
3006 Handle<Object> value, 2972 Handle<Object> value,
3007 StrictMode strict_mode, 2973 StrictMode strict_mode,
3008 StoreFromKeyed store_mode) { 2974 StoreFromKeyed store_mode) {
3009 LookupResult result(object->GetIsolate()); 2975 LookupIterator it(object, name);
3010 object->LookupOwn(name, &result, true); 2976 return Object::SetProperty(&it, value, strict_mode, store_mode);
3011 if (!result.IsFound()) {
3012 object->map()->LookupTransition(JSObject::cast(*object), *name, &result);
3013 }
3014 return SetProperty(object, &result, name, value, strict_mode, store_mode);
3015 } 2977 }
3016 2978
3017 2979
2980 MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
2981 Handle<Object> value,
2982 StrictMode strict_mode,
2983 StoreFromKeyed store_mode) {
2984 // Make sure that the top context does not change when doing callbacks or
2985 // interceptor calls.
2986 AssertNoContextChange ncc(it->isolate());
2987
2988 bool done = false;
2989 for (; it->IsFound(); it->Next()) {
2990 switch (it->state()) {
2991 case LookupIterator::NOT_FOUND:
2992 UNREACHABLE();
2993
2994 case LookupIterator::ACCESS_CHECK:
2995 // TODO(verwaest): Remove the distinction. This is mostly bogus since we
2996 // don't know whether we'll want to fetch attributes or call a setter
2997 // until we find the property.
2998 if (it->HasAccess(v8::ACCESS_SET)) break;
2999 return JSObject::SetPropertyWithFailedAccessCheck(it, value,
3000 strict_mode);
3001
3002 case LookupIterator::JSPROXY:
3003 if (it->HolderIsReceiver()) {
3004 return JSProxy::SetPropertyWithHandler(it->GetJSProxy(),
3005 it->GetReceiver(), it->name(),
3006 value, strict_mode);
3007 } else {
3008 // TODO(verwaest): Use the MaybeHandle to indicate result.
3009 bool has_result = false;
3010 MaybeHandle<Object> maybe_result =
3011 JSProxy::SetPropertyViaPrototypesWithHandler(
3012 it->GetJSProxy(), it->GetReceiver(), it->name(), value,
3013 strict_mode, &has_result);
3014 if (has_result) return maybe_result;
3015 done = true;
3016 }
3017 break;
3018
3019 case LookupIterator::INTERCEPTOR:
3020 if (it->HolderIsReceiver()) {
3021 MaybeHandle<Object> maybe_result =
3022 JSObject::SetPropertyWithInterceptor(it, value);
3023 if (!maybe_result.is_null()) return maybe_result;
3024 if (it->isolate()->has_pending_exception()) return maybe_result;
3025 } else {
3026 Maybe<PropertyAttributes> maybe_attributes =
3027 JSObject::GetPropertyAttributesWithInterceptor(
3028 it->GetHolder(), it->GetReceiver(), it->name());
3029 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
3030 done = maybe_attributes.has_value;
3031 if (done && (maybe_attributes.value & READ_ONLY) != 0) {
3032 return WriteToReadOnlyProperty(it, value, strict_mode);
3033 }
3034 }
3035 break;
3036
3037 case LookupIterator::PROPERTY:
3038 if (!it->HasProperty()) break;
3039 if (it->property_details().IsReadOnly()) {
3040 return WriteToReadOnlyProperty(it, value, strict_mode);
3041 }
3042 switch (it->property_kind()) {
3043 case LookupIterator::ACCESSOR:
3044 if (it->HolderIsReceiver() ||
Igor Sheludko 2014/07/18 13:08:31 &&
Toon Verwaest 2014/07/18 13:45:22 The original was actually correct. If the holder-i
3045 !it->GetAccessors()->IsDeclaredAccessorInfo()) {
3046 return SetPropertyWithAccessor(it->GetReceiver(), it->name(),
3047 value, it->GetHolder(),
3048 it->GetAccessors(), strict_mode);
3049 }
3050 // Fall through.
Igor Sheludko 2014/07/18 13:08:31 Wrong identation.
3051 case LookupIterator::DATA:
3052 if (it->HolderIsReceiver()) return SetDataProperty(it, value);
3053 done = true;
3054 }
3055 break;
3056 }
3057
3058 if (done) break;
3059 }
3060
3061 return AddDataProperty(it, value, NONE, strict_mode, store_mode);
3062 }
3063
3064
3065 MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it,
3066 Handle<Object> value,
3067 StrictMode strict_mode) {
3068 if (strict_mode != STRICT) return value;
3069
3070 Handle<Object> args[] = {it->name(), it->GetReceiver()};
3071 Handle<Object> error = it->factory()->NewTypeError(
3072 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3073 return it->isolate()->Throw<Object>(error);
3074 }
3075
3076
3077 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
3078 Handle<Object> value) {
3079 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
3080 // have own properties.
3081 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3082
3083 // Store on the holder which may be hidden behind the receiver.
3084 ASSERT(it->HolderIsReceiver());
3085
3086 // Old value for the observation change record.
3087 // Fetch before transforming the object since the encoding may become
3088 // incompatible with what's cached in |it|.
3089 bool is_observed = receiver->map()->is_observed();
Igor Sheludko 2014/07/18 13:08:31 Should we observe modifications of "hidden_string"
3090 MaybeHandle<Object> maybe_old;
3091 if (is_observed) maybe_old = it->GetDataValue();
3092
3093 // Possibly migrate to the most up-to-date map that will be able to store
3094 // |value| under it->name().
3095 it->PrepareForDataProperty(value);
3096
3097 // Write the property value.
3098 it->WriteDataValue(value);
3099
3100 // Send the change record if there are observers.
3101 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
3102 JSObject::EnqueueChangeRecord(receiver, "update", it->name(),
3103 maybe_old.ToHandleChecked());
3104 }
3105
3106 return value;
3107 }
3108
3109
3110 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3111 Handle<Object> value,
3112 PropertyAttributes attributes,
3113 StrictMode strict_mode,
3114 StoreFromKeyed store_mode) {
3115 ASSERT(!it->GetReceiver()->IsJSProxy());
3116 // Transitions to data properties of value wrappers are not observable.
3117 if (!it->GetReceiver()->IsJSObject()) return value;
3118 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3119
3120 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3121 // instead. If the prototype is Null, the proxy is detached.
3122 if (receiver->IsJSGlobalProxy()) {
3123 // Trying to assign to a detached proxy.
3124 if (receiver->GetPrototype()->IsNull()) return value;
3125 receiver = handle(JSGlobalObject::cast(receiver->GetPrototype()));
3126 }
3127
3128 if (!receiver->map()->is_extensible()) {
3129 if (strict_mode == SLOPPY) return value;
3130
3131 Handle<Object> args[1] = {it->name()};
3132 Handle<Object> error = it->factory()->NewTypeError(
3133 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
3134 return it->isolate()->Throw<Object>(error);
3135 }
3136
3137 // Possibly migrate to the most up-to-date map that will be able to store
3138 // |value| under it->name() with |attributes|.
3139 it->TransitionToDataProperty(value, attributes, store_mode);
3140
3141 // TODO(verwaest): Encapsulate dictionary handling better.
3142 if (receiver->map()->is_dictionary_map()) {
3143 // TODO(verwaest): Probably should ensure this is done beforehand.
3144 it->InternalizeName();
3145 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
3146 } else {
3147 // Write the property value.
3148 it->WriteDataValue(value);
3149 }
3150
3151 // Send the change record if there are observers.
3152 if (receiver->map()->is_observed()) {
Igor Sheludko 2014/07/18 13:08:31 Same here.
3153 JSObject::EnqueueChangeRecord(receiver, "add", it->name(),
3154 it->factory()->the_hole_value());
3155 }
3156
3157 return value;
3158 }
3159
3160
3018 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( 3161 MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
3019 Handle<JSObject> object, 3162 Handle<JSObject> object,
3020 uint32_t index, 3163 uint32_t index,
3021 Handle<Object> value, 3164 Handle<Object> value,
3022 bool* found, 3165 bool* found,
3023 StrictMode strict_mode) { 3166 StrictMode strict_mode) {
3024 Isolate *isolate = object->GetIsolate(); 3167 Isolate *isolate = object->GetIsolate();
3025 for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd(); 3168 for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
3026 iter.Advance()) { 3169 iter.Advance()) {
3027 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 3170 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
(...skipping 17 matching lines...) Expand all
3045 return SetElementWithCallback(object, structure, index, value, js_proto, 3188 return SetElementWithCallback(object, structure, index, value, js_proto,
3046 strict_mode); 3189 strict_mode);
3047 } 3190 }
3048 } 3191 }
3049 } 3192 }
3050 *found = false; 3193 *found = false;
3051 return isolate->factory()->the_hole_value(); 3194 return isolate->factory()->the_hole_value();
3052 } 3195 }
3053 3196
3054 3197
3055 MaybeHandle<Object> JSObject::SetPropertyViaPrototypes(
3056 Handle<JSObject> object,
3057 Handle<Name> name,
3058 Handle<Object> value,
3059 StrictMode strict_mode,
3060 bool* done) {
3061 Isolate* isolate = object->GetIsolate();
3062
3063 *done = false;
3064 // We could not find an own property, so let's check whether there is an
3065 // accessor that wants to handle the property, or whether the property is
3066 // read-only on the prototype chain.
3067 LookupResult result(isolate);
3068 object->LookupRealNamedPropertyInPrototypes(name, &result);
3069 if (result.IsFound()) {
3070 switch (result.type()) {
3071 case NORMAL:
3072 case FIELD:
3073 case CONSTANT:
3074 *done = result.IsReadOnly();
3075 break;
3076 case INTERCEPTOR: {
3077 LookupIterator it(object, name, handle(result.holder()));
3078 PropertyAttributes attr = GetPropertyAttributes(&it);
3079 *done = !!(attr & READ_ONLY);
3080 break;
3081 }
3082 case CALLBACKS: {
3083 *done = true;
3084 if (!result.IsReadOnly()) {
3085 Handle<Object> callback_object(result.GetCallbackObject(), isolate);
3086 return SetPropertyWithCallback(object, name, value,
3087 handle(result.holder()),
3088 callback_object, strict_mode);
3089 }
3090 break;
3091 }
3092 case HANDLER: {
3093 Handle<JSProxy> proxy(result.proxy());
3094 return JSProxy::SetPropertyViaPrototypesWithHandler(
3095 proxy, object, name, value, strict_mode, done);
3096 }
3097 case NONEXISTENT:
3098 UNREACHABLE();
3099 break;
3100 }
3101 }
3102
3103 // If we get here with *done true, we have encountered a read-only property.
3104 if (*done) {
3105 if (strict_mode == SLOPPY) return value;
3106 Handle<Object> args[] = { name, object };
3107 Handle<Object> error = isolate->factory()->NewTypeError(
3108 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
3109 return isolate->Throw<Object>(error);
3110 }
3111 return isolate->factory()->the_hole_value();
3112 }
3113
3114
3115 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { 3198 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
3116 // Only supports adding slack to owned descriptors. 3199 // Only supports adding slack to owned descriptors.
3117 ASSERT(map->owns_descriptors()); 3200 ASSERT(map->owns_descriptors());
3118 3201
3119 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 3202 Handle<DescriptorArray> descriptors(map->instance_descriptors());
3120 int old_size = map->NumberOfOwnDescriptors(); 3203 int old_size = map->NumberOfOwnDescriptors();
3121 if (slack <= descriptors->NumberOfSlackDescriptors()) return; 3204 if (slack <= descriptors->NumberOfSlackDescriptors()) return;
3122 3205
3123 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( 3206 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
3124 descriptors, old_size, slack); 3207 descriptors, old_size, slack);
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
3513 return result->HandlerResult(JSProxy::cast(iter.GetCurrent())); 3596 return result->HandlerResult(JSProxy::cast(iter.GetCurrent()));
3514 } 3597 }
3515 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result); 3598 JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result);
3516 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); 3599 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
3517 if (result->IsFound()) return; 3600 if (result->IsFound()) return;
3518 } 3601 }
3519 result->NotFound(); 3602 result->NotFound();
3520 } 3603 }
3521 3604
3522 3605
3523 MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
3524 LookupResult* result,
3525 Handle<Name> key,
3526 Handle<Object> value,
3527 StrictMode strict_mode,
3528 StoreFromKeyed store_mode) {
3529 if (result->IsHandler()) {
3530 return JSProxy::SetPropertyWithHandler(handle(result->proxy()), object, key,
3531 value, strict_mode);
3532 } else {
3533 return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object),
3534 result, key, value, strict_mode,
3535 store_mode);
3536 }
3537 }
3538
3539
3540 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) { 3606 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) {
3541 Isolate* isolate = proxy->GetIsolate(); 3607 Isolate* isolate = proxy->GetIsolate();
3542 3608
3543 // TODO(rossberg): adjust once there is a story for symbols vs proxies. 3609 // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3544 if (name->IsSymbol()) return false; 3610 if (name->IsSymbol()) return false;
3545 3611
3546 Handle<Object> args[] = { name }; 3612 Handle<Object> args[] = { name };
3547 Handle<Object> result; 3613 Handle<Object> result;
3548 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3614 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3549 isolate, result, 3615 isolate, result,
3550 CallTrap(proxy, 3616 CallTrap(proxy,
3551 "has", 3617 "has",
3552 isolate->derived_has_trap(), 3618 isolate->derived_has_trap(),
3553 ARRAY_SIZE(args), 3619 ARRAY_SIZE(args),
3554 args), 3620 args),
3555 false); 3621 false);
3556 3622
3557 return result->BooleanValue(); 3623 return result->BooleanValue();
3558 } 3624 }
3559 3625
3560 3626
3561 MaybeHandle<Object> JSProxy::SetPropertyWithHandler( 3627 MaybeHandle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy,
3562 Handle<JSProxy> proxy, 3628 Handle<Object> receiver,
3563 Handle<JSReceiver> receiver, 3629 Handle<Name> name,
3564 Handle<Name> name, 3630 Handle<Object> value,
3565 Handle<Object> value, 3631 StrictMode strict_mode) {
3566 StrictMode strict_mode) {
3567 Isolate* isolate = proxy->GetIsolate(); 3632 Isolate* isolate = proxy->GetIsolate();
3568 3633
3569 // TODO(rossberg): adjust once there is a story for symbols vs proxies. 3634 // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3570 if (name->IsSymbol()) return value; 3635 if (name->IsSymbol()) return value;
3571 3636
3572 Handle<Object> args[] = { receiver, name, value }; 3637 Handle<Object> args[] = { receiver, name, value };
3573 RETURN_ON_EXCEPTION( 3638 RETURN_ON_EXCEPTION(
3574 isolate, 3639 isolate,
3575 CallTrap(proxy, 3640 CallTrap(proxy,
3576 "set", 3641 "set",
3577 isolate->derived_set_trap(), 3642 isolate->derived_set_trap(),
3578 ARRAY_SIZE(args), 3643 ARRAY_SIZE(args),
3579 args), 3644 args),
3580 Object); 3645 Object);
3581 3646
3582 return value; 3647 return value;
3583 } 3648 }
3584 3649
3585 3650
3586 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( 3651 MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
3587 Handle<JSProxy> proxy, 3652 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
3588 Handle<JSReceiver> receiver, 3653 Handle<Object> value, StrictMode strict_mode, bool* done) {
3589 Handle<Name> name,
3590 Handle<Object> value,
3591 StrictMode strict_mode,
3592 bool* done) {
3593 Isolate* isolate = proxy->GetIsolate(); 3654 Isolate* isolate = proxy->GetIsolate();
3594 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. 3655 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy.
3595 3656
3596 // TODO(rossberg): adjust once there is a story for symbols vs proxies. 3657 // TODO(rossberg): adjust once there is a story for symbols vs proxies.
3597 if (name->IsSymbol()) { 3658 if (name->IsSymbol()) {
3598 *done = false; 3659 *done = false;
3599 return isolate->factory()->the_hole_value(); 3660 return isolate->factory()->the_hole_value();
3600 } 3661 }
3601 3662
3602 *done = true; // except where redefined... 3663 *done = true; // except where redefined...
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
4001 } 4062 }
4002 lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value); 4063 lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value);
4003 } 4064 }
4004 4065
4005 4066
4006 void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup, 4067 void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup,
4007 Handle<Name> name, 4068 Handle<Name> name,
4008 Handle<Object> value, 4069 Handle<Object> value,
4009 PropertyAttributes attributes) { 4070 PropertyAttributes attributes) {
4010 Handle<JSObject> object(lookup->holder()); 4071 Handle<JSObject> object(lookup->holder());
4011 if (object->TooManyFastProperties()) { 4072 if (object->map()->TooManyFastProperties(Object::MAY_BE_STORE_FROM_KEYED)) {
4012 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); 4073 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
4013 } 4074 }
4014 4075
4015 if (!object->HasFastProperties()) { 4076 if (!object->HasFastProperties()) {
4016 ReplaceSlowProperty(object, name, value, attributes); 4077 ReplaceSlowProperty(object, name, value, attributes);
4017 return; 4078 return;
4018 } 4079 }
4019 4080
4020 int descriptor_index = lookup->GetDescriptorIndex(); 4081 int descriptor_index = lookup->GetDescriptorIndex();
4021 if (lookup->GetAttributes() == attributes) { 4082 if (lookup->GetAttributes() == attributes) {
(...skipping 17 matching lines...) Expand all
4039 PropertyAttributes attributes) { 4100 PropertyAttributes attributes) {
4040 if (lookup->GetAttributes() == attributes) { 4101 if (lookup->GetAttributes() == attributes) {
4041 if (value->IsUninitialized()) return; 4102 if (value->IsUninitialized()) return;
4042 SetPropertyToField(lookup, value); 4103 SetPropertyToField(lookup, value);
4043 } else { 4104 } else {
4044 ConvertAndSetOwnProperty(lookup, name, value, attributes); 4105 ConvertAndSetOwnProperty(lookup, name, value, attributes);
4045 } 4106 }
4046 } 4107 }
4047 4108
4048 4109
4049 MaybeHandle<Object> JSObject::SetPropertyForResult(
4050 Handle<JSObject> object,
4051 LookupResult* lookup,
4052 Handle<Name> name,
4053 Handle<Object> value,
4054 StrictMode strict_mode,
4055 StoreFromKeyed store_mode) {
4056 Isolate* isolate = object->GetIsolate();
4057
4058 // Make sure that the top context does not change when doing callbacks or
4059 // interceptor calls.
4060 AssertNoContextChange ncc(isolate);
4061
4062 // Optimization for 2-byte strings often used as keys in a decompression
4063 // dictionary. We internalize these short keys to avoid constantly
4064 // reallocating them.
4065 if (name->IsString() && !name->IsInternalizedString() &&
4066 Handle<String>::cast(name)->length() <= 2) {
4067 name = isolate->factory()->InternalizeString(Handle<String>::cast(name));
4068 }
4069
4070 // Check access rights if needed.
4071 if (object->IsAccessCheckNeeded()) {
4072 if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4073 return SetPropertyWithFailedAccessCheck(object, lookup, name, value,
4074 true, strict_mode);
4075 }
4076 }
4077
4078 if (object->IsJSGlobalProxy()) {
4079 Handle<Object> proto(object->GetPrototype(), isolate);
4080 if (proto->IsNull()) return value;
4081 ASSERT(proto->IsJSGlobalObject());
4082 return SetPropertyForResult(Handle<JSObject>::cast(proto), lookup, name,
4083 value, strict_mode, store_mode);
4084 }
4085
4086 ASSERT(!lookup->IsFound() || lookup->holder() == *object ||
4087 lookup->holder()->map()->is_hidden_prototype());
4088
4089 if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) {
4090 bool done = false;
4091 Handle<Object> result_object;
4092 ASSIGN_RETURN_ON_EXCEPTION(
4093 isolate, result_object,
4094 SetPropertyViaPrototypes(object, name, value, strict_mode, &done),
4095 Object);
4096 if (done) return result_object;
4097 }
4098
4099 if (!lookup->IsFound()) {
4100 // Neither properties nor transitions found.
4101 return AddPropertyInternal(object, name, value, NONE, strict_mode,
4102 store_mode);
4103 }
4104
4105 if (lookup->IsProperty() && lookup->IsReadOnly()) {
4106 if (strict_mode == STRICT) {
4107 Handle<Object> args[] = { name, object };
4108 Handle<Object> error = isolate->factory()->NewTypeError(
4109 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
4110 return isolate->Throw<Object>(error);
4111 } else {
4112 return value;
4113 }
4114 }
4115
4116 Handle<Object> old_value = isolate->factory()->the_hole_value();
4117 bool is_observed = object->map()->is_observed() &&
4118 *name != isolate->heap()->hidden_string();
4119 if (is_observed && lookup->IsDataProperty()) {
4120 old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked();
4121 }
4122
4123 // This is a real property that is not read-only, or it is a
4124 // transition or null descriptor and there are no setters in the prototypes.
4125 MaybeHandle<Object> maybe_result = value;
4126 if (lookup->IsTransition()) {
4127 maybe_result = SetPropertyUsingTransition(handle(lookup->holder()), lookup,
4128 name, value, NONE);
4129 } else {
4130 switch (lookup->type()) {
4131 case NORMAL:
4132 SetNormalizedProperty(handle(lookup->holder()), lookup, value);
4133 break;
4134 case FIELD:
4135 SetPropertyToField(lookup, value);
4136 break;
4137 case CONSTANT:
4138 // Only replace the constant if necessary.
4139 if (*value == lookup->GetConstant()) return value;
4140 SetPropertyToField(lookup, value);
4141 break;
4142 case CALLBACKS: {
4143 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
4144 return SetPropertyWithCallback(object, name, value,
4145 handle(lookup->holder()),
4146 callback_object, strict_mode);
4147 }
4148 case INTERCEPTOR:
4149 maybe_result = SetPropertyWithInterceptor(handle(lookup->holder()),
4150 name, value, strict_mode);
4151 break;
4152 case HANDLER:
4153 case NONEXISTENT:
4154 UNREACHABLE();
4155 }
4156 }
4157
4158 Handle<Object> result;
4159 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
4160
4161 if (is_observed) {
4162 if (lookup->IsTransition()) {
4163 EnqueueChangeRecord(object, "add", name, old_value);
4164 } else {
4165 LookupResult new_lookup(isolate);
4166 object->LookupOwn(name, &new_lookup, true);
4167 if (new_lookup.IsDataProperty()) {
4168 Handle<Object> new_value =
4169 Object::GetPropertyOrElement(object, name).ToHandleChecked();
4170 if (!new_value->SameValue(*old_value)) {
4171 EnqueueChangeRecord(object, "update", name, old_value);
4172 }
4173 }
4174 }
4175 }
4176
4177 return result;
4178 }
4179
4180
4181 void JSObject::AddProperty( 4110 void JSObject::AddProperty(
4182 Handle<JSObject> object, 4111 Handle<JSObject> object,
4183 Handle<Name> name, 4112 Handle<Name> name,
4184 Handle<Object> value, 4113 Handle<Object> value,
4185 PropertyAttributes attributes, 4114 PropertyAttributes attributes,
4186 StoreMode store_mode) { 4115 StoreMode store_mode) {
4187 #ifdef DEBUG 4116 #ifdef DEBUG
4188 uint32_t index; 4117 uint32_t index;
4189 ASSERT(!object->IsJSProxy()); 4118 ASSERT(!object->IsJSProxy());
4190 ASSERT(!name->AsArrayIndex(&index)); 4119 ASSERT(!name->AsArrayIndex(&index));
(...skipping 26 matching lines...) Expand all
4217 4146
4218 LookupResult lookup(isolate); 4147 LookupResult lookup(isolate);
4219 object->LookupOwn(name, &lookup, true); 4148 object->LookupOwn(name, &lookup, true);
4220 if (!lookup.IsFound()) { 4149 if (!lookup.IsFound()) {
4221 object->map()->LookupTransition(*object, *name, &lookup); 4150 object->map()->LookupTransition(*object, *name, &lookup);
4222 } 4151 }
4223 4152
4224 // Check access rights if needed. 4153 // Check access rights if needed.
4225 if (object->IsAccessCheckNeeded()) { 4154 if (object->IsAccessCheckNeeded()) {
4226 if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) { 4155 if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4227 return SetPropertyWithFailedAccessCheck(object, &lookup, name, value, 4156 LookupIterator it(object, name, LookupIterator::CHECK_OWN);
4228 false, SLOPPY); 4157 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4229 } 4158 }
4230 } 4159 }
4231 4160
4232 if (object->IsJSGlobalProxy()) { 4161 if (object->IsJSGlobalProxy()) {
4233 Handle<Object> proto(object->GetPrototype(), isolate); 4162 Handle<Object> proto(object->GetPrototype(), isolate);
4234 if (proto->IsNull()) return value; 4163 if (proto->IsNull()) return value;
4235 ASSERT(proto->IsJSGlobalObject()); 4164 ASSERT(proto->IsJSGlobalObject());
4236 return SetOwnPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), name, 4165 return SetOwnPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), name,
4237 value, attributes, mode, 4166 value, attributes, mode,
4238 extensibility_check); 4167 extensibility_check);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
4290 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); 4219 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4291 } 4220 }
4292 break; 4221 break;
4293 case CALLBACKS: 4222 case CALLBACKS:
4294 { 4223 {
4295 Handle<Object> callback(lookup.GetCallbackObject(), isolate); 4224 Handle<Object> callback(lookup.GetCallbackObject(), isolate);
4296 if (callback->IsExecutableAccessorInfo() && 4225 if (callback->IsExecutableAccessorInfo() &&
4297 handling == DONT_FORCE_FIELD) { 4226 handling == DONT_FORCE_FIELD) {
4298 Handle<Object> result; 4227 Handle<Object> result;
4299 ASSIGN_RETURN_ON_EXCEPTION( 4228 ASSIGN_RETURN_ON_EXCEPTION(
4300 isolate, result, 4229 isolate, result, JSObject::SetPropertyWithAccessor(
4301 JSObject::SetPropertyWithCallback(object, 4230 object, name, value, handle(lookup.holder()),
4302 name, 4231 callback, STRICT),
4303 value,
4304 handle(lookup.holder()),
4305 callback,
4306 STRICT),
4307 Object); 4232 Object);
4308 4233
4309 if (attributes != lookup.GetAttributes()) { 4234 if (attributes != lookup.GetAttributes()) {
4310 Handle<ExecutableAccessorInfo> new_data = 4235 Handle<ExecutableAccessorInfo> new_data =
4311 Accessors::CloneAccessor( 4236 Accessors::CloneAccessor(
4312 isolate, Handle<ExecutableAccessorInfo>::cast(callback)); 4237 isolate, Handle<ExecutableAccessorInfo>::cast(callback));
4313 new_data->set_property_attributes(attributes); 4238 new_data->set_property_attributes(attributes);
4314 if (attributes & READ_ONLY) { 4239 if (attributes & READ_ONLY) {
4315 // This way we don't have to introduce a lookup to the setter, 4240 // This way we don't have to introduce a lookup to the setter,
4316 // simply make it unavailable to reflect the attributes. 4241 // simply make it unavailable to reflect the attributes.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
4365 4290
4366 return value; 4291 return value;
4367 } 4292 }
4368 4293
4369 4294
4370 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( 4295 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4371 Handle<JSObject> holder, 4296 Handle<JSObject> holder,
4372 Handle<Object> receiver, 4297 Handle<Object> receiver,
4373 Handle<Name> name) { 4298 Handle<Name> name) {
4374 // TODO(rossberg): Support symbols in the API. 4299 // TODO(rossberg): Support symbols in the API.
4375 if (name->IsSymbol()) return Maybe<PropertyAttributes>(ABSENT); 4300 if (name->IsSymbol()) return Maybe<PropertyAttributes>();
4376 4301
4377 Isolate* isolate = holder->GetIsolate(); 4302 Isolate* isolate = holder->GetIsolate();
4378 HandleScope scope(isolate); 4303 HandleScope scope(isolate);
4379 4304
4380 // Make sure that the top context does not change when doing 4305 // Make sure that the top context does not change when doing
4381 // callbacks or interceptor calls. 4306 // callbacks or interceptor calls.
4382 AssertNoContextChange ncc(isolate); 4307 AssertNoContextChange ncc(isolate);
4383 4308
4384 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor()); 4309 Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
4385 PropertyCallbackArguments args( 4310 PropertyCallbackArguments args(
(...skipping 2974 matching lines...) Expand 10 before | Expand all | Expand 10 after
7360 handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN); 7285 handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN);
7361 Handle<Map> new_map = CopyReplaceDescriptors( 7286 Handle<Map> new_map = CopyReplaceDescriptors(
7362 map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol()); 7287 map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol());
7363 new_map->freeze(); 7288 new_map->freeze();
7364 new_map->set_is_extensible(false); 7289 new_map->set_is_extensible(false);
7365 new_map->set_elements_kind(DICTIONARY_ELEMENTS); 7290 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
7366 return new_map; 7291 return new_map;
7367 } 7292 }
7368 7293
7369 7294
7295 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
7296 PropertyDetails details = GetDetails(descriptor);
7297 switch (details.type()) {
7298 case FIELD:
7299 return value->FitsRepresentation(details.representation()) &&
7300 GetFieldType(descriptor)->NowContains(value);
7301
7302 case CONSTANT:
7303 ASSERT(GetConstant(descriptor) != value ||
7304 value->FitsRepresentation(details.representation()));
7305 return GetConstant(descriptor) == value;
7306
7307 case CALLBACKS:
7308 return false;
7309
7310 case NORMAL:
7311 case INTERCEPTOR:
7312 case HANDLER:
7313 case NONEXISTENT:
7314 break;
7315 }
7316
7317 UNREACHABLE();
7318 return false;
7319 }
7320
7321
7322 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
7323 Handle<Object> value) {
7324 // Dictionaries can store any property value.
7325 if (map->is_dictionary_map()) return map;
7326
7327 Handle<DescriptorArray> descriptors(map->instance_descriptors());
7328
7329 if (descriptors->CanHoldValue(descriptor, *value)) return map;
7330
7331 Isolate* isolate = map->GetIsolate();
7332 Representation representation = value->OptimalRepresentation();
7333 Handle<HeapType> type = value->OptimalType(isolate, representation);
7334
7335 return GeneralizeRepresentation(map, descriptor, representation, type,
7336 FORCE_FIELD);
7337 }
7338
7339
7340 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
7341 Handle<Object> value,
7342 PropertyAttributes attributes,
7343 StoreFromKeyed store_mode) {
7344 // Cannot currently handle deprecated maps.
7345 ASSERT(!map->is_deprecated());
7346 // Dictionary maps can always have additional data properties.
7347 if (map->is_dictionary_map()) return map;
7348
7349 int index = map->SearchTransition(*name);
7350 if (index != TransitionArray::kNotFound) {
7351 Handle<Map> transition(map->GetTransition(index));
7352 int descriptor = transition->LastAdded();
7353
7354 // TODO(verwaest): Handle attributes better.
7355 DescriptorArray* descriptors = transition->instance_descriptors();
7356 if (descriptors->GetDetails(descriptor).attributes() != attributes) {
7357 return CopyGeneralizeAllRepresentations(transition, descriptor,
7358 FORCE_FIELD, attributes,
7359 "attributes mismatch");
7360 }
7361
7362 return Map::PrepareForDataProperty(transition, descriptor, value);
7363 }
7364
7365 TransitionFlag flag = INSERT_TRANSITION;
7366 MaybeHandle<Map> maybe_map;
7367 if (value->IsJSFunction()) {
7368 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
7369 } else if (!map->TooManyFastProperties(store_mode)) {
7370 Isolate* isolate = name->GetIsolate();
7371 Representation representation = value->OptimalRepresentation();
7372 Handle<HeapType> type = value->OptimalType(isolate, representation);
7373 maybe_map =
7374 Map::CopyWithField(map, name, type, attributes, representation, flag);
7375 }
7376
7377 Handle<Map> result;
7378 if (!maybe_map.ToHandle(&result)) {
7379 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES);
7380 }
7381
7382 return result;
7383 }
7384
7385
7370 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, 7386 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7371 Descriptor* descriptor, 7387 Descriptor* descriptor,
7372 TransitionFlag flag) { 7388 TransitionFlag flag) {
7373 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 7389 Handle<DescriptorArray> descriptors(map->instance_descriptors());
7374 7390
7375 // Ensure the key is unique. 7391 // Ensure the key is unique.
7376 descriptor->KeyToUniqueName(); 7392 descriptor->KeyToUniqueName();
7377 7393
7378 if (flag == INSERT_TRANSITION && 7394 if (flag == INSERT_TRANSITION &&
7379 map->owns_descriptors() && 7395 map->owns_descriptors() &&
(...skipping 9535 matching lines...) Expand 10 before | Expand all | Expand 10 after
16915 #define ERROR_MESSAGES_TEXTS(C, T) T, 16931 #define ERROR_MESSAGES_TEXTS(C, T) T,
16916 static const char* error_messages_[] = { 16932 static const char* error_messages_[] = {
16917 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16933 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16918 }; 16934 };
16919 #undef ERROR_MESSAGES_TEXTS 16935 #undef ERROR_MESSAGES_TEXTS
16920 return error_messages_[reason]; 16936 return error_messages_[reason];
16921 } 16937 }
16922 16938
16923 16939
16924 } } // namespace v8::internal 16940 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | src/v8natives.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698