summaryrefslogtreecommitdiff
path: root/deps/v8/src/runtime/runtime-object.cc
diff options
context:
space:
mode:
authorAli Ijaz Sheikh <ofrobots@google.com>2015-08-23 06:09:40 -0700
committerRod Vagg <rod@vagg.org>2015-09-06 21:38:01 +1000
commit9fddd83cf9adf505bce2e2373881df0c4d41b261 (patch)
tree4272ce14c10fea496af2e78fc6debb187d613451 /deps/v8/src/runtime/runtime-object.cc
parent46b7d151674d138e7ea4342d5f3ada1208b87ff2 (diff)
downloadandroid-node-v8-9fddd83cf9adf505bce2e2373881df0c4d41b261.tar.gz
android-node-v8-9fddd83cf9adf505bce2e2373881df0c4d41b261.tar.bz2
android-node-v8-9fddd83cf9adf505bce2e2373881df0c4d41b261.zip
deps: upgrade V8 to 4.5.103.24
Upgrade to the latest branch-head for V8 4.5. For the full commit log see https://github.com/v8/v8-git-mirror/commits/4.5.103.24 PR-URL: https://github.com/nodejs/node/pull/2509 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/runtime/runtime-object.cc')
-rw-r--r--deps/v8/src/runtime/runtime-object.cc626
1 files changed, 252 insertions, 374 deletions
diff --git a/deps/v8/src/runtime/runtime-object.cc b/deps/v8/src/runtime/runtime-object.cc
index 79950c6218..da1ec4977b 100644
--- a/deps/v8/src/runtime/runtime-object.cc
+++ b/deps/v8/src/runtime/runtime-object.cc
@@ -17,40 +17,25 @@ namespace internal {
// Returns a single character string where first character equals
// string->Get(index).
static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
- if (index < static_cast<uint32_t>(string->length())) {
- Factory* factory = string->GetIsolate()->factory();
- return factory->LookupSingleCharacterStringFromCode(
- String::Flatten(string)->Get(index));
- }
- return Execution::CharAt(string, index);
+ DCHECK_LT(index, static_cast<uint32_t>(string->length()));
+ Factory* factory = string->GetIsolate()->factory();
+ return factory->LookupSingleCharacterStringFromCode(
+ String::Flatten(string)->Get(index));
}
MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
Handle<Object> object,
- uint32_t index) {
+ uint32_t index,
+ LanguageMode language_mode) {
// Handle [] indexing on Strings
- if (object->IsString()) {
+ if (object->IsString() &&
+ index < static_cast<uint32_t>(String::cast(*object)->length())) {
Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
if (!result->IsUndefined()) return result;
}
- // Handle [] indexing on String objects
- if (object->IsStringObjectWithCharacterAt(index)) {
- Handle<JSValue> js_value = Handle<JSValue>::cast(object);
- Handle<Object> result =
- GetCharAt(Handle<String>(String::cast(js_value->value())), index);
- if (!result->IsUndefined()) return result;
- }
-
- Handle<Object> result;
- if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
- PrototypeIterator iter(isolate, object);
- return Object::GetElement(isolate, PrototypeIterator::GetCurrent(iter),
- index);
- } else {
- return Object::GetElement(isolate, object, index);
- }
+ return Object::GetElement(isolate, object, index, language_mode);
}
@@ -68,18 +53,19 @@ MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) {
MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
Handle<Object> object,
- Handle<Object> key) {
+ Handle<Object> key,
+ LanguageMode language_mode) {
if (object->IsUndefined() || object->IsNull()) {
- Handle<Object> args[2] = {key, object};
- THROW_NEW_ERROR(isolate, NewTypeError("non_object_property_load",
- HandleVector(args, 2)),
- Object);
+ THROW_NEW_ERROR(
+ isolate,
+ NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
+ Object);
}
// Check if the given key is an array index.
- uint32_t index;
+ uint32_t index = 0;
if (key->ToArrayIndex(&index)) {
- return GetElementOrCharAt(isolate, object, index);
+ return GetElementOrCharAt(isolate, object, index, language_mode);
}
// Convert the key to a name - possibly by calling back into JavaScript.
@@ -88,158 +74,140 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
// Check if the name is trivially convertible to an index and get
// the element if so.
+ // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and
+ // remove the special casing here.
if (name->AsArrayIndex(&index)) {
return GetElementOrCharAt(isolate, object, index);
} else {
- return Object::GetProperty(object, name);
+ return Object::GetProperty(object, name, language_mode);
}
}
-MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
- Handle<Object> object,
- Handle<Object> key,
- Handle<Object> value,
- LanguageMode language_mode) {
- if (object->IsUndefined() || object->IsNull()) {
- Handle<Object> args[2] = {key, object};
- THROW_NEW_ERROR(isolate, NewTypeError("non_object_property_store",
- HandleVector(args, 2)),
- Object);
- }
-
- if (object->IsJSProxy()) {
- Handle<Object> name_object;
- if (key->IsSymbol()) {
- name_object = key;
- } else {
- ASSIGN_RETURN_ON_EXCEPTION(isolate, name_object,
- Execution::ToString(isolate, key), Object);
- }
- Handle<Name> name = Handle<Name>::cast(name_object);
- return Object::SetProperty(Handle<JSProxy>::cast(object), name, value,
- language_mode);
- }
-
- // Check if the given key is an array index.
- uint32_t index;
- if (key->ToArrayIndex(&index)) {
- // TODO(verwaest): Support non-JSObject receivers.
- if (!object->IsJSObject()) return value;
- Handle<JSObject> js_object = Handle<JSObject>::cast(object);
-
- // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
- // of a string using [] notation. We need to support this too in
- // JavaScript.
- // In the case of a String object we just need to redirect the assignment to
- // the underlying string if the index is in range. Since the underlying
- // string does nothing with the assignment then we can ignore such
- // assignments.
- if (js_object->IsStringObjectWithCharacterAt(index)) {
- return value;
- }
-
- JSObject::ValidateElements(js_object);
- if (js_object->HasExternalArrayElements() ||
- js_object->HasFixedTypedArrayElements()) {
- if (!value->IsNumber() && !value->IsUndefined()) {
- ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
- Execution::ToNumber(isolate, value), Object);
+MaybeHandle<Object> Runtime::KeyedGetObjectProperty(
+ Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
+ LanguageMode language_mode) {
+ // Fast cases for getting named properties of the receiver JSObject
+ // itself.
+ //
+ // The global proxy objects has to be excluded since LookupOwn on
+ // the global proxy object can return a valid result even though the
+ // global proxy object never has properties. This is the case
+ // because the global proxy object forwards everything to its hidden
+ // prototype including own lookups.
+ //
+ // Additionally, we need to make sure that we do not cache results
+ // for objects that require access checks.
+ if (receiver_obj->IsJSObject()) {
+ if (!receiver_obj->IsJSGlobalProxy() &&
+ !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
+ DisallowHeapAllocation no_allocation;
+ Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
+ Handle<Name> key = Handle<Name>::cast(key_obj);
+ if (receiver->IsGlobalObject()) {
+ // Attempt dictionary lookup.
+ GlobalDictionary* dictionary = receiver->global_dictionary();
+ int entry = dictionary->FindEntry(key);
+ if (entry != GlobalDictionary::kNotFound) {
+ DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
+ PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
+ if (cell->property_details().type() == DATA) {
+ Object* value = cell->value();
+ if (!value->IsTheHole()) return Handle<Object>(value, isolate);
+ // If value is the hole (meaning, absent) do the general lookup.
+ }
+ }
+ } else if (!receiver->HasFastProperties()) {
+ // Attempt dictionary lookup.
+ NameDictionary* dictionary = receiver->property_dictionary();
+ int entry = dictionary->FindEntry(key);
+ if ((entry != NameDictionary::kNotFound) &&
+ (dictionary->DetailsAt(entry).type() == DATA)) {
+ Object* value = dictionary->ValueAt(entry);
+ return Handle<Object>(value, isolate);
+ }
}
- }
-
- MaybeHandle<Object> result = JSObject::SetElement(
- js_object, index, value, NONE, language_mode, true, SET_PROPERTY);
- JSObject::ValidateElements(js_object);
-
- return result.is_null() ? result : value;
- }
-
- if (key->IsName()) {
- Handle<Name> name = Handle<Name>::cast(key);
- if (name->AsArrayIndex(&index)) {
- // TODO(verwaest): Support non-JSObject receivers.
- if (!object->IsJSObject()) return value;
- Handle<JSObject> js_object = Handle<JSObject>::cast(object);
- if (js_object->HasExternalArrayElements()) {
- if (!value->IsNumber() && !value->IsUndefined()) {
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, value, Execution::ToNumber(isolate, value), Object);
+ } else if (key_obj->IsSmi()) {
+ // JSObject without a name key. If the key is a Smi, check for a
+ // definite out-of-bounds access to elements, which is a strong indicator
+ // that subsequent accesses will also call the runtime. Proactively
+ // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
+ // doubles for those future calls in the case that the elements would
+ // become FAST_DOUBLE_ELEMENTS.
+ Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
+ ElementsKind elements_kind = js_object->GetElementsKind();
+ if (IsFastDoubleElementsKind(elements_kind)) {
+ if (Smi::cast(*key_obj)->value() >= js_object->elements()->length()) {
+ elements_kind = IsFastHoleyElementsKind(elements_kind)
+ ? FAST_HOLEY_ELEMENTS
+ : FAST_ELEMENTS;
+ JSObject::TransitionElementsKind(js_object, elements_kind);
}
+ } else {
+ DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
+ !IsFastElementsKind(elements_kind));
}
- return JSObject::SetElement(js_object, index, value, NONE, language_mode,
- true, SET_PROPERTY);
- } else {
- if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
- return Object::SetProperty(object, name, value, language_mode);
+ }
+ } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
+ // Fast case for string indexing using [] with a smi index.
+ Handle<String> str = Handle<String>::cast(receiver_obj);
+ int index = Handle<Smi>::cast(key_obj)->value();
+ if (index >= 0 && index < str->length()) {
+ return GetCharAt(str, index);
}
}
- // Call-back into JavaScript to convert the key to a string.
- Handle<Object> converted;
- ASSIGN_RETURN_ON_EXCEPTION(isolate, converted,
- Execution::ToString(isolate, key), Object);
- Handle<String> name = Handle<String>::cast(converted);
-
- if (name->AsArrayIndex(&index)) {
- // TODO(verwaest): Support non-JSObject receivers.
- if (!object->IsJSObject()) return value;
- Handle<JSObject> js_object = Handle<JSObject>::cast(object);
- return JSObject::SetElement(js_object, index, value, NONE, language_mode,
- true, SET_PROPERTY);
- }
- return Object::SetProperty(object, name, value, language_mode);
+ // Fall back to GetObjectProperty.
+ return GetObjectProperty(isolate, receiver_obj, key_obj, language_mode);
}
-MaybeHandle<Object> Runtime::DefineObjectProperty(Handle<JSObject> js_object,
+MaybeHandle<Object> Runtime::DeleteObjectProperty(Isolate* isolate,
+ Handle<JSReceiver> receiver,
Handle<Object> key,
- Handle<Object> value,
- PropertyAttributes attrs) {
- Isolate* isolate = js_object->GetIsolate();
+ LanguageMode language_mode) {
// Check if the given key is an array index.
- uint32_t index;
+ uint32_t index = 0;
if (key->ToArrayIndex(&index)) {
- // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
- // of a string using [] notation. We need to support this too in
- // JavaScript.
- // In the case of a String object we just need to redirect the assignment to
- // the underlying string if the index is in range. Since the underlying
- // string does nothing with the assignment then we can ignore such
- // assignments.
- if (js_object->IsStringObjectWithCharacterAt(index)) {
- return value;
- }
+ return JSReceiver::DeleteElement(receiver, index, language_mode);
+ }
- return JSObject::SetElement(js_object, index, value, attrs, SLOPPY, false,
- DEFINE_PROPERTY);
+ Handle<Name> name;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
+
+ return JSReceiver::DeletePropertyOrElement(receiver, name, language_mode);
+}
+
+
+MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
+ Handle<Object> object,
+ Handle<Object> key,
+ Handle<Object> value,
+ LanguageMode language_mode) {
+ if (object->IsUndefined() || object->IsNull()) {
+ THROW_NEW_ERROR(
+ isolate,
+ NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
+ Object);
}
- if (key->IsName()) {
- Handle<Name> name = Handle<Name>::cast(key);
- if (name->AsArrayIndex(&index)) {
- return JSObject::SetElement(js_object, index, value, attrs, SLOPPY, false,
- DEFINE_PROPERTY);
- } else {
- if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
- return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value,
- attrs);
- }
+ // Check if the given key is an array index.
+ uint32_t index = 0;
+ if (key->ToArrayIndex(&index)) {
+ // TODO(verwaest): Support other objects as well.
+ if (!object->IsJSReceiver()) return value;
+ return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index,
+ value, language_mode);
}
- // Call-back into JavaScript to convert the key to a string.
- Handle<Object> converted;
- ASSIGN_RETURN_ON_EXCEPTION(isolate, converted,
- Execution::ToString(isolate, key), Object);
- Handle<String> name = Handle<String>::cast(converted);
+ Handle<Name> name;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
- if (name->AsArrayIndex(&index)) {
- return JSObject::SetElement(js_object, index, value, attrs, SLOPPY, false,
- DEFINE_PROPERTY);
- } else {
- return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value,
- attrs);
- }
+ LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
+ // TODO(verwaest): Support other objects as well.
+ if (it.IsElement() && !object->IsJSReceiver()) return value;
+ return Object::SetProperty(&it, value, language_mode,
+ Object::MAY_BE_STORE_FROM_KEYED);
}
@@ -360,61 +328,35 @@ MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
Factory* factory = isolate->factory();
PropertyAttributes attrs;
- uint32_t index = 0;
- Handle<Object> value;
- MaybeHandle<AccessorPair> maybe_accessors;
- // TODO(verwaest): Unify once indexed properties can be handled by the
- // LookupIterator.
- if (name->AsArrayIndex(&index)) {
- // Get attributes.
- Maybe<PropertyAttributes> maybe =
- JSReceiver::GetOwnElementAttribute(obj, index);
- if (!maybe.IsJust()) return MaybeHandle<Object>();
- attrs = maybe.FromJust();
- if (attrs == ABSENT) return factory->undefined_value();
-
- // Get AccessorPair if present.
- maybe_accessors = JSObject::GetOwnElementAccessorPair(obj, index);
-
- // Get value if not an AccessorPair.
- if (maybe_accessors.is_null()) {
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, value, Runtime::GetElementOrCharAt(isolate, obj, index),
- Object);
- }
- } else {
- // Get attributes.
- LookupIterator it(obj, name, LookupIterator::HIDDEN);
- Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
- if (!maybe.IsJust()) return MaybeHandle<Object>();
- attrs = maybe.FromJust();
- if (attrs == ABSENT) return factory->undefined_value();
-
- // Get AccessorPair if present.
- if (it.state() == LookupIterator::ACCESSOR &&
- it.GetAccessors()->IsAccessorPair()) {
- maybe_accessors = Handle<AccessorPair>::cast(it.GetAccessors());
- }
+ // Get attributes.
+ LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name,
+ LookupIterator::HIDDEN);
+ Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
+
+ if (!maybe.IsJust()) return MaybeHandle<Object>();
+ attrs = maybe.FromJust();
+ if (attrs == ABSENT) return factory->undefined_value();
- // Get value if not an AccessorPair.
- if (maybe_accessors.is_null()) {
- ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
- Object);
- }
- }
DCHECK(!isolate->has_pending_exception());
Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
- elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(!maybe_accessors.is_null()));
- Handle<AccessorPair> accessors;
- if (maybe_accessors.ToHandle(&accessors)) {
+ bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
+ it.GetAccessors()->IsAccessorPair();
+ elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
+
+ if (is_accessor_pair) {
+ Handle<AccessorPair> accessors =
+ Handle<AccessorPair>::cast(it.GetAccessors());
Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
elms->set(GETTER_INDEX, *getter);
elms->set(SETTER_INDEX, *setter);
} else {
+ Handle<Object> value;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
+ Object);
elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
elms->set(VALUE_INDEX, *value);
}
@@ -457,43 +399,7 @@ RUNTIME_FUNCTION(Runtime_IsExtensible) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(JSObject, obj, 0);
- if (obj->IsJSGlobalProxy()) {
- PrototypeIterator iter(isolate, obj);
- if (iter.IsAtEnd()) return isolate->heap()->false_value();
- DCHECK(iter.GetCurrent()->IsJSGlobalObject());
- obj = JSObject::cast(iter.GetCurrent());
- }
- return isolate->heap()->ToBoolean(obj->map()->is_extensible());
-}
-
-
-RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
- Handle<Map> old_map(object->map());
- bool needs_access_checks = old_map->is_access_check_needed();
- if (needs_access_checks) {
- // Copy map so it won't interfere constructor's initial map.
- Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
- new_map->set_is_access_check_needed(false);
- JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
- }
- return isolate->heap()->ToBoolean(needs_access_checks);
-}
-
-
-RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
- Handle<Map> old_map(object->map());
- RUNTIME_ASSERT(!old_map->is_access_check_needed());
- // Copy map so it won't interfere constructor's initial map.
- Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
- new_map->set_is_access_check_needed(true);
- JSObject::MigrateToMap(object, new_map);
- return isolate->heap()->undefined_value();
+ return isolate->heap()->ToBoolean(obj->IsExtensible());
}
@@ -548,28 +454,27 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, Runtime::GetObjectProperty(isolate, object, key));
+ isolate, result,
+ Runtime::GetObjectProperty(isolate, object, key, SLOPPY));
return *result;
}
-MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
- Handle<Object> object, ElementsKind to_kind, Isolate* isolate) {
+RUNTIME_FUNCTION(Runtime_GetPropertyStrong) {
HandleScope scope(isolate);
- if (!object->IsJSObject()) {
- isolate->ThrowIllegalOperation();
- return MaybeHandle<Object>();
- }
- ElementsKind from_kind =
- Handle<JSObject>::cast(object)->map()->elements_kind();
- if (Map::IsValidElementsTransition(from_kind, to_kind)) {
- JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
- return object;
- }
- isolate->ThrowIllegalOperation();
- return MaybeHandle<Object>();
+ DCHECK(args.length() == 2);
+
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Runtime::GetObjectProperty(isolate, object, key, STRONG));
+ return *result;
}
@@ -581,76 +486,25 @@ RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
- // Fast cases for getting named properties of the receiver JSObject
- // itself.
- //
- // The global proxy objects has to be excluded since LookupOwn on
- // the global proxy object can return a valid result even though the
- // global proxy object never has properties. This is the case
- // because the global proxy object forwards everything to its hidden
- // prototype including own lookups.
- //
- // Additionally, we need to make sure that we do not cache results
- // for objects that require access checks.
- if (receiver_obj->IsJSObject()) {
- if (!receiver_obj->IsJSGlobalProxy() &&
- !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
- DisallowHeapAllocation no_allocation;
- Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
- Handle<Name> key = Handle<Name>::cast(key_obj);
- if (!receiver->HasFastProperties()) {
- // Attempt dictionary lookup.
- NameDictionary* dictionary = receiver->property_dictionary();
- int entry = dictionary->FindEntry(key);
- if ((entry != NameDictionary::kNotFound) &&
- (dictionary->DetailsAt(entry).type() == DATA)) {
- Object* value = dictionary->ValueAt(entry);
- if (!receiver->IsGlobalObject()) return value;
- DCHECK(value->IsPropertyCell());
- value = PropertyCell::cast(value)->value();
- if (!value->IsTheHole()) return value;
- // If value is the hole (meaning, absent) do the general lookup.
- }
- }
- } else if (key_obj->IsSmi()) {
- // JSObject without a name key. If the key is a Smi, check for a
- // definite out-of-bounds access to elements, which is a strong indicator
- // that subsequent accesses will also call the runtime. Proactively
- // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
- // doubles for those future calls in the case that the elements would
- // become FAST_DOUBLE_ELEMENTS.
- Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
- ElementsKind elements_kind = js_object->GetElementsKind();
- if (IsFastDoubleElementsKind(elements_kind)) {
- Handle<Smi> key = Handle<Smi>::cast(key_obj);
- if (key->value() >= js_object->elements()->length()) {
- if (IsFastHoleyElementsKind(elements_kind)) {
- elements_kind = FAST_HOLEY_ELEMENTS;
- } else {
- elements_kind = FAST_ELEMENTS;
- }
- RETURN_FAILURE_ON_EXCEPTION(
- isolate, TransitionElements(js_object, elements_kind, isolate));
- }
- } else {
- DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
- !IsFastElementsKind(elements_kind));
- }
- }
- } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
- // Fast case for string indexing using [] with a smi index.
- Handle<String> str = Handle<String>::cast(receiver_obj);
- int index = args.smi_at(1);
- if (index >= 0 && index < str->length()) {
- return *GetCharAt(str, index);
- }
- }
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, SLOPPY));
+ return *result;
+}
+
+
+RUNTIME_FUNCTION(Runtime_KeyedGetPropertyStrong) {
+ HandleScope scope(isolate);
+ DCHECK(args.length() == 2);
+
+ CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
- // Fall back to GetObjectProperty.
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
- Runtime::GetObjectProperty(isolate, receiver_obj, key_obj));
+ Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, STRONG));
return *result;
}
@@ -660,14 +514,14 @@ RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
RUNTIME_ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
- CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
#ifdef DEBUG
uint32_t index = 0;
- DCHECK(!key->ToArrayIndex(&index));
- LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
+ DCHECK(!name->ToArrayIndex(&index));
+ LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
if (!maybe.IsJust()) return isolate->heap()->exception();
RUNTIME_ASSERT(!it.IsFound());
@@ -676,47 +530,77 @@ RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
- JSObject::SetOwnPropertyIgnoreAttributes(object, key, value, attrs));
+ JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs));
return *result;
}
-RUNTIME_FUNCTION(Runtime_SetProperty) {
+// Adds an element to an array.
+// This is used to create an indexed data property into an array.
+RUNTIME_FUNCTION(Runtime_AddElement) {
HandleScope scope(isolate);
- RUNTIME_ASSERT(args.length() == 4);
+ RUNTIME_ASSERT(args.length() == 3);
- CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
- CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
- LanguageMode language_mode = language_mode_arg;
+
+ uint32_t index = 0;
+ CHECK(key->ToArrayIndex(&index));
+
+#ifdef DEBUG
+ LookupIterator it(isolate, object, index,
+ LookupIterator::OWN_SKIP_INTERCEPTOR);
+ Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
+ if (!maybe.IsJust()) return isolate->heap()->exception();
+ RUNTIME_ASSERT(!it.IsFound());
+
+ if (object->IsJSArray()) {
+ Handle<JSArray> array = Handle<JSArray>::cast(object);
+ RUNTIME_ASSERT(!JSArray::WouldChangeReadOnlyLength(array, index));
+ }
+#endif
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
- Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
+ JSObject::SetOwnElementIgnoreAttributes(object, index, value, NONE));
return *result;
}
-// Adds an element to an array.
-// This is used to create an indexed data property into an array.
-RUNTIME_FUNCTION(Runtime_AddElement) {
+RUNTIME_FUNCTION(Runtime_AppendElement) {
+ HandleScope scope(isolate);
+ RUNTIME_ASSERT(args.length() == 2);
+
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
+
+ uint32_t index;
+ CHECK(array->length()->ToArrayIndex(&index));
+
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, JSObject::AddDataElement(array, index, value, NONE));
+ JSObject::ValidateElements(array);
+ return *array;
+}
+
+
+RUNTIME_FUNCTION(Runtime_SetProperty) {
HandleScope scope(isolate);
RUNTIME_ASSERT(args.length() == 4);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
- CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
-
- uint32_t index = 0;
- key->ToArrayIndex(&index);
+ CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
+ LanguageMode language_mode = language_mode_arg;
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, JSObject::SetElement(object, index, value, attrs, SLOPPY,
- false, DEFINE_PROPERTY));
+ isolate, result,
+ Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
return *result;
}
@@ -724,12 +608,13 @@ RUNTIME_FUNCTION(Runtime_AddElement) {
RUNTIME_FUNCTION(Runtime_DeleteProperty) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
- CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
- CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, JSReceiver::DeleteProperty(object, key, language_mode));
+ isolate, result,
+ Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode));
return *result;
}
@@ -1187,9 +1072,7 @@ static Object* Runtime_NewObjectHelper(Isolate* isolate,
Debug* debug = isolate->debug();
// Handle stepping into constructors if step into is active.
- if (debug->StepInActive()) {
- debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
- }
+ if (debug->StepInActive()) debug->HandleStepIn(function, true);
if (function->has_initial_map()) {
if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
@@ -1381,36 +1264,22 @@ RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
HandleScope scope(isolate);
DCHECK(args.length() == 4);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
- LookupIterator it(js_object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
- if (it.IsFound() && it.state() == LookupIterator::ACCESS_CHECK) {
- if (!isolate->MayAccess(js_object)) {
- return isolate->heap()->undefined_value();
- }
- it.Next();
- }
-
- // Take special care when attributes are different and there is already
- // a property.
- if (it.state() == LookupIterator::ACCESSOR) {
- // Use IgnoreAttributes version since a readonly property may be
- // overridden and SetProperty does not allow this.
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- JSObject::SetOwnPropertyIgnoreAttributes(
- js_object, name, obj_value, attrs, JSObject::DONT_FORCE_FIELD));
- return *result;
+ LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
+ LookupIterator::OWN);
+ if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) {
+ return isolate->heap()->undefined_value();
}
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- Runtime::DefineObjectProperty(js_object, name, obj_value, attrs));
+ isolate, result, JSObject::DefineOwnPropertyIgnoreAttributes(
+ &it, value, attrs, JSObject::DONT_FORCE_FIELD));
+
return *result;
}
@@ -1419,9 +1288,9 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
RUNTIME_FUNCTION(Runtime_GetDataProperty) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
- CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
- CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
- return *JSObject::GetDataProperty(object, key);
+ CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
+ return *JSReceiver::GetDataProperty(object, name);
}
@@ -1518,6 +1387,15 @@ RUNTIME_FUNCTION(Runtime_IsSpecObject) {
}
+RUNTIME_FUNCTION(Runtime_IsStrong) {
+ SealHandleScope shs(isolate);
+ DCHECK(args.length() == 1);
+ CONVERT_ARG_CHECKED(Object, obj, 0);
+ return isolate->heap()->ToBoolean(obj->IsJSReceiver() &&
+ JSReceiver::cast(obj)->map()->is_strong());
+}
+
+
RUNTIME_FUNCTION(Runtime_ClassOf) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
@@ -1557,5 +1435,5 @@ RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
setter, attrs));
return isolate->heap()->undefined_value();
}
-}
-} // namespace v8::internal
+} // namespace internal
+} // namespace v8