diff options
author | Ali Ijaz Sheikh <ofrobots@google.com> | 2015-08-23 06:09:40 -0700 |
---|---|---|
committer | Rod Vagg <rod@vagg.org> | 2015-09-06 21:38:01 +1000 |
commit | 9fddd83cf9adf505bce2e2373881df0c4d41b261 (patch) | |
tree | 4272ce14c10fea496af2e78fc6debb187d613451 /deps/v8/src/runtime/runtime-object.cc | |
parent | 46b7d151674d138e7ea4342d5f3ada1208b87ff2 (diff) | |
download | android-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.cc | 626 |
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 |