From: mstarzinger@chromium.org Date: Wed, 11 Sep 2013 11:00:36 +0000 (+0000) Subject: Handlify JSObject::AddProperty method. X-Git-Tag: upstream/4.7.83~12565 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c570640334fb05b1448d1e07170a63d5b5d1de17;p=platform%2Fupstream%2Fv8.git Handlify JSObject::AddProperty method. R=verwaest@chromium.org Review URL: https://codereview.chromium.org/23883007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16647 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/objects.cc b/src/objects.cc index f329c27..4ca3d57 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1900,6 +1900,20 @@ MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, } +void JSObject::AddFastProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StoreFromKeyed store_mode, + ValueType value_type, + TransitionFlag flag) { + CALL_HEAP_FUNCTION_VOID( + object->GetIsolate(), + object->AddFastProperty( + *name, *value, attributes, store_mode, value_type, flag)); +} + + MaybeObject* JSObject::AddFastProperty(Name* name, Object* value, PropertyAttributes attributes, @@ -1945,6 +1959,17 @@ MaybeObject* JSObject::AddFastProperty(Name* name, } +void JSObject::AddConstantProperty(Handle object, + Handle name, + Handle constant, + PropertyAttributes attributes, + TransitionFlag flag) { + CALL_HEAP_FUNCTION_VOID( + object->GetIsolate(), + object->AddConstantProperty(*name, *constant, attributes, flag)); +} + + MaybeObject* JSObject::AddConstantProperty( Name* name, Object* constant, @@ -1971,7 +1996,15 @@ MaybeObject* JSObject::AddConstantProperty( } -// Add property in slow mode +void JSObject::AddSlowProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes) { + CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), + object->AddSlowProperty(*name, *value, attributes)); +} + + MaybeObject* JSObject::AddSlowProperty(Name* name, Object* value, PropertyAttributes attributes) { @@ -2013,69 +2046,61 @@ MaybeObject* JSObject::AddSlowProperty(Name* name, } -MaybeObject* JSObject::AddProperty(Name* name, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - JSReceiver::StoreFromKeyed store_mode, - ExtensibilityCheck extensibility_check, - ValueType value_type, - StoreMode mode, - TransitionFlag transition_flag) { - ASSERT(!IsJSGlobalProxy()); - Map* map_of_this = map(); - Heap* heap = GetHeap(); - Isolate* isolate = heap->isolate(); - MaybeObject* result; +Handle JSObject::AddProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + JSReceiver::StoreFromKeyed store_mode, + ExtensibilityCheck extensibility_check, + ValueType value_type, + StoreMode mode, + TransitionFlag transition_flag) { + ASSERT(!object->IsJSGlobalProxy()); + Isolate* isolate = object->GetIsolate(); if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && - !map_of_this->is_extensible()) { + !object->map()->is_extensible()) { if (strict_mode == kNonStrictMode) { return value; } else { - Handle args[1] = {Handle(name)}; - return isolate->Throw( - *isolate->factory()->NewTypeError("object_not_extensible", - HandleVector(args, 1))); + Handle args[1] = { name }; + Handle error = isolate->factory()->NewTypeError( + "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); + isolate->Throw(*error); + return Handle(); } } - if (HasFastProperties()) { + if (object->HasFastProperties()) { // Ensure the descriptor array does not get too big. - if (map_of_this->NumberOfOwnDescriptors() < + if (object->map()->NumberOfOwnDescriptors() < DescriptorArray::kMaxNumberOfDescriptors) { // TODO(verwaest): Support other constants. // if (mode == ALLOW_AS_CONSTANT && // !value->IsTheHole() && // !value->IsConsString()) { if (value->IsJSFunction()) { - result = AddConstantProperty(name, value, attributes, transition_flag); + AddConstantProperty(object, name, value, attributes, transition_flag); } else { - result = AddFastProperty( - name, value, attributes, store_mode, value_type, transition_flag); + AddFastProperty(object, name, value, attributes, store_mode, + value_type, transition_flag); } } else { // Normalize the object to prevent very large instance descriptors. // This eliminates unwanted N^2 allocation and lookup behavior. - Object* obj; - MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (!maybe->To(&obj)) return maybe; - result = AddSlowProperty(name, value, attributes); + NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); + AddSlowProperty(object, name, value, attributes); } } else { - result = AddSlowProperty(name, value, attributes); + AddSlowProperty(object, name, value, attributes); } - Handle hresult; - if (!result->ToHandle(&hresult, isolate)) return result; - - if (FLAG_harmony_observation && map()->is_observed()) { - EnqueueChangeRecord(handle(this, isolate), - "new", - handle(name, isolate), - handle(heap->the_hole_value(), isolate)); + if (FLAG_harmony_observation && object->map()->is_observed()) { + Handle old_value = isolate->factory()->the_hole_value(); + EnqueueChangeRecord(object, "new", name, old_value); } - return *hresult; + return value; } @@ -2115,29 +2140,32 @@ void JSObject::DeliverChangeRecords(Isolate* isolate) { } -MaybeObject* JSObject::SetPropertyPostInterceptor( - Name* name, - Object* value, +Handle JSObject::SetPropertyPostInterceptor( + Handle object, + Handle name, + Handle value, PropertyAttributes attributes, - StrictModeFlag strict_mode, - StoreMode mode) { + StrictModeFlag strict_mode) { // Check local property, ignore interceptor. - LookupResult result(GetIsolate()); - LocalLookupRealNamedProperty(name, &result); - if (!result.IsFound()) map()->LookupTransition(this, name, &result); + LookupResult result(object->GetIsolate()); + object->LocalLookupRealNamedProperty(*name, &result); + if (!result.IsFound()) { + object->map()->LookupTransition(*object, *name, &result); + } if (result.IsFound()) { // An existing property or a map transition was found. Use set property to // handle all these cases. - return SetProperty(&result, name, value, attributes, strict_mode); + CALL_HEAP_FUNCTION(object->GetIsolate(), + object->SetProperty( + &result, *name, *value, attributes, strict_mode), + Object); } bool done = false; - MaybeObject* result_object = - SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done); + Handle result_object = SetPropertyViaPrototypes( + object, name, value, attributes, strict_mode, &done); if (done) return result_object; // Add a new real property. - return AddProperty(name, value, attributes, strict_mode, - MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, - OPTIMAL_REPRESENTATION, mode); + return AddProperty(object, name, value, attributes, strict_mode); } @@ -2703,41 +2731,36 @@ Map* Map::CurrentMapForDeprecated() { } -MaybeObject* JSObject::SetPropertyWithInterceptor( - Name* name, - Object* value, +Handle JSObject::SetPropertyWithInterceptor( + Handle object, + Handle name, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode) { // TODO(rossberg): Support symbols in the API. if (name->IsSymbol()) return value; - Isolate* isolate = GetIsolate(); - HandleScope scope(isolate); - Handle this_handle(this); - Handle name_handle(String::cast(name)); - Handle value_handle(value, isolate); - Handle interceptor(GetNamedInterceptor()); + Isolate* isolate = object->GetIsolate(); + Handle name_string = Handle::cast(name); + Handle interceptor(object->GetNamedInterceptor()); if (!interceptor->setter()->IsUndefined()) { - LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); - PropertyCallbackArguments args(isolate, interceptor->data(), this, this); + LOG(isolate, + ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); + PropertyCallbackArguments args( + isolate, interceptor->data(), *object, *object); v8::NamedPropertySetterCallback setter = v8::ToCData(interceptor->setter()); - Handle value_unhole(value->IsTheHole() ? - isolate->heap()->undefined_value() : - value, - isolate); + Handle value_unhole = value->IsTheHole() + ? Handle(isolate->factory()->undefined_value()) : value; v8::Handle result = args.Call(setter, - v8::Utils::ToLocal(name_handle), + v8::Utils::ToLocal(name_string), v8::Utils::ToLocal(value_unhole)); - RETURN_IF_SCHEDULED_EXCEPTION(isolate); - if (!result.IsEmpty()) return *value_handle; + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); + if (!result.IsEmpty()) return value; } - MaybeObject* raw_result = - this_handle->SetPropertyPostInterceptor(*name_handle, - *value_handle, - attributes, - strict_mode); - RETURN_IF_SCHEDULED_EXCEPTION(isolate); - return raw_result; + Handle result = + SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); + return result; } @@ -2930,21 +2953,20 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( return heap->the_hole_value(); } -MaybeObject* JSObject::SetPropertyViaPrototypes( - Name* name, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - bool* done) { - Heap* heap = GetHeap(); - Isolate* isolate = heap->isolate(); +Handle JSObject::SetPropertyViaPrototypes(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + bool* done) { + Isolate* isolate = object->GetIsolate(); *done = false; // We could not find a local property so let's check whether there is an // accessor that wants to handle the property, or whether the property is // read-only on the prototype chain. LookupResult result(isolate); - LookupRealNamedPropertyInPrototypes(name, &result); + object->LookupRealNamedPropertyInPrototypes(*name, &result); if (result.IsFound()) { switch (result.type()) { case NORMAL: @@ -2955,19 +2977,25 @@ MaybeObject* JSObject::SetPropertyViaPrototypes( case INTERCEPTOR: { PropertyAttributes attr = result.holder()->GetPropertyAttributeWithInterceptor( - this, name, true); + *object, *name, true); *done = !!(attr & READ_ONLY); break; } case CALLBACKS: { if (!FLAG_es5_readonly && result.IsReadOnly()) break; *done = true; - return SetPropertyWithCallback(result.GetCallbackObject(), - name, value, result.holder(), strict_mode); + CALL_HEAP_FUNCTION(isolate, + object->SetPropertyWithCallback( + result.GetCallbackObject(), + *name, *value, result.holder(), strict_mode), + Object); } case HANDLER: { - return result.proxy()->SetPropertyViaPrototypesWithHandler( - this, name, value, attributes, strict_mode, done); + CALL_HEAP_FUNCTION(isolate, + result.proxy()->SetPropertyViaPrototypesWithHandler( + *object, *name, *value, attributes, strict_mode, + done), + Object); } case TRANSITION: case NONEXISTENT: @@ -2980,12 +3008,13 @@ MaybeObject* JSObject::SetPropertyViaPrototypes( if (!FLAG_es5_readonly) *done = false; if (*done) { if (strict_mode == kNonStrictMode) return value; - Handle args[] = { Handle(name, isolate), - Handle(this, isolate)}; - return isolate->Throw(*isolate->factory()->NewTypeError( - "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); + Handle args[] = { name, object }; + Handle error = isolate->factory()->NewTypeError( + "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); + isolate->Throw(*error); + return Handle(); } - return heap->the_hole_value(); + return isolate->factory()->the_hole_value(); } @@ -3773,11 +3802,14 @@ static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup, // AddProperty will either normalize the object, or create a new fast copy // of the map. If we get a fast copy of the map, all field representations // will be tagged since the transition is omitted. - return lookup->holder()->AddProperty( - *name, *value, attributes, kNonStrictMode, + Handle holder(lookup->holder()); + Handle result = JSObject::AddProperty( + holder, name, value, attributes, kNonStrictMode, JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, JSReceiver::OMIT_EXTENSIBILITY_CHECK, JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); + RETURN_IF_EMPTY_HANDLE(holder->GetIsolate(), result); + return *result; } // Keep the target CONSTANT if the same value is stored. @@ -3947,15 +3979,18 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) { bool done = false; - MaybeObject* result_object = self->SetPropertyViaPrototypes( - *name, *value, attributes, strict_mode, &done); - if (done) return result_object; + Handle result_object = SetPropertyViaPrototypes( + self, name, value, attributes, strict_mode, &done); + RETURN_IF_EMPTY_HANDLE(isolate, result_object); + if (done) return *result_object; } if (!lookup->IsFound()) { // Neither properties nor transitions found. - return self->AddProperty( - *name, *value, attributes, strict_mode, store_mode); + Handle result_object = AddProperty( + self, name, value, attributes, strict_mode, store_mode); + RETURN_IF_EMPTY_HANDLE(isolate, result_object); + return *result_object; } if (lookup->IsProperty() && lookup->IsReadOnly()) { @@ -3994,10 +4029,14 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, return self->SetPropertyWithCallback( callback_object, *name, *value, lookup->holder(), strict_mode); } - case INTERCEPTOR: - result = lookup->holder()->SetPropertyWithInterceptor( - *name, *value, attributes, strict_mode); + case INTERCEPTOR: { + Handle holder(lookup->holder()); + Handle hresult = SetPropertyWithInterceptor( + holder, name, value, attributes, strict_mode); + RETURN_IF_EMPTY_HANDLE(isolate, hresult); + result = *hresult; break; + } case TRANSITION: { result = SetPropertyUsingTransition(lookup, name, value, attributes); break; @@ -4120,21 +4159,23 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( LocalLookupRealNamedProperty(name_raw, &lookup); } - // Check for accessor in prototype chain removed here in clone. - if (!lookup.IsFound()) { - // Neither properties nor transitions found. - return AddProperty( - name_raw, value_raw, attributes, kNonStrictMode, - MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); - } - // From this point on everything needs to be handlified. HandleScope scope(isolate); Handle self(this); Handle name(name_raw); Handle value(value_raw, isolate); - Handle old_value(isolate->heap()->the_hole_value(), isolate); + // Check for accessor in prototype chain removed here in clone. + if (!lookup.IsFound()) { + // Neither properties nor transitions found. + Handle result = AddProperty( + self, name, value, attributes, kNonStrictMode, + MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; + } + + Handle old_value = isolate->factory()->the_hole_value(); PropertyAttributes old_attributes = ABSENT; bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); if (is_observed && lookup.IsProperty()) { diff --git a/src/objects.h b/src/objects.h index ea376ea..e7175cc 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2145,17 +2145,12 @@ class JSObject: public JSReceiver { Object* value, JSObject* holder, StrictModeFlag strict_mode); - MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor( - Name* name, - Object* value, + static Handle SetPropertyWithInterceptor( + Handle object, + Handle name, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode); - MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor( - Name* name, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - StoreMode mode = ALLOW_AS_CONSTANT); static Handle SetLocalPropertyIgnoreAttributes( Handle object, @@ -2476,6 +2471,7 @@ class JSObject: public JSReceiver { // Add a property to a fast-case object using a map transition to // new_map. + // TODO(mstarzinger): Only public because of SetPropertyUsingTransition! MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap( Map* new_map, Name* name, @@ -2483,18 +2479,6 @@ class JSObject: public JSReceiver { int field_index, Representation representation); - // Add a constant function property to a fast-case object. - // This leaves a CONSTANT_TRANSITION in the old map, and - // if it is called on a second object with this map, a - // normal property is added instead, with a map transition. - // This avoids the creation of many maps with the same constant - // function, all orphaned. - MUST_USE_RESULT MaybeObject* AddConstantProperty( - Name* name, - Object* constant, - PropertyAttributes attributes, - TransitionFlag flag); - MUST_USE_RESULT MaybeObject* ReplaceSlowProperty( Name* name, Object* value, @@ -2522,24 +2506,12 @@ class JSObject: public JSReceiver { Representation new_representation, StoreMode store_mode); - // Add a property to a fast-case object. - MUST_USE_RESULT MaybeObject* AddFastProperty( - Name* name, - Object* value, - PropertyAttributes attributes, - StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED, - ValueType value_type = OPTIMAL_REPRESENTATION, - TransitionFlag flag = INSERT_TRANSITION); - - // Add a property to a slow-case object. - MUST_USE_RESULT MaybeObject* AddSlowProperty(Name* name, - Object* value, - PropertyAttributes attributes); - - // Add a property to an object. May cause GC. - MUST_USE_RESULT MaybeObject* AddProperty( - Name* name, - Object* value, + // Add a property to an object. + // TODO(mstarzinger): Only public because of SetPropertyUsingTransition! + static Handle AddProperty( + Handle object, + Handle name, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode, StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED, @@ -2774,13 +2746,62 @@ class JSObject: public JSReceiver { // Searches the prototype chain for property 'name'. If it is found and // has a setter, invoke it and set '*done' to true. If it is found and is // read-only, reject and set '*done' to true. Otherwise, set '*done' to - // false. Can cause GC and can return a failure result with '*done==true'. - MUST_USE_RESULT MaybeObject* SetPropertyViaPrototypes( - Name* name, - Object* value, + // false. Can throw and return an empty handle with '*done==true'. + static Handle SetPropertyViaPrototypes( + Handle object, + Handle name, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool* done); + static Handle SetPropertyPostInterceptor( + Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode); + + // Add a constant function property to a fast-case object. + // This leaves a CONSTANT_TRANSITION in the old map, and + // if it is called on a second object with this map, a + // normal property is added instead, with a map transition. + // This avoids the creation of many maps with the same constant + // function, all orphaned. + static void AddConstantProperty(Handle object, + Handle name, + Handle constant, + PropertyAttributes attributes, + TransitionFlag flag); + MUST_USE_RESULT MaybeObject* AddConstantProperty( + Name* name, + Object* constant, + PropertyAttributes attributes, + TransitionFlag flag); + + // Add a property to a fast-case object. + static void AddFastProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StoreFromKeyed store_mode, + ValueType value_type, + TransitionFlag flag); + MUST_USE_RESULT MaybeObject* AddFastProperty( + Name* name, + Object* value, + PropertyAttributes attributes, + StoreFromKeyed store_mode, + ValueType value_type, + TransitionFlag flag); + + // Add a property to a slow-case object. + static void AddSlowProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* AddSlowProperty(Name* name, + Object* value, + PropertyAttributes attributes); static Handle DeleteProperty(Handle object, Handle name, diff --git a/src/stub-cache.cc b/src/stub-cache.cc index bdfb32f..f4468ca 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -1404,17 +1404,19 @@ RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) { RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) { + HandleScope scope(isolate); ASSERT(args.length() == 4); - JSObject* recv = JSObject::cast(args[0]); - Name* name = Name::cast(args[1]); - Object* value = args[2]; + Handle recv(JSObject::cast(args[0])); + Handle name(Name::cast(args[1])); + Handle value(args[2], isolate); ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode); StrictModeFlag strict_mode = static_cast(args.smi_at(3)); ASSERT(recv->HasNamedInterceptor()); PropertyAttributes attr = NONE; - MaybeObject* result = recv->SetPropertyWithInterceptor( - name, value, attr, strict_mode); - return result; + Handle result = JSObject::SetPropertyWithInterceptor( + recv, name, value, attr, strict_mode); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; }