diff options
Diffstat (limited to 'chromium/v8/src/runtime/runtime-object.cc')
-rw-r--r-- | chromium/v8/src/runtime/runtime-object.cc | 607 |
1 files changed, 147 insertions, 460 deletions
diff --git a/chromium/v8/src/runtime/runtime-object.cc b/chromium/v8/src/runtime/runtime-object.cc index 4782a314305..75ddb7bc22b 100644 --- a/chromium/v8/src/runtime/runtime-object.cc +++ b/chromium/v8/src/runtime/runtime-object.cc @@ -9,6 +9,7 @@ #include "src/debug/debug.h" #include "src/isolate-inl.h" #include "src/messages.h" +#include "src/property-descriptor.h" #include "src/runtime/runtime.h" namespace v8 { @@ -26,26 +27,12 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, Object); } - // Check if the given key is an array index. - uint32_t index = 0; - if (key->ToArrayIndex(&index)) { - return Object::GetElement(isolate, object, index, language_mode); - } + bool success = false; + LookupIterator it = + LookupIterator::PropertyOrElement(isolate, object, key, &success); + if (!success) return MaybeHandle<Object>(); - // Convert the key to a name - possibly by calling back into JavaScript. - Handle<Name> name; - ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key), - Object); - - // 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 Object::GetElement(isolate, object, index); - } else { - return Object::GetProperty(object, name, language_mode); - } + return Object::GetProperty(&it, language_mode); } @@ -70,7 +57,7 @@ static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate, DisallowHeapAllocation no_allocation; Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj); Handle<Name> key = Handle<Name>::cast(key_obj); - if (receiver->IsGlobalObject()) { + if (receiver->IsJSGlobalObject()) { // Attempt dictionary lookup. GlobalDictionary* dictionary = receiver->global_dictionary(); int entry = dictionary->FindEntry(key); @@ -131,21 +118,16 @@ static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate, } -MaybeHandle<Object> Runtime::DeleteObjectProperty(Isolate* isolate, - Handle<JSReceiver> receiver, - Handle<Object> key, - LanguageMode language_mode) { - // Check if the given key is an array index. - uint32_t index = 0; - if (key->ToArrayIndex(&index)) { - return JSReceiver::DeleteElement(receiver, index, language_mode); - } +Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate, + Handle<JSReceiver> receiver, + Handle<Object> key, + LanguageMode language_mode) { + bool success = false; + LookupIterator it = LookupIterator::PropertyOrElement( + isolate, receiver, key, &success, LookupIterator::HIDDEN); + if (!success) return Nothing<bool>(); - Handle<Name> name; - ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key), - Object); - - return JSReceiver::DeletePropertyOrElement(receiver, name, language_mode); + return JSReceiver::DeleteProperty(&it, language_mode); } @@ -162,18 +144,14 @@ MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate, } // Check if the given key is an array index. - uint32_t index = 0; - if (key->ToArrayIndex(&index)) { - return Object::SetElement(isolate, object, index, value, language_mode); - } - - Handle<Name> name; - ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key), - Object); + bool success = false; + LookupIterator it = + LookupIterator::PropertyOrElement(isolate, object, key, &success); + if (!success) return MaybeHandle<Object>(); - LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name); - return Object::SetProperty(&it, value, language_mode, - Object::MAY_BE_STORE_FROM_KEYED); + MAYBE_RETURN_NULL(Object::SetProperty(&it, value, language_mode, + Object::MAY_BE_STORE_FROM_KEYED)); + return value; } @@ -181,68 +159,34 @@ RUNTIME_FUNCTION(Runtime_GetPrototype) { HandleScope scope(isolate); DCHECK(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0); - // We don't expect access checks to be needed on JSProxy objects. - DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); - PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); - do { - if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && - !isolate->MayAccess(PrototypeIterator::GetCurrent<JSObject>(iter))) { - return isolate->heap()->null_value(); - } - iter.AdvanceIgnoringProxies(); - if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { - return *PrototypeIterator::GetCurrent(iter); - } - } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)); - return *PrototypeIterator::GetCurrent(iter); + Handle<Object> prototype; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype, + Object::GetPrototype(isolate, obj)); + return *prototype; } RUNTIME_FUNCTION(Runtime_InternalSetPrototype) { HandleScope scope(isolate); DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0); CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); - DCHECK(!obj->IsAccessCheckNeeded()); - DCHECK(!obj->map()->is_observed()); - Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, JSObject::SetPrototype(obj, prototype, false)); - return *result; + MAYBE_RETURN( + JSReceiver::SetPrototype(obj, prototype, false, Object::THROW_ON_ERROR), + isolate->heap()->exception()); + return *obj; } RUNTIME_FUNCTION(Runtime_SetPrototype) { HandleScope scope(isolate); DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0); CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); - if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) { - isolate->ReportFailedAccessCheck(obj); - RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); - return isolate->heap()->undefined_value(); - } - if (obj->map()->is_observed()) { - Handle<Object> old_value = - Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); - Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, JSObject::SetPrototype(obj, prototype, true)); - - Handle<Object> new_value = - Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); - if (!new_value->SameValue(*old_value)) { - RETURN_FAILURE_ON_EXCEPTION( - isolate, JSObject::EnqueueChangeRecord( - obj, "setPrototype", isolate->factory()->proto_string(), - old_value)); - } - return *result; - } - Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, JSObject::SetPrototype(obj, prototype, true)); - return *result; + MAYBE_RETURN( + JSReceiver::SetPrototype(obj, prototype, true, Object::THROW_ON_ERROR), + isolate->heap()->exception()); + return *obj; } @@ -265,14 +209,13 @@ MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate, Heap* heap = isolate->heap(); Factory* factory = isolate->factory(); - PropertyAttributes attrs; // 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(); + PropertyAttributes attrs = maybe.FromJust(); if (attrs == ABSENT) return factory->undefined_value(); DCHECK(!isolate->has_pending_exception()); @@ -310,7 +253,8 @@ MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate, // [false, value, Writeable, Enumerable, Configurable] // if args[1] is an accessor on args[0] // [true, GetFunction, SetFunction, Enumerable, Configurable] -RUNTIME_FUNCTION(Runtime_GetOwnProperty) { +// TODO(jkummerow): Deprecated. Remove all callers and delete. +RUNTIME_FUNCTION(Runtime_GetOwnProperty_Legacy) { HandleScope scope(isolate); DCHECK(args.length() == 2); CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); @@ -322,22 +266,28 @@ RUNTIME_FUNCTION(Runtime_GetOwnProperty) { } -RUNTIME_FUNCTION(Runtime_PreventExtensions) { +// ES6 19.1.2.6 +RUNTIME_FUNCTION(Runtime_GetOwnProperty) { HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); - Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, - JSObject::PreventExtensions(obj)); - return *result; -} - - -RUNTIME_FUNCTION(Runtime_IsExtensible) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(JSObject, obj, 0); - return isolate->heap()->ToBoolean(obj->IsExtensible()); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, raw_name, 1); + // 1. Let obj be ? ToObject(O). + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object, + Execution::ToObject(isolate, object)); + // 2. Let key be ? ToPropertyKey(P). + Handle<Name> key; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, + Object::ToName(isolate, raw_name)); + + // 3. Let desc be ? obj.[[GetOwnProperty]](key). + PropertyDescriptor desc; + Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor( + isolate, Handle<JSReceiver>::cast(object), key, &desc); + MAYBE_RETURN(found, isolate->heap()->exception()); + // 4. Return FromPropertyDescriptor(desc). + if (!found.FromJust()) return isolate->heap()->undefined_value(); + return *desc.ToObject(isolate); } @@ -356,36 +306,6 @@ RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) { } -RUNTIME_FUNCTION(Runtime_ObjectFreeze) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); - - // %ObjectFreeze is a fast path and these cases are handled elsewhere. - RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && - !object->map()->is_observed() && !object->IsJSProxy()); - - Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object)); - return *result; -} - - -RUNTIME_FUNCTION(Runtime_ObjectSeal) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); - - // %ObjectSeal is a fast path and these cases are handled elsewhere. - RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() && - !object->map()->is_observed() && !object->IsJSProxy()); - - Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object)); - return *result; -} - - RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); @@ -399,7 +319,8 @@ RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) { // Lookup the named property on the global object. Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate); Handle<Name> name(scope_info->ContextSlotName(slot), isolate); - Handle<GlobalObject> global_object(script_context->global_object(), isolate); + Handle<JSGlobalObject> global_object(script_context->global_object(), + isolate); LookupIterator it(global_object, name, LookupIterator::HIDDEN); // Switch to fast mode only if there is a data property and it's not on @@ -433,7 +354,8 @@ Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value, // Lookup the named property on the global object. Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate); Handle<Name> name(scope_info->ContextSlotName(slot), isolate); - Handle<GlobalObject> global_object(script_context->global_object(), isolate); + Handle<JSGlobalObject> global_object(script_context->global_object(), + isolate); LookupIterator it(global_object, name, LookupIterator::HIDDEN); // Switch to fast mode only if there is a data property and it's not on @@ -449,12 +371,10 @@ Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value, script_context->set(slot, isolate->heap()->empty_property_cell()); } - Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, - Object::SetProperty(&it, value, language_mode, - Object::CERTAINLY_NOT_STORE_FROM_KEYED)); - return *result; + MAYBE_RETURN(Object::SetProperty(&it, value, language_mode, + Object::CERTAINLY_NOT_STORE_FROM_KEYED), + isolate->heap()->exception()); + return *value; } } // namespace @@ -647,11 +567,10 @@ Object* DeleteProperty(Isolate* isolate, Handle<Object> object, THROW_NEW_ERROR_RETURN_FAILURE( isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); } - Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, - Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode)); - return *result; + Maybe<bool> result = + Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode); + MAYBE_RETURN(result, isolate->heap()->exception()); + return isolate->heap()->ToBoolean(result.FromJust()); } } // namespace @@ -686,14 +605,15 @@ static Object* HasOwnPropertyImplementation(Isolate* isolate, // look like they are on this object. PrototypeIterator iter(isolate, object); if (!iter.IsAtEnd() && - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)) + PrototypeIterator::GetCurrent<HeapObject>(iter) ->map() ->is_hidden_prototype()) { // TODO(verwaest): The recursion is not necessary for keys that are array // indices. Removing this. + // Casting to JSObject is fine because JSProxies are never used as + // hidden prototypes. return HasOwnPropertyImplementation( - isolate, Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), - key); + isolate, PrototypeIterator::GetCurrent<JSObject>(iter), key); } RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); return isolate->heap()->false_value(); @@ -715,9 +635,13 @@ RUNTIME_FUNCTION(Runtime_HasOwnProperty) { // Fast case: either the key is a real named property or it is not // an array index and there are no interceptors or hidden // prototypes. + // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to + // handle all cases directly (without this custom fast path). Maybe<bool> maybe = Nothing<bool>(); if (key_is_array_index) { - maybe = JSObject::HasOwnElement(js_obj, index); + LookupIterator it(js_obj->GetIsolate(), js_obj, index, + LookupIterator::HIDDEN); + maybe = JSReceiver::HasProperty(&it); } else { maybe = JSObject::HasRealNamedProperty(js_obj, key); } @@ -740,6 +664,11 @@ RUNTIME_FUNCTION(Runtime_HasOwnProperty) { if (index < static_cast<uint32_t>(string->length())) { return isolate->heap()->true_value(); } + } else if (object->IsJSProxy()) { + Maybe<bool> result = + JSReceiver::HasOwnProperty(Handle<JSProxy>::cast(object), key); + if (!result.IsJust()) return isolate->heap()->exception(); + return isolate->heap()->ToBoolean(result.FromJust()); } return isolate->heap()->false_value(); } @@ -772,17 +701,17 @@ RUNTIME_FUNCTION(Runtime_HasProperty) { } -RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) { +RUNTIME_FUNCTION(Runtime_PropertyIsEnumerable) { HandleScope scope(isolate); DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); Maybe<PropertyAttributes> maybe = JSReceiver::GetOwnPropertyAttributes(object, key); if (!maybe.IsJust()) return isolate->heap()->exception(); - if (maybe.FromJust() == ABSENT) maybe = Just(DONT_ENUM); + if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value(); return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0); } @@ -803,8 +732,8 @@ RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) { Handle<JSReceiver> object(raw_object); Handle<FixedArray> content; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, content, - JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS)); + isolate, content, JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS, + ENUMERABLE_STRINGS)); // Test again, since cache may have been built by preceding call. if (object->IsSimpleEnum()) return object->map(); @@ -813,119 +742,19 @@ RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) { } -// Return the names of the own named properties. -// args[0]: object -// args[1]: PropertyAttributes as int -RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { +RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) { HandleScope scope(isolate); DCHECK(args.length() == 2); - if (!args[0]->IsJSObject()) { - return isolate->heap()->undefined_value(); - } - CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); CONVERT_SMI_ARG_CHECKED(filter_value, 1); - PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value); - - // Find the number of own properties for each of the objects. - int total_property_count = 0; - for (PrototypeIterator iter(isolate, object, - PrototypeIterator::START_AT_RECEIVER); - !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { - Handle<JSObject> jsproto = - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); - total_property_count += jsproto->NumberOfOwnProperties(filter); - } - - // Allocate an array with storage for all the property names. - Handle<FixedArray> names = - isolate->factory()->NewFixedArray(total_property_count); - - // Get the property names. - int next_copy_index = 0; - int hidden_strings = 0; - Handle<Object> hidden_string = isolate->factory()->hidden_string(); - for (PrototypeIterator iter(isolate, object, - PrototypeIterator::START_AT_RECEIVER); - !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { - Handle<JSObject> jsproto = - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); - int own = jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); - // Names from hidden prototypes may already have been added - // for inherited function template instances. Count the duplicates - // and stub them out; the final copy pass at the end ignores holes. - for (int j = next_copy_index; j < next_copy_index + own; j++) { - Object* name_from_hidden_proto = names->get(j); - if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) { - hidden_strings++; - } else { - for (int k = 0; k < next_copy_index; k++) { - Object* name = names->get(k); - if (name_from_hidden_proto == name) { - names->set(j, *hidden_string); - hidden_strings++; - break; - } - } - } - } - next_copy_index += own; - } - - CHECK_EQ(total_property_count, next_copy_index); + PropertyFilter filter = static_cast<PropertyFilter>(filter_value); - if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { - for (int i = 0; i < total_property_count; i++) { - Handle<Name> name(Name::cast(names->get(i))); - if (name.is_identical_to(hidden_string)) continue; - LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); - if (!JSObject::AllCanRead(&it)) { - names->set(i, *hidden_string); - hidden_strings++; - } - } - } - - // Filter out name of hidden properties object and - // hidden prototype duplicates. - if (hidden_strings > 0) { - if (hidden_strings == total_property_count) { - names = isolate->factory()->empty_fixed_array(); - } else { - int i; - for (i = 0; i < total_property_count; i++) { - Object* name = names->get(i); - if (name == *hidden_string) break; - } - int dest_pos = i; - for (; i < total_property_count; i++) { - Object* name = names->get(i); - if (name == *hidden_string) continue; - names->set(dest_pos++, name); - } - - isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( - *names, hidden_strings); - } - } - - return *isolate->factory()->NewJSArrayWithElements(names); -} - - -// Return the names of the own indexed properties. -// args[0]: object -RUNTIME_FUNCTION(Runtime_GetOwnElementNames) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - if (!args[0]->IsJSObject()) { - return isolate->heap()->undefined_value(); - } - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); + Handle<FixedArray> keys; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, keys, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY, filter, + CONVERT_TO_STRING)); - int n = obj->NumberOfOwnElements(NONE); - Handle<FixedArray> names = isolate->factory()->NewFixedArray(n); - obj->GetOwnElementKeys(*names, NONE); - return *isolate->factory()->NewJSArrayWithElements(names); + return *isolate->factory()->NewJSArrayWithElements(keys); } @@ -947,84 +776,11 @@ RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) { } -// Return property names from named interceptor. -// args[0]: object -RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); - - if (obj->HasNamedInterceptor()) { - Handle<JSObject> result; - if (JSObject::GetKeysForNamedInterceptor(obj, obj).ToHandle(&result)) { - return *result; - } - } - return isolate->heap()->undefined_value(); -} - - -// Return element names from indexed interceptor. -// args[0]: object -RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); - - if (obj->HasIndexedInterceptor()) { - Handle<JSObject> result; - if (JSObject::GetKeysForIndexedInterceptor(obj, obj).ToHandle(&result)) { - return *result; - } - } - return isolate->heap()->undefined_value(); -} - - -RUNTIME_FUNCTION(Runtime_OwnKeys) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(JSObject, raw_object, 0); - Handle<JSObject> object(raw_object); - - Handle<FixedArray> contents; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, contents, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY)); - - // Some fast paths through GetKeysInFixedArrayFor reuse a cached - // property array and since the result is mutable we have to create - // a fresh clone on each invocation. - int length = contents->length(); - Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length); - int offset = 0; - // Use an outer loop to avoid creating too many handles in the current - // handle scope. - while (offset < length) { - HandleScope scope(isolate); - offset += 100; - int end = Min(offset, length); - for (int i = offset - 100; i < end; i++) { - Object* entry = contents->get(i); - if (entry->IsString()) { - copy->set(i, entry); - } else { - DCHECK(entry->IsNumber()); - Handle<Object> entry_handle(entry, isolate); - Handle<Object> entry_str = - isolate->factory()->NumberToString(entry_handle); - copy->set(i, *entry_str); - } - } - } - return *isolate->factory()->NewJSArrayWithElements(copy); -} - - RUNTIME_FUNCTION(Runtime_ToFastProperties) { HandleScope scope(isolate); DCHECK(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); - if (object->IsJSObject() && !object->IsGlobalObject()) { + if (object->IsJSObject() && !object->IsJSGlobalObject()) { JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0, "RuntimeToFastProperties"); } @@ -1039,87 +795,15 @@ RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) { } -static Object* Runtime_NewObjectHelper(Isolate* isolate, - Handle<Object> constructor, - Handle<Object> original_constructor, - Handle<AllocationSite> site) { - // If the constructor isn't a proper function we throw a type error. - if (!constructor->IsJSFunction()) { - THROW_NEW_ERROR_RETURN_FAILURE( - isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor)); - } - - Handle<JSFunction> function = Handle<JSFunction>::cast(constructor); - - CHECK(original_constructor->IsJSFunction()); - Handle<JSFunction> original_function = - Handle<JSFunction>::cast(original_constructor); - - - // Check that function is a constructor. - if (!function->IsConstructor()) { - THROW_NEW_ERROR_RETURN_FAILURE( - isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor)); - } - - Debug* debug = isolate->debug(); - // Handle stepping into constructors if step into is active. - if (debug->StepInActive()) debug->HandleStepIn(function, true); - - if (function->has_initial_map()) { - if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) { - // The 'Function' function ignores the receiver object when - // called using 'new' and creates a new JSFunction object that - // is returned. The receiver object is only used for error - // reporting if an error occurs when constructing the new - // JSFunction. Factory::NewJSObject() should not be used to - // allocate JSFunctions since it does not properly initialize - // the shared part of the function. Since the receiver is - // ignored anyway, we use the global object as the receiver - // instead of a new JSFunction object. This way, errors are - // reported the same way whether or not 'Function' is called - // using 'new'. - return isolate->global_proxy(); - } - } - - // The function should be compiled for the optimization hints to be - // available. - Compiler::Compile(function, CLEAR_EXCEPTION); - - Handle<JSObject> result; - if (site.is_null()) { - result = isolate->factory()->NewJSObject(function); - } else { - result = isolate->factory()->NewJSObjectWithMemento(function, site); - } - - // Set up the prototoype using original function. - // TODO(dslomov): instead of setting the __proto__, - // use and cache the correct map. - if (*original_function != *function) { - if (original_function->has_instance_prototype()) { - Handle<Object> prototype = - handle(original_function->instance_prototype(), isolate); - RETURN_FAILURE_ON_EXCEPTION( - isolate, JSObject::SetPrototype(result, prototype, false)); - } - } - - isolate->counters()->constructed_objects()->Increment(); - isolate->counters()->constructed_objects_runtime()->Increment(); - - return *result; -} - - RUNTIME_FUNCTION(Runtime_NewObject) { HandleScope scope(isolate); - DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, original_constructor, 1); - return Runtime_NewObjectHelper(isolate, constructor, original_constructor, - Handle<AllocationSite>::null()); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1); + Handle<JSObject> result; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, + JSObject::New(target, new_target)); + return *result; } @@ -1127,8 +811,8 @@ RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) { HandleScope scope(isolate); DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); - function->CompleteInobjectSlackTracking(); + CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0); + initial_map->CompleteInobjectSlackTracking(); return isolate->heap()->undefined_value(); } @@ -1307,22 +991,6 @@ RUNTIME_FUNCTION(Runtime_JSValueGetValue) { } -RUNTIME_FUNCTION(Runtime_HeapObjectGetMap) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(HeapObject, obj, 0); - return obj->map(); -} - - -RUNTIME_FUNCTION(Runtime_MapGetInstanceType) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(Map, map, 0); - return Smi::FromInt(map->instance_type()); -} - - RUNTIME_FUNCTION(Runtime_ObjectEquals) { SealHandleScope shs(isolate); DCHECK(args.length() == 2); @@ -1332,11 +1000,11 @@ RUNTIME_FUNCTION(Runtime_ObjectEquals) { } -RUNTIME_FUNCTION(Runtime_IsSpecObject) { +RUNTIME_FUNCTION(Runtime_IsJSReceiver) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); CONVERT_ARG_CHECKED(Object, obj, 0); - return isolate->heap()->ToBoolean(obj->IsSpecObject()); + return isolate->heap()->ToBoolean(obj->IsJSReceiver()); } @@ -1581,15 +1249,12 @@ RUNTIME_FUNCTION(Runtime_InstanceOf) { if (!object->IsJSReceiver()) { return isolate->heap()->false_value(); } - // Check if {callable} is bound, if so, get [[BoundFunction]] from it and use - // that instead of {callable}. - if (callable->IsJSFunction()) { - Handle<JSFunction> function = Handle<JSFunction>::cast(callable); - if (function->shared()->bound()) { - Handle<FixedArray> bindings(function->function_bindings(), isolate); - callable = - handle(bindings->get(JSFunction::kBoundFunctionIndex), isolate); - } + // Check if {callable} is bound, if so, get [[BoundTargetFunction]] from it + // and use that instead of {callable}. + while (callable->IsJSBoundFunction()) { + callable = + handle(Handle<JSBoundFunction>::cast(callable)->bound_target_function(), + isolate); } DCHECK(callable->IsCallable()); // Get the "prototype" of {callable}; raise an error if it's not a receiver. @@ -1603,18 +1268,20 @@ RUNTIME_FUNCTION(Runtime_InstanceOf) { NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype)); } // Return whether or not {prototype} is in the prototype chain of {object}. - return isolate->heap()->ToBoolean( - object->HasInPrototypeChain(isolate, *prototype)); + Maybe<bool> result = Object::HasInPrototypeChain(isolate, object, prototype); + MAYBE_RETURN(result, isolate->heap()->exception()); + return isolate->heap()->ToBoolean(result.FromJust()); } RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) { - SealHandleScope scope(isolate); + HandleScope scope(isolate); DCHECK_EQ(2, args.length()); - CONVERT_ARG_CHECKED(Object, object, 0); - CONVERT_ARG_CHECKED(Object, prototype, 1); - return isolate->heap()->ToBoolean( - object->HasInPrototypeChain(isolate, prototype)); + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); + Maybe<bool> result = Object::HasInPrototypeChain(isolate, object, prototype); + MAYBE_RETURN(result, isolate->heap()->exception()); + return isolate->heap()->ToBoolean(result.FromJust()); } @@ -1636,5 +1303,25 @@ RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) { } +RUNTIME_FUNCTION(Runtime_ObjectDefineProperty) { + HandleScope scope(isolate); + DCHECK(args.length() == 3); + CONVERT_ARG_HANDLE_CHECKED(Object, o, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, name, 1); + CONVERT_ARG_HANDLE_CHECKED(Object, attributes, 2); + return JSReceiver::DefineProperty(isolate, o, name, attributes); +} + + +RUNTIME_FUNCTION(Runtime_ObjectDefineProperties) { + HandleScope scope(isolate); + DCHECK(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(Object, o, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, properties, 1); + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, o, JSReceiver::DefineProperties(isolate, o, properties)); + return *o; +} + } // namespace internal } // namespace v8 |