Revision: 22482
Author: [email protected]
Date: Fri Jul 18 13:47:25 2014 UTC
Log: Reimplement SetProperty using the LookupIterator
BUG=
[email protected]
Review URL: https://codereview.chromium.org/392243002
http://code.google.com/p/v8/source/detail?r=22482
Modified:
/branches/bleeding_edge/src/debug.cc
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/lookup.cc
/branches/bleeding_edge/src/lookup.h
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/stub-cache.cc
/branches/bleeding_edge/src/v8natives.js
/branches/bleeding_edge/test/cctest/test-decls.cc
=======================================
--- /branches/bleeding_edge/src/debug.cc Wed Jul 16 12:18:33 2014 UTC
+++ /branches/bleeding_edge/src/debug.cc Fri Jul 18 13:47:25 2014 UTC
@@ -1547,7 +1547,7 @@
if (is_load_or_store) {
// Remember source position and frame to handle step in
getter/setter. If
// there is a custom getter/setter it will be handled in
- // Object::Get/SetPropertyWithCallback, otherwise the step action
will be
+ // Object::Get/SetPropertyWithAccessor, otherwise the step action
will be
// propagated on the next Debug::Break.
thread_local_.last_statement_position_ =
debug_info->code()->SourceStatementPosition(frame->pc());
=======================================
--- /branches/bleeding_edge/src/ic.cc Thu Jul 17 09:44:37 2014 UTC
+++ /branches/bleeding_edge/src/ic.cc Fri Jul 18 13:47:25 2014 UTC
@@ -1281,6 +1281,8 @@
Handle<String> name,
Handle<Object> value,
JSReceiver::StoreFromKeyed store_mode) {
+ // TODO(verwaest): Let SetProperty do the migration, since storing a
property
+ // might deprecate the current map again, if value does not fit.
if (MigrateDeprecated(object) || object->IsJSProxy()) {
Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
Handle<Object> result;
@@ -1757,6 +1759,8 @@
MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
Handle<Object> key,
Handle<Object> value) {
+ // TODO(verwaest): Let SetProperty do the migration, since storing a
property
+ // might deprecate the current map again, if value does not fit.
if (MigrateDeprecated(object)) {
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(
=======================================
--- /branches/bleeding_edge/src/lookup.cc Thu Jul 17 09:06:49 2014 UTC
+++ /branches/bleeding_edge/src/lookup.cc Fri Jul 18 13:47:25 2014 UTC
@@ -142,6 +142,78 @@
has_property_ = true;
return true;
}
+
+
+void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
+ ASSERT(has_property_);
+ ASSERT(HolderIsReceiver());
+ if (property_encoding_ == DICTIONARY) return;
+ holder_map_ = Map::PrepareForDataProperty(holder_map_, number_, value);
+ JSObject::MigrateToMap(GetHolder(), holder_map_);
+ // Reload property information.
+ if (holder_map_->is_dictionary_map()) {
+ property_encoding_ = DICTIONARY;
+ } else {
+ property_encoding_ = DESCRIPTOR;
+ }
+ CHECK(HasProperty());
+}
+
+
+void LookupIterator::TransitionToDataProperty(
+ Handle<Object> value, PropertyAttributes attributes,
+ Object::StoreFromKeyed store_mode) {
+ ASSERT(!has_property_ || !HolderIsReceiver());
+
+ // Can only be called when the receiver is a JSObject. JSProxy has to be
+ // handled via a trap. Adding properties to primitive values is not
+ // observable.
+ Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver());
+
+ // Properties have to be added to context extension objects through
+ // SetOwnPropertyIgnoreAttributes.
+ ASSERT(!receiver->IsJSContextExtensionObject());
+
+ if (receiver->IsJSGlobalProxy()) {
+ PrototypeIterator iter(isolate(), receiver);
+ receiver =
+ Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter));
+ }
+
+ maybe_holder_ = receiver;
+ holder_map_ = Map::TransitionToDataProperty(handle(receiver->map()),
name_,
+ value, attributes,
store_mode);
+ JSObject::MigrateToMap(receiver, holder_map_);
+
+ // Reload the information.
+ state_ = NOT_FOUND;
+ configuration_ = CHECK_OWN_REAL;
+ state_ = LookupInHolder();
+ ASSERT(IsFound());
+ HasProperty();
+}
+
+
+bool LookupIterator::HolderIsReceiver() const {
+ ASSERT(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY);
+ DisallowHeapAllocation no_gc;
+ Handle<Object> receiver = GetReceiver();
+ if (!receiver->IsJSReceiver()) return false;
+ Object* current = *receiver;
+ JSReceiver* holder = *maybe_holder_.ToHandleChecked();
+ // JSProxy do not occur as hidden prototypes.
+ if (current->IsJSProxy()) {
+ return JSReceiver::cast(current) == holder;
+ }
+ PrototypeIterator iter(isolate(), current,
+ PrototypeIterator::START_AT_RECEIVER);
+ do {
+ if (JSReceiver::cast(iter.GetCurrent()) == holder) return true;
+ ASSERT(!current->IsJSProxy());
+ iter.Advance();
+ } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
+ return false;
+}
Handle<Object> LookupIterator::FetchValue() const {
@@ -181,4 +253,29 @@
}
+void LookupIterator::WriteDataValue(Handle<Object> value) {
+ ASSERT(is_guaranteed_to_have_holder());
+ ASSERT(has_property_);
+ if (property_encoding_ == DICTIONARY) {
+ Handle<JSObject> holder = GetHolder();
+ NameDictionary* property_dictionary = holder->property_dictionary();
+ if (holder->IsGlobalObject()) {
+ Handle<PropertyCell> cell(
+ PropertyCell::cast(property_dictionary->ValueAt(number_)));
+ PropertyCell::SetValueInferType(cell, value);
+ } else {
+ property_dictionary->ValueAtPut(number_, *value);
+ }
+ } else if (property_details_.type() == v8::internal::FIELD) {
+ GetHolder()->WriteToField(number_, *value);
+ } else {
+ ASSERT_EQ(v8::internal::CONSTANT, property_details_.type());
+ }
+}
+
+
+void LookupIterator::InternalizeName() {
+ if (name_->IsUniqueName()) return;
+ name_ = factory()->InternalizeString(Handle<String>::cast(name_));
+}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/lookup.h Thu Jun 12 15:08:33 2014 UTC
+++ /branches/bleeding_edge/src/lookup.h Fri Jul 18 13:47:25 2014 UTC
@@ -92,11 +92,13 @@
Handle<Object> GetReceiver() const {
return Handle<Object>::cast(maybe_receiver_.ToHandleChecked());
}
+ Handle<Map> holder_map() const { return holder_map_; }
Handle<JSObject> GetHolder() const {
ASSERT(IsFound() && state_ != JSPROXY);
return Handle<JSObject>::cast(maybe_holder_.ToHandleChecked());
}
Handle<JSReceiver> GetRoot() const;
+ bool HolderIsReceiver() const;
/* Dynamically reduce the trapped types. */
void skip_interceptor() {
@@ -116,6 +118,10 @@
// below can be used. It ensures that we are able to provide a definite
// answer, and loads extra information about the property.
bool HasProperty();
+ void PrepareForDataProperty(Handle<Object> value);
+ void TransitionToDataProperty(Handle<Object> value,
+ PropertyAttributes attributes,
+ Object::StoreFromKeyed store_mode);
PropertyKind property_kind() const {
ASSERT(has_property_);
return property_kind_;
@@ -124,11 +130,18 @@
ASSERT(has_property_);
return property_details_;
}
+ int descriptor_number() const {
+ ASSERT(has_property_);
+ ASSERT_EQ(DESCRIPTOR, property_encoding_);
+ return number_;
+ }
Handle<Object> GetAccessors() const;
Handle<Object> GetDataValue() const;
+ void WriteDataValue(Handle<Object> value);
+
+ void InternalizeName();
/* JSPROXY */
-
Handle<JSProxy> GetJSProxy() const {
return Handle<JSProxy>::cast(maybe_holder_.ToHandleChecked());
}
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Thu Jul 17 09:44:37 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h Fri Jul 18 13:47:25 2014 UTC
@@ -2079,23 +2079,12 @@
}
-bool JSObject::TooManyFastProperties(StoreFromKeyed store_mode) {
- // Allow extra fast properties if the object has more than
- // kFastPropertiesSoftLimit in-object properties. When this is the case,
it is
- // very unlikely that the object is being used as a dictionary and there
is a
- // good chance that allowing more map transitions will be worth it.
- Map* map = this->map();
- if (map->unused_property_fields() != 0) return false;
-
- int inobject = map->inobject_properties();
-
- int limit;
- if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED) {
- limit = Max(inobject, kMaxFastProperties);
- } else {
- limit = Max(inobject, kFastPropertiesSoftLimit);
- }
- return properties()->length() > limit;
+bool Map::TooManyFastProperties(StoreFromKeyed store_mode) {
+ if (unused_property_fields() != 0) return false;
+ int minimum = store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ? 128 : 12;
+ int limit = Max(minimum, inobject_properties());
+ int external = NumberOfFields() - inobject_properties();
+ return external > limit;
}
=======================================
--- /branches/bleeding_edge/src/objects.cc Fri Jul 18 07:17:21 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc Fri Jul 18 13:47:25 2014 UTC
@@ -462,12 +462,9 @@
}
-MaybeHandle<Object> Object::SetPropertyWithCallback(Handle<Object>
receiver,
- Handle<Name> name,
- Handle<Object> value,
- Handle<JSObject>
holder,
- Handle<Object>
structure,
- StrictMode
strict_mode) {
+MaybeHandle<Object> Object::SetPropertyWithAccessor(
+ Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
+ Handle<JSObject> holder, Handle<Object> structure, StrictMode
strict_mode) {
Isolate* isolate = name->GetIsolate();
// We should never get here to initialize a const with the hole
@@ -605,48 +602,33 @@
}
-static bool FindAllCanWriteHolder(LookupResult* result,
- Handle<Name> name,
- bool check_prototype) {
- if (result->IsInterceptor()) {
- result->holder()->LookupOwnRealNamedProperty(name, result);
- }
-
- while (result->IsProperty()) {
- if (result->type() == CALLBACKS) {
- Object* callback_obj = result->GetCallbackObject();
- if (callback_obj->IsAccessorInfo()) {
- if (AccessorInfo::cast(callback_obj)->all_can_write()) return true;
+static bool FindAllCanWriteHolder(LookupIterator* it) {
+ it->skip_interceptor();
+ it->skip_access_check();
+ for (; it->IsFound(); it->Next()) {
+ if (it->state() == LookupIterator::PROPERTY && it->HasProperty() &&
+ it->property_kind() == LookupIterator::ACCESSOR) {
+ Handle<Object> accessors = it->GetAccessors();
+ if (accessors->IsAccessorInfo()) {
+ if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
}
}
- if (!check_prototype) break;
- result->holder()->LookupRealNamedPropertyInPrototypes(name, result);
}
return false;
}
MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
- Handle<JSObject> object,
- LookupResult* result,
- Handle<Name> name,
- Handle<Object> value,
- bool check_prototype,
- StrictMode strict_mode) {
- if (check_prototype && !result->IsProperty()) {
- object->LookupRealNamedPropertyInPrototypes(name, result);
- }
-
- if (FindAllCanWriteHolder(result, name, check_prototype)) {
- Handle<JSObject> holder(result->holder());
- Handle<Object> callbacks(result->GetCallbackObject(),
result->isolate());
- return SetPropertyWithCallback(
- object, name, value, holder, callbacks, strict_mode);
+ LookupIterator* it, Handle<Object> value, StrictMode strict_mode) {
+ Handle<JSObject> checked = Handle<JSObject>::cast(it->GetHolder());
+ if (FindAllCanWriteHolder(it)) {
+ return SetPropertyWithAccessor(it->GetReceiver(), it->name(), value,
+ it->GetHolder(), it->GetAccessors(),
+ strict_mode);
}
- Isolate* isolate = object->GetIsolate();
- isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_SET);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
return value;
}
@@ -1835,7 +1817,7 @@
if (value->IsJSFunction()) {
maybe_map = Map::CopyWithConstant(
handle(object->map()), name, value, attributes, flag);
- } else if (!object->TooManyFastProperties(store_mode)) {
+ } else if (!object->map()->TooManyFastProperties(store_mode)) {
Isolate* isolate = object->GetIsolate();
Representation representation = value->OptimalRepresentation();
maybe_map = Map::CopyWithField(
@@ -1967,23 +1949,6 @@
isolate->factory()->undefined_value(),
argc, args).Assert();
}
-
-
-MaybeHandle<Object> JSObject::SetPropertyPostInterceptor(
- Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode) {
- // Check own property, ignore interceptor.
- Isolate* isolate = object->GetIsolate();
- LookupResult result(isolate);
- object->LookupOwnRealNamedProperty(name, &result);
- if (!result.IsFound()) {
- object->map()->LookupTransition(*object, *name, &result);
- }
- return SetPropertyForResult(object, &result, name, value, strict_mode,
- MAY_BE_STORE_FROM_KEYED);
-}
static void ReplaceSlowProperty(Handle<JSObject> object,
@@ -2972,29 +2937,28 @@
}
-MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(
- Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode) {
+MaybeHandle<Object> JSObject::SetPropertyWithInterceptor(LookupIterator*
it,
+ Handle<Object>
value) {
// TODO(rossberg): Support symbols in the API.
- if (name->IsSymbol()) return value;
- 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", *object, *name));
- PropertyCallbackArguments args(
- isolate, interceptor->data(), *object, *object);
- v8::NamedPropertySetterCallback setter =
-
v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter());
- v8::Handle<v8::Value> result = args.Call(
- setter, v8::Utils::ToLocal(name_string),
v8::Utils::ToLocal(value));
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
- if (!result.IsEmpty()) return value;
- }
- return SetPropertyPostInterceptor(object, name, value, strict_mode);
+ if (it->name()->IsSymbol()) return value;
+
+ Handle<String> name_string = Handle<String>::cast(it->name());
+ Handle<JSObject> holder = it->GetHolder();
+ Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor());
+ if (interceptor->setter()->IsUndefined()) return MaybeHandle<Object>();
+
+ LOG(it->isolate(),
+ ApiNamedPropertyAccess("interceptor-named-set", *holder,
*name_string));
+ PropertyCallbackArguments args(it->isolate(), interceptor->data(),
*holder,
+ *holder);
+ v8::NamedPropertySetterCallback setter =
+ v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter());
+ v8::Handle<v8::Value> result = args.Call(
+ setter, v8::Utils::ToLocal(name_string), v8::Utils::ToLocal(value));
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
+ if (!result.IsEmpty()) return value;
+
+ return MaybeHandle<Object>();
}
@@ -3003,12 +2967,194 @@
Handle<Object> value,
StrictMode strict_mode,
StoreFromKeyed store_mode) {
- LookupResult result(object->GetIsolate());
- object->LookupOwn(name, &result, true);
- if (!result.IsFound()) {
- object->map()->LookupTransition(JSObject::cast(*object), *name,
&result);
+ LookupIterator it(object, name);
+ return Object::SetProperty(&it, value, strict_mode, store_mode);
+}
+
+
+MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
+ Handle<Object> value,
+ StrictMode strict_mode,
+ StoreFromKeyed store_mode) {
+ // Make sure that the top context does not change when doing callbacks or
+ // interceptor calls.
+ AssertNoContextChange ncc(it->isolate());
+
+ bool done = false;
+ for (; it->IsFound(); it->Next()) {
+ switch (it->state()) {
+ case LookupIterator::NOT_FOUND:
+ UNREACHABLE();
+
+ case LookupIterator::ACCESS_CHECK:
+ // TODO(verwaest): Remove the distinction. This is mostly bogus
since we
+ // don't know whether we'll want to fetch attributes or call a
setter
+ // until we find the property.
+ if (it->HasAccess(v8::ACCESS_SET)) break;
+ return JSObject::SetPropertyWithFailedAccessCheck(it, value,
+ strict_mode);
+
+ case LookupIterator::JSPROXY:
+ if (it->HolderIsReceiver()) {
+ return JSProxy::SetPropertyWithHandler(it->GetJSProxy(),
+ it->GetReceiver(),
it->name(),
+ value, strict_mode);
+ } else {
+ // TODO(verwaest): Use the MaybeHandle to indicate result.
+ bool has_result = false;
+ MaybeHandle<Object> maybe_result =
+ JSProxy::SetPropertyViaPrototypesWithHandler(
+ it->GetJSProxy(), it->GetReceiver(), it->name(), value,
+ strict_mode, &has_result);
+ if (has_result) return maybe_result;
+ done = true;
+ }
+ break;
+
+ case LookupIterator::INTERCEPTOR:
+ if (it->HolderIsReceiver()) {
+ MaybeHandle<Object> maybe_result =
+ JSObject::SetPropertyWithInterceptor(it, value);
+ if (!maybe_result.is_null()) return maybe_result;
+ if (it->isolate()->has_pending_exception()) return maybe_result;
+ } else {
+ Maybe<PropertyAttributes> maybe_attributes =
+ JSObject::GetPropertyAttributesWithInterceptor(
+ it->GetHolder(), it->GetReceiver(), it->name());
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
+ done = maybe_attributes.has_value;
+ if (done && (maybe_attributes.value & READ_ONLY) != 0) {
+ return WriteToReadOnlyProperty(it, value, strict_mode);
+ }
+ }
+ break;
+
+ case LookupIterator::PROPERTY:
+ if (!it->HasProperty()) break;
+ if (it->property_details().IsReadOnly()) {
+ return WriteToReadOnlyProperty(it, value, strict_mode);
+ }
+ switch (it->property_kind()) {
+ case LookupIterator::ACCESSOR:
+ if (it->HolderIsReceiver() ||
+ !it->GetAccessors()->IsDeclaredAccessorInfo()) {
+ return SetPropertyWithAccessor(it->GetReceiver(), it->name(),
+ value, it->GetHolder(),
+ it->GetAccessors(),
strict_mode);
+ }
+ break;
+ case LookupIterator::DATA:
+ if (it->HolderIsReceiver()) return SetDataProperty(it, value);
+ }
+ done = true;
+ break;
+ }
+
+ if (done) break;
}
- return SetProperty(object, &result, name, value, strict_mode,
store_mode);
+
+ return AddDataProperty(it, value, NONE, strict_mode, store_mode);
+}
+
+
+MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it,
+ Handle<Object> value,
+ StrictMode
strict_mode) {
+ if (strict_mode != STRICT) return value;
+
+ Handle<Object> args[] = {it->name(), it->GetReceiver()};
+ Handle<Object> error = it->factory()->NewTypeError(
+ "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
+ return it->isolate()->Throw<Object>(error);
+}
+
+
+MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
+ Handle<Object> value) {
+ // Proxies are handled on the WithHandler path. Other non-JSObjects
cannot
+ // have own properties.
+ Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
+
+ // Store on the holder which may be hidden behind the receiver.
+ ASSERT(it->HolderIsReceiver());
+
+ // Old value for the observation change record.
+ // Fetch before transforming the object since the encoding may become
+ // incompatible with what's cached in |it|.
+ bool is_observed =
+ receiver->map()->is_observed() &&
+ !it->name().is_identical_to(it->factory()->hidden_string());
+ MaybeHandle<Object> maybe_old;
+ if (is_observed) maybe_old = it->GetDataValue();
+
+ // Possibly migrate to the most up-to-date map that will be able to store
+ // |value| under it->name().
+ it->PrepareForDataProperty(value);
+
+ // Write the property value.
+ it->WriteDataValue(value);
+
+ // Send the change record if there are observers.
+ if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
+ JSObject::EnqueueChangeRecord(receiver, "update", it->name(),
+ maybe_old.ToHandleChecked());
+ }
+
+ return value;
+}
+
+
+MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
+ Handle<Object> value,
+ PropertyAttributes attributes,
+ StrictMode strict_mode,
+ StoreFromKeyed store_mode) {
+ ASSERT(!it->GetReceiver()->IsJSProxy());
+ // Transitions to data properties of value wrappers are not observable.
+ if (!it->GetReceiver()->IsJSObject()) return value;
+ Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
+
+ // If the receiver is a JSGlobalProxy, store on the prototype
(JSGlobalObject)
+ // instead. If the prototype is Null, the proxy is detached.
+ if (receiver->IsJSGlobalProxy()) {
+ // Trying to assign to a detached proxy.
+ PrototypeIterator iter(it->isolate(), receiver);
+ if (iter.IsAtEnd()) return value;
+ receiver =
+ Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter));
+ }
+
+ if (!receiver->map()->is_extensible()) {
+ if (strict_mode == SLOPPY) return value;
+
+ Handle<Object> args[1] = {it->name()};
+ Handle<Object> error = it->factory()->NewTypeError(
+ "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
+ return it->isolate()->Throw<Object>(error);
+ }
+
+ // Possibly migrate to the most up-to-date map that will be able to store
+ // |value| under it->name() with |attributes|.
+ it->TransitionToDataProperty(value, attributes, store_mode);
+
+ // TODO(verwaest): Encapsulate dictionary handling better.
+ if (receiver->map()->is_dictionary_map()) {
+ // TODO(verwaest): Probably should ensure this is done beforehand.
+ it->InternalizeName();
+ JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
+ } else {
+ // Write the property value.
+ it->WriteDataValue(value);
+ }
+
+ // Send the change record if there are observers.
+ if (receiver->map()->is_observed() &&
+ !it->name().is_identical_to(it->factory()->hidden_string())) {
+ JSObject::EnqueueChangeRecord(receiver, "add", it->name(),
+ it->factory()->the_hole_value());
+ }
+
+ return value;
}
@@ -3047,66 +3193,6 @@
*found = false;
return isolate->factory()->the_hole_value();
}
-
-
-MaybeHandle<Object> JSObject::SetPropertyViaPrototypes(
- Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode,
- bool* done) {
- Isolate* isolate = object->GetIsolate();
-
- *done = false;
- // We could not find an own 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);
- object->LookupRealNamedPropertyInPrototypes(name, &result);
- if (result.IsFound()) {
- switch (result.type()) {
- case NORMAL:
- case FIELD:
- case CONSTANT:
- *done = result.IsReadOnly();
- break;
- case INTERCEPTOR: {
- LookupIterator it(object, name, handle(result.holder()));
- PropertyAttributes attr = GetPropertyAttributes(&it);
- *done = !!(attr & READ_ONLY);
- break;
- }
- case CALLBACKS: {
- *done = true;
- if (!result.IsReadOnly()) {
- Handle<Object> callback_object(result.GetCallbackObject(),
isolate);
- return SetPropertyWithCallback(object, name, value,
- handle(result.holder()),
- callback_object, strict_mode);
- }
- break;
- }
- case HANDLER: {
- Handle<JSProxy> proxy(result.proxy());
- return JSProxy::SetPropertyViaPrototypesWithHandler(
- proxy, object, name, value, strict_mode, done);
- }
- case NONEXISTENT:
- UNREACHABLE();
- break;
- }
- }
-
- // If we get here with *done true, we have encountered a read-only
property.
- if (*done) {
- if (strict_mode == SLOPPY) return value;
- Handle<Object> args[] = { name, object };
- Handle<Object> error = isolate->factory()->NewTypeError(
- "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
- return isolate->Throw<Object>(error);
- }
- return isolate->factory()->the_hole_value();
-}
void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
@@ -3506,23 +3592,6 @@
}
result->NotFound();
}
-
-
-MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
- LookupResult* result,
- Handle<Name> key,
- Handle<Object> value,
- StrictMode strict_mode,
- StoreFromKeyed store_mode) {
- if (result->IsHandler()) {
- return JSProxy::SetPropertyWithHandler(handle(result->proxy()),
object, key,
- value, strict_mode);
- } else {
- return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object),
- result, key, value, strict_mode,
- store_mode);
- }
-}
bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name>
name) {
@@ -3546,12 +3615,11 @@
}
-MaybeHandle<Object> JSProxy::SetPropertyWithHandler(
- Handle<JSProxy> proxy,
- Handle<JSReceiver> receiver,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode) {
+MaybeHandle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy,
+ Handle<Object>
receiver,
+ Handle<Name> name,
+ Handle<Object> value,
+ StrictMode
strict_mode) {
Isolate* isolate = proxy->GetIsolate();
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
@@ -3572,12 +3640,8 @@
MaybeHandle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
- Handle<JSProxy> proxy,
- Handle<JSReceiver> receiver,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode,
- bool* done) {
+ Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
+ Handle<Object> value, StrictMode strict_mode, bool* done) {
Isolate* isolate = proxy->GetIsolate();
Handle<Object> handler(proxy->handler(), isolate); // Trap might morph
proxy.
@@ -3996,7 +4060,7 @@
Handle<Object> value,
PropertyAttributes attributes) {
Handle<JSObject> object(lookup->holder());
- if (object->TooManyFastProperties()) {
+ if
(object->map()->TooManyFastProperties(Object::MAY_BE_STORE_FROM_KEYED)) {
JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
}
@@ -4032,140 +4096,6 @@
ConvertAndSetOwnProperty(lookup, name, value, attributes);
}
}
-
-
-MaybeHandle<Object> JSObject::SetPropertyForResult(
- Handle<JSObject> object,
- LookupResult* lookup,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode,
- StoreFromKeyed store_mode) {
- ASSERT(!value->IsTheHole());
- Isolate* isolate = object->GetIsolate();
-
- // Make sure that the top context does not change when doing callbacks or
- // interceptor calls.
- AssertNoContextChange ncc(isolate);
-
- // Optimization for 2-byte strings often used as keys in a decompression
- // dictionary. We internalize these short keys to avoid constantly
- // reallocating them.
- if (name->IsString() && !name->IsInternalizedString() &&
- Handle<String>::cast(name)->length() <= 2) {
- name =
isolate->factory()->InternalizeString(Handle<String>::cast(name));
- }
-
- // Check access rights if needed.
- if (object->IsAccessCheckNeeded()) {
- if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
- return SetPropertyWithFailedAccessCheck(object, lookup, name, value,
- true, strict_mode);
- }
- }
-
- if (object->IsJSGlobalProxy()) {
- PrototypeIterator iter(isolate, object);
- if (iter.IsAtEnd()) return value;
- ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
- return SetPropertyForResult(
- Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
lookup,
- name, value, strict_mode, store_mode);
- }
-
- ASSERT(!lookup->IsFound() || lookup->holder() == *object ||
- lookup->holder()->map()->is_hidden_prototype());
-
- if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) {
- bool done = false;
- Handle<Object> result_object;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, result_object,
- SetPropertyViaPrototypes(object, name, value, strict_mode, &done),
- Object);
- if (done) return result_object;
- }
-
- if (!lookup->IsFound()) {
- // Neither properties nor transitions found.
- return AddPropertyInternal(object, name, value, NONE, strict_mode,
- store_mode);
- }
-
- if (lookup->IsProperty() && lookup->IsReadOnly()) {
- if (strict_mode == STRICT) {
- Handle<Object> args[] = { name, object };
- Handle<Object> error = isolate->factory()->NewTypeError(
- "strict_read_only_property", HandleVector(args,
ARRAY_SIZE(args)));
- return isolate->Throw<Object>(error);
- } else {
- return value;
- }
- }
-
- Handle<Object> old_value = isolate->factory()->the_hole_value();
- bool is_observed = object->map()->is_observed() &&
- *name != isolate->heap()->hidden_string();
- if (is_observed && lookup->IsDataProperty()) {
- old_value = Object::GetPropertyOrElement(object,
name).ToHandleChecked();
- }
-
- // This is a real property that is not read-only, or it is a
- // transition or null descriptor and there are no setters in the
prototypes.
- MaybeHandle<Object> maybe_result = value;
- if (lookup->IsTransition()) {
- maybe_result = SetPropertyUsingTransition(handle(lookup->holder()),
lookup,
- name, value, NONE);
- } else {
- switch (lookup->type()) {
- case NORMAL:
- SetNormalizedProperty(handle(lookup->holder()), lookup, value);
- break;
- case FIELD:
- SetPropertyToField(lookup, value);
- break;
- case CONSTANT:
- // Only replace the constant if necessary.
- if (*value == lookup->GetConstant()) return value;
- SetPropertyToField(lookup, value);
- break;
- case CALLBACKS: {
- Handle<Object> callback_object(lookup->GetCallbackObject(),
isolate);
- return SetPropertyWithCallback(object, name, value,
- handle(lookup->holder()),
- callback_object, strict_mode);
- }
- case INTERCEPTOR:
- maybe_result = SetPropertyWithInterceptor(handle(lookup->holder()),
- name, value,
strict_mode);
- break;
- case HANDLER:
- case NONEXISTENT:
- UNREACHABLE();
- }
- }
-
- Handle<Object> result;
- ASSIGN_RETURN_ON_EXCEPTION(isolate, result, maybe_result, Object);
-
- if (is_observed) {
- if (lookup->IsTransition()) {
- EnqueueChangeRecord(object, "add", name, old_value);
- } else {
- LookupResult new_lookup(isolate);
- object->LookupOwn(name, &new_lookup, true);
- if (new_lookup.IsDataProperty()) {
- Handle<Object> new_value =
- Object::GetPropertyOrElement(object, name).ToHandleChecked();
- if (!new_value->SameValue(*old_value)) {
- EnqueueChangeRecord(object, "update", name, old_value);
- }
- }
- }
- }
-
- return result;
-}
void JSObject::AddProperty(
@@ -4215,8 +4145,8 @@
// Check access rights if needed.
if (object->IsAccessCheckNeeded()) {
if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
- return SetPropertyWithFailedAccessCheck(object, &lookup, name, value,
- false, SLOPPY);
+ LookupIterator it(object, name, LookupIterator::CHECK_OWN);
+ return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
}
}
@@ -4288,13 +4218,9 @@
handling == DONT_FORCE_FIELD) {
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(
- isolate, result,
- JSObject::SetPropertyWithCallback(object,
- name,
- value,
- handle(lookup.holder()),
- callback,
- STRICT),
+ isolate, result, JSObject::SetPropertyWithAccessor(
+ object, name, value,
handle(lookup.holder()),
+ callback, STRICT),
Object);
if (attributes != lookup.GetAttributes()) {
@@ -4363,7 +4289,7 @@
Handle<Object> receiver,
Handle<Name> name) {
// TODO(rossberg): Support symbols in the API.
- if (name->IsSymbol()) return Maybe<PropertyAttributes>(ABSENT);
+ if (name->IsSymbol()) return Maybe<PropertyAttributes>();
Isolate* isolate = holder->GetIsolate();
HandleScope scope(isolate);
@@ -7365,6 +7291,97 @@
new_map->set_elements_kind(DICTIONARY_ELEMENTS);
return new_map;
}
+
+
+bool DescriptorArray::CanHoldValue(int descriptor, Object* value) {
+ PropertyDetails details = GetDetails(descriptor);
+ switch (details.type()) {
+ case FIELD:
+ return value->FitsRepresentation(details.representation()) &&
+ GetFieldType(descriptor)->NowContains(value);
+
+ case CONSTANT:
+ ASSERT(GetConstant(descriptor) != value ||
+ value->FitsRepresentation(details.representation()));
+ return GetConstant(descriptor) == value;
+
+ case CALLBACKS:
+ return false;
+
+ case NORMAL:
+ case INTERCEPTOR:
+ case HANDLER:
+ case NONEXISTENT:
+ break;
+ }
+
+ UNREACHABLE();
+ return false;
+}
+
+
+Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
+ Handle<Object> value) {
+ // Dictionaries can store any property value.
+ if (map->is_dictionary_map()) return map;
+
+ Handle<DescriptorArray> descriptors(map->instance_descriptors());
+
+ if (descriptors->CanHoldValue(descriptor, *value)) return map;
+
+ Isolate* isolate = map->GetIsolate();
+ Representation representation = value->OptimalRepresentation();
+ Handle<HeapType> type = value->OptimalType(isolate, representation);
+
+ return GeneralizeRepresentation(map, descriptor, representation, type,
+ FORCE_FIELD);
+}
+
+
+Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name>
name,
+ Handle<Object> value,
+ PropertyAttributes attributes,
+ StoreFromKeyed store_mode) {
+ // Cannot currently handle deprecated maps.
+ ASSERT(!map->is_deprecated());
+ // Dictionary maps can always have additional data properties.
+ if (map->is_dictionary_map()) return map;
+
+ int index = map->SearchTransition(*name);
+ if (index != TransitionArray::kNotFound) {
+ Handle<Map> transition(map->GetTransition(index));
+ int descriptor = transition->LastAdded();
+
+ // TODO(verwaest): Handle attributes better.
+ DescriptorArray* descriptors = transition->instance_descriptors();
+ if (descriptors->GetDetails(descriptor).attributes() != attributes) {
+ return CopyGeneralizeAllRepresentations(transition, descriptor,
+ FORCE_FIELD, attributes,
+ "attributes mismatch");
+ }
+
+ return Map::PrepareForDataProperty(transition, descriptor, value);
+ }
+
+ TransitionFlag flag = INSERT_TRANSITION;
+ MaybeHandle<Map> maybe_map;
+ if (value->IsJSFunction()) {
+ maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
+ } else if (!map->TooManyFastProperties(store_mode)) {
+ Isolate* isolate = name->GetIsolate();
+ Representation representation = value->OptimalRepresentation();
+ Handle<HeapType> type = value->OptimalType(isolate, representation);
+ maybe_map =
+ Map::CopyWithField(map, name, type, attributes, representation,
flag);
+ }
+
+ Handle<Map> result;
+ if (!maybe_map.ToHandle(&result)) {
+ return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES);
+ }
+
+ return result;
+}
Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
=======================================
--- /branches/bleeding_edge/src/objects.h Thu Jul 17 09:44:37 2014 UTC
+++ /branches/bleeding_edge/src/objects.h Fri Jul 18 13:47:25 2014 UTC
@@ -1375,6 +1375,13 @@
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
#undef IS_TYPE_FUNCTION_DECL
+ // A non-keyed store is of the form a.x = foo or a["x"] = foo whereas
+ // a keyed store is of the form a[expression] = foo.
+ enum StoreFromKeyed {
+ MAY_BE_STORE_FROM_KEYED,
+ CERTAINLY_NOT_STORE_FROM_KEYED
+ };
+
INLINE(bool IsFixedArrayBase() const);
INLINE(bool IsExternal() const);
INLINE(bool IsAccessorInfo() const);
@@ -1476,6 +1483,16 @@
void Lookup(Handle<Name> name, LookupResult* result);
MUST_USE_RESULT static MaybeHandle<Object> GetProperty(LookupIterator*
it);
+ MUST_USE_RESULT static MaybeHandle<Object> SetProperty(
+ LookupIterator* it, Handle<Object> value, StrictMode strict_mode,
+ StoreFromKeyed store_mode);
+ MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
+ LookupIterator* it, Handle<Object> value, StrictMode strict_mode);
+ MUST_USE_RESULT static MaybeHandle<Object> SetDataProperty(
+ LookupIterator* it, Handle<Object> value);
+ MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty(
+ LookupIterator* it, Handle<Object> value, PropertyAttributes
attributes,
+ StrictMode strict_mode, StoreFromKeyed store_mode);
MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
Handle<Object> object,
Handle<Name> key);
@@ -1492,12 +1509,9 @@
Handle<Name> name,
Handle<JSObject> holder,
Handle<Object> structure);
- MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithCallback(
- Handle<Object> receiver,
- Handle<Name> name,
- Handle<Object> value,
- Handle<JSObject> holder,
- Handle<Object> structure,
+ MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithAccessor(
+ Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
+ Handle<JSObject> holder, Handle<Object> structure,
StrictMode strict_mode);
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter(
@@ -1918,13 +1932,6 @@
FORCE_DELETION
};
- // A non-keyed store is of the form a.x = foo or a["x"] = foo whereas
- // a keyed store is of the form a[expression] = foo.
- enum StoreFromKeyed {
- MAY_BE_STORE_FROM_KEYED,
- CERTAINLY_NOT_STORE_FROM_KEYED
- };
-
// Internal properties (e.g. the hidden properties dictionary) might
// be added even though the receiver is non-extensible.
enum ExtensibilityCheck {
@@ -2136,18 +2143,7 @@
uint32_t limit);
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithInterceptor(
- Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode);
-
- MUST_USE_RESULT static MaybeHandle<Object> SetPropertyForResult(
- Handle<JSObject> object,
- LookupResult* result,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode,
- StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
+ LookupIterator* it, Handle<Object> value);
// SetLocalPropertyIgnoreAttributes converts callbacks to fields. We
need to
// grant an exemption to ExecutableAccessor callbacks in some cases.
@@ -2573,12 +2569,6 @@
Object* SlowReverseLookup(Object* value);
- // Maximal number of fast properties for the JSObject. Used to
- // restrict the number of map transitions to avoid an explosion in
- // the number of maps for objects used as dictionaries.
- inline bool TooManyFastProperties(
- StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
-
// Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
// Also maximal value of JSArray's length property.
static const uint32_t kMaxElementCount = 0xffffffffu;
@@ -2606,8 +2596,6 @@
// "global.Object" and not to arbitrary other JSObject maps.
static const int kInitialGlobalObjectUnusedPropertiesCount = 4;
- static const int kFastPropertiesSoftLimit = 12;
- static const int kMaxFastProperties = 128;
static const int kMaxInstanceSize = 255 * kPointerSize;
// When extending the backing storage for property values, we increase
// its size by more than the 1 entry necessary, so sequentially adding
fields
@@ -2734,21 +2722,6 @@
StrictMode strict_mode,
bool check_prototype = true);
- // 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 throw and return an empty handle with '*done==true'.
- MUST_USE_RESULT static MaybeHandle<Object> SetPropertyViaPrototypes(
- Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode,
- bool* done);
- MUST_USE_RESULT static MaybeHandle<Object> SetPropertyPostInterceptor(
- Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode);
MUST_USE_RESULT static MaybeHandle<Object> SetPropertyUsingTransition(
Handle<JSObject> object,
LookupResult* lookup,
@@ -2756,12 +2729,7 @@
Handle<Object> value,
PropertyAttributes attributes);
MUST_USE_RESULT static MaybeHandle<Object>
SetPropertyWithFailedAccessCheck(
- Handle<JSObject> object,
- LookupResult* result,
- Handle<Name> name,
- Handle<Object> value,
- bool check_prototype,
- StrictMode strict_mode);
+ LookupIterator* it, Handle<Object> value, StrictMode strict_mode);
// Add a property to an object.
MUST_USE_RESULT static MaybeHandle<Object> AddPropertyInternal(
@@ -3452,6 +3420,8 @@
FixedArray* new_cache,
Object* new_index_cache);
+ bool CanHoldValue(int descriptor, Object* value);
+
// Accessors for fetching instance descriptor at descriptor number.
inline Name* GetKey(int descriptor_number);
inline Object** GetKeySlot(int descriptor_number);
@@ -6334,6 +6304,10 @@
StoreMode store_mode,
const char* reason);
+ static Handle<Map> PrepareForDataProperty(Handle<Map> old_map,
+ int descriptor_number,
+ Handle<Object> value);
+
static Handle<Map> Normalize(Handle<Map> map, PropertyNormalizationMode
mode);
// Returns the constructor name (the name (possibly, inferred name) of
the
@@ -6526,6 +6500,15 @@
static Handle<Map> CopyForObserved(Handle<Map> map);
static Handle<Map> CopyForFreeze(Handle<Map> map);
+ // Maximal number of fast properties. Used to restrict the number of map
+ // transitions to avoid an explosion in the number of maps for objects
used as
+ // dictionaries.
+ inline bool TooManyFastProperties(StoreFromKeyed store_mode);
+ static Handle<Map> TransitionToDataProperty(Handle<Map> map,
+ Handle<Name> name,
+ Handle<Object> value,
+ PropertyAttributes
attributes,
+ StoreFromKeyed store_mode);
inline void AppendDescriptor(Descriptor* desc);
@@ -6834,6 +6817,9 @@
Handle<Object> prototype,
Handle<Map> target_map);
+ static const int kFastPropertiesSoftLimit = 12;
+ static const int kMaxFastProperties = 128;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
};
@@ -9968,12 +9954,8 @@
// otherwise set it to false.
MUST_USE_RESULT
static MaybeHandle<Object> SetPropertyViaPrototypesWithHandler(
- Handle<JSProxy> proxy,
- Handle<JSReceiver> receiver,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode,
- bool* done);
+ Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
+ Handle<Object> value, StrictMode strict_mode, bool* done);
static PropertyAttributes GetPropertyAttributesWithHandler(
Handle<JSProxy> proxy,
@@ -9983,6 +9965,9 @@
Handle<JSProxy> proxy,
Handle<JSReceiver> receiver,
uint32_t index);
+ MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithHandler(
+ Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
+ Handle<Object> value, StrictMode strict_mode);
// Turn the proxy into an (empty) JSObject.
static void Fix(Handle<JSProxy> proxy);
@@ -10022,12 +10007,6 @@
private:
friend class JSReceiver;
- MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithHandler(
- Handle<JSProxy> proxy,
- Handle<JSReceiver> receiver,
- Handle<Name> name,
- Handle<Object> value,
- StrictMode strict_mode);
MUST_USE_RESULT static inline MaybeHandle<Object> SetElementWithHandler(
Handle<JSProxy> proxy,
Handle<JSReceiver> receiver,
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc Thu Jul 17 09:44:37 2014 UTC
+++ /branches/bleeding_edge/src/stub-cache.cc Fri Jul 18 13:47:25 2014 UTC
@@ -581,8 +581,8 @@
ASSERT(receiver->HasNamedInterceptor());
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, JSObject::SetPropertyWithInterceptor(
- receiver, name, value, ic.strict_mode()));
+ isolate, result,
+ JSObject::SetProperty(receiver, name, value, ic.strict_mode()));
return *result;
}
=======================================
--- /branches/bleeding_edge/src/v8natives.js Mon Jul 14 14:05:30 2014 UTC
+++ /branches/bleeding_edge/src/v8natives.js Fri Jul 18 13:47:25 2014 UTC
@@ -1322,7 +1322,9 @@
for (var i = 0; i < names.length; i++) {
var name = names[i];
var desc = GetOwnPropertyJS(obj, name);
- if (desc.isConfigurable()) return false;
+ if (desc.isConfigurable()) {
+ return false;
+ }
}
return true;
}
=======================================
--- /branches/bleeding_edge/test/cctest/test-decls.cc Mon Jul 14 14:01:04
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-decls.cc Fri Jul 18 13:47:25
2014 UTC
@@ -423,11 +423,8 @@
// Sanity check to make sure that the holder of the interceptor
// really is the prototype object.
{ ExistsInPrototypeContext context;
- context.Check("this.x = 87; this.x",
- 0,
- 0,
- 0,
- EXPECT_RESULT, Number::New(CcTest::isolate(), 87));
+ context.Check("this.x = 87; this.x", 0, 0, 1, EXPECT_RESULT,
+ Number::New(CcTest::isolate(), 87));
}
{ ExistsInPrototypeContext context;
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.