| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 30a546cc7474b4c294ecc43807300082f4983f59..87f7d2660252aca506a44a846fde86926b4ef074 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,32 @@ 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,
|
| - 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<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 +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<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 +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<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 +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<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 +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<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 +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<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 +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<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()) {
|
|
|