Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 30a546cc7474b4c294ecc43807300082f4983f59..92ea2a01c1f0d39abc309f01aaca127d641bfaf1 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -1900,6 +1900,20 @@ MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, |
| } |
| +void JSObject::AddFastProperty(Handle<JSObject> object, |
| + Handle<Name> name, |
| + Handle<Object> 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<JSObject> object, |
| + Handle<Name> name, |
| + Handle<Object> 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<JSObject> object, |
| + Handle<Name> name, |
| + Handle<Object> 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<Object> JSObject::AddProperty(Handle<JSObject> object, |
| + Handle<Name> name, |
| + Handle<Object> 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<Object> args[1] = {Handle<Name>(name)}; |
| - return isolate->Throw( |
| - *isolate->factory()->NewTypeError("object_not_extensible", |
| - HandleVector(args, 1))); |
| + Handle<Object> args[1] = { name }; |
| + Handle<Object> error = isolate->factory()->NewTypeError( |
| + "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); |
| + isolate->Throw(*error); |
| + return Handle<Object>(); |
| } |
| } |
| - 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<Object> 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<Object> old_value = isolate->factory()->the_hole_value(); |
| + EnqueueChangeRecord(object, "new", name, old_value); |
| } |
| - return *hresult; |
| + return value; |
| } |
| @@ -2115,29 +2140,34 @@ void JSObject::DeliverChangeRecords(Isolate* isolate) { |
| } |
| -MaybeObject* JSObject::SetPropertyPostInterceptor( |
| - Name* name, |
| - Object* value, |
| +Handle<Object> JSObject::SetPropertyPostInterceptor( |
| + Handle<JSObject> object, |
| + Handle<Name> name, |
| + Handle<Object> 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<Object> 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, |
| + return AddProperty(object, name, value, attributes, strict_mode, |
| MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, |
|
Toon Verwaest
2013/09/11 09:31:29
Those 4 uppercase arguments are the default argume
Michael Starzinger
2013/09/11 10:52:32
Done.
|
| - OPTIMAL_REPRESENTATION, mode); |
| + OPTIMAL_REPRESENTATION, ALLOW_AS_CONSTANT); |
| } |
| @@ -2703,41 +2733,36 @@ Map* Map::CurrentMapForDeprecated() { |
| } |
| -MaybeObject* JSObject::SetPropertyWithInterceptor( |
| - Name* name, |
| - Object* value, |
| +Handle<Object> JSObject::SetPropertyWithInterceptor( |
| + Handle<JSObject> object, |
| + Handle<Name> name, |
| + Handle<Object> 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<JSObject> this_handle(this); |
| - Handle<String> name_handle(String::cast(name)); |
| - Handle<Object> value_handle(value, isolate); |
| - Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| + Isolate* isolate = object->GetIsolate(); |
| + Handle<String> name_string = Handle<String>::cast(name); |
| + Handle<InterceptorInfo> 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<v8::NamedPropertySetterCallback>(interceptor->setter()); |
| - Handle<Object> value_unhole(value->IsTheHole() ? |
| - isolate->heap()->undefined_value() : |
| - value, |
| - isolate); |
| + Handle<Object> value_unhole = value->IsTheHole() |
| + ? Handle<Object>(isolate->factory()->undefined_value()) : value; |
| v8::Handle<v8::Value> 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<Object> result = |
| + SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); |
| + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| + return result; |
| } |
| @@ -2930,21 +2955,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<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, |
| + Handle<Name> name, |
| + Handle<Object> 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 +2979,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 +3010,13 @@ MaybeObject* JSObject::SetPropertyViaPrototypes( |
| if (!FLAG_es5_readonly) *done = false; |
| if (*done) { |
| if (strict_mode == kNonStrictMode) return value; |
| - Handle<Object> args[] = { Handle<Object>(name, isolate), |
| - Handle<Object>(this, isolate)}; |
| - return isolate->Throw(*isolate->factory()->NewTypeError( |
| - "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); |
| + Handle<Object> args[] = { name, object }; |
| + Handle<Object> error = isolate->factory()->NewTypeError( |
| + "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| + isolate->Throw(*error); |
| + return Handle<Object>(); |
| } |
| - return heap->the_hole_value(); |
| + return isolate->factory()->the_hole_value(); |
| } |
| @@ -3773,11 +3804,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<JSObject> holder(lookup->holder()); |
| + Handle<Object> 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 +3981,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<Object> 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<Object> 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 +4031,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<JSObject> holder(lookup->holder()); |
| + Handle<Object> 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 +4161,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<JSObject> self(this); |
| Handle<Name> name(name_raw); |
| Handle<Object> value(value_raw, isolate); |
| - Handle<Object> 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<Object> 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<Object> 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()) { |