Home | History | Annotate | Download | only in runtime
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/runtime/runtime-utils.h"
      6 
      7 #include "src/arguments.h"
      8 #include "src/bootstrapper.h"
      9 #include "src/debug/debug.h"
     10 #include "src/isolate-inl.h"
     11 #include "src/messages.h"
     12 #include "src/property-descriptor.h"
     13 #include "src/runtime/runtime.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 
     18 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
     19                                                Handle<Object> object,
     20                                                Handle<Object> key,
     21                                                bool* is_found_out) {
     22   if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
     23     THROW_NEW_ERROR(
     24         isolate,
     25         NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
     26         Object);
     27   }
     28 
     29   bool success = false;
     30   LookupIterator it =
     31       LookupIterator::PropertyOrElement(isolate, object, key, &success);
     32   if (!success) return MaybeHandle<Object>();
     33 
     34   MaybeHandle<Object> result = Object::GetProperty(&it);
     35   if (is_found_out) *is_found_out = it.IsFound();
     36   return result;
     37 }
     38 
     39 static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate,
     40                                                   Handle<Object> receiver_obj,
     41                                                   Handle<Object> key_obj) {
     42   // Fast cases for getting named properties of the receiver JSObject
     43   // itself.
     44   //
     45   // The global proxy objects has to be excluded since LookupOwn on
     46   // the global proxy object can return a valid result even though the
     47   // global proxy object never has properties.  This is the case
     48   // because the global proxy object forwards everything to its hidden
     49   // prototype including own lookups.
     50   //
     51   // Additionally, we need to make sure that we do not cache results
     52   // for objects that require access checks.
     53   if (receiver_obj->IsJSObject()) {
     54     if (!receiver_obj->IsJSGlobalProxy() &&
     55         !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
     56       DisallowHeapAllocation no_allocation;
     57       Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
     58       Handle<Name> key = Handle<Name>::cast(key_obj);
     59       if (receiver->IsJSGlobalObject()) {
     60         // Attempt dictionary lookup.
     61         GlobalDictionary* dictionary = receiver->global_dictionary();
     62         int entry = dictionary->FindEntry(key);
     63         if (entry != GlobalDictionary::kNotFound) {
     64           DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
     65           PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
     66           if (cell->property_details().type() == DATA) {
     67             Object* value = cell->value();
     68             if (!value->IsTheHole(isolate)) {
     69               return Handle<Object>(value, isolate);
     70             }
     71             // If value is the hole (meaning, absent) do the general lookup.
     72           }
     73         }
     74       } else if (!receiver->HasFastProperties()) {
     75         // Attempt dictionary lookup.
     76         NameDictionary* dictionary = receiver->property_dictionary();
     77         int entry = dictionary->FindEntry(key);
     78         if ((entry != NameDictionary::kNotFound) &&
     79             (dictionary->DetailsAt(entry).type() == DATA)) {
     80           Object* value = dictionary->ValueAt(entry);
     81           return Handle<Object>(value, isolate);
     82         }
     83       }
     84     } else if (key_obj->IsSmi()) {
     85       // JSObject without a name key. If the key is a Smi, check for a
     86       // definite out-of-bounds access to elements, which is a strong indicator
     87       // that subsequent accesses will also call the runtime. Proactively
     88       // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
     89       // doubles for those future calls in the case that the elements would
     90       // become FAST_DOUBLE_ELEMENTS.
     91       Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
     92       ElementsKind elements_kind = js_object->GetElementsKind();
     93       if (IsFastDoubleElementsKind(elements_kind)) {
     94         if (Smi::cast(*key_obj)->value() >= js_object->elements()->length()) {
     95           elements_kind = IsFastHoleyElementsKind(elements_kind)
     96                               ? FAST_HOLEY_ELEMENTS
     97                               : FAST_ELEMENTS;
     98           JSObject::TransitionElementsKind(js_object, elements_kind);
     99         }
    100       } else {
    101         DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
    102                !IsFastElementsKind(elements_kind));
    103       }
    104     }
    105   } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
    106     // Fast case for string indexing using [] with a smi index.
    107     Handle<String> str = Handle<String>::cast(receiver_obj);
    108     int index = Handle<Smi>::cast(key_obj)->value();
    109     if (index >= 0 && index < str->length()) {
    110       Factory* factory = isolate->factory();
    111       return factory->LookupSingleCharacterStringFromCode(
    112           String::Flatten(str)->Get(index));
    113     }
    114   }
    115 
    116   // Fall back to GetObjectProperty.
    117   return Runtime::GetObjectProperty(isolate, receiver_obj, key_obj);
    118 }
    119 
    120 
    121 Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate,
    122                                           Handle<JSReceiver> receiver,
    123                                           Handle<Object> key,
    124                                           LanguageMode language_mode) {
    125   bool success = false;
    126   LookupIterator it = LookupIterator::PropertyOrElement(
    127       isolate, receiver, key, &success, LookupIterator::OWN);
    128   if (!success) return Nothing<bool>();
    129 
    130   return JSReceiver::DeleteProperty(&it, language_mode);
    131 }
    132 
    133 // ES6 19.1.3.2
    134 RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
    135   HandleScope scope(isolate);
    136   Handle<Object> property = args.at<Object>(1);
    137 
    138   Handle<Name> key;
    139   uint32_t index;
    140   bool key_is_array_index = property->ToArrayIndex(&index);
    141 
    142   if (!key_is_array_index) {
    143     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
    144                                        Object::ToName(isolate, property));
    145     key_is_array_index = key->AsArrayIndex(&index);
    146   }
    147 
    148   Handle<Object> object = args.at<Object>(0);
    149 
    150   if (object->IsJSObject()) {
    151     Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
    152     // Fast case: either the key is a real named property or it is not
    153     // an array index and there are no interceptors or hidden
    154     // prototypes.
    155     // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to
    156     // handle all cases directly (without this custom fast path).
    157     {
    158       LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
    159       LookupIterator it =
    160           key_is_array_index ? LookupIterator(isolate, js_obj, index, js_obj, c)
    161                              : LookupIterator(js_obj, key, js_obj, c);
    162       Maybe<bool> maybe = JSReceiver::HasProperty(&it);
    163       if (maybe.IsNothing()) return isolate->heap()->exception();
    164       DCHECK(!isolate->has_pending_exception());
    165       if (maybe.FromJust()) return isolate->heap()->true_value();
    166     }
    167 
    168     Map* map = js_obj->map();
    169     if (!map->has_hidden_prototype() &&
    170         (key_is_array_index ? !map->has_indexed_interceptor()
    171                             : !map->has_named_interceptor())) {
    172       return isolate->heap()->false_value();
    173     }
    174 
    175     // Slow case.
    176     LookupIterator::Configuration c = LookupIterator::OWN;
    177     LookupIterator it = key_is_array_index
    178                             ? LookupIterator(isolate, js_obj, index, js_obj, c)
    179                             : LookupIterator(js_obj, key, js_obj, c);
    180 
    181     Maybe<bool> maybe = JSReceiver::HasProperty(&it);
    182     if (maybe.IsNothing()) return isolate->heap()->exception();
    183     DCHECK(!isolate->has_pending_exception());
    184     return isolate->heap()->ToBoolean(maybe.FromJust());
    185 
    186   } else if (object->IsJSProxy()) {
    187     if (key.is_null()) {
    188       DCHECK(key_is_array_index);
    189       key = isolate->factory()->Uint32ToString(index);
    190     }
    191 
    192     Maybe<bool> result =
    193         JSReceiver::HasOwnProperty(Handle<JSProxy>::cast(object), key);
    194     if (!result.IsJust()) return isolate->heap()->exception();
    195     return isolate->heap()->ToBoolean(result.FromJust());
    196 
    197   } else if (object->IsString()) {
    198     return isolate->heap()->ToBoolean(
    199         key_is_array_index
    200             ? index < static_cast<uint32_t>(String::cast(*object)->length())
    201             : key->Equals(isolate->heap()->length_string()));
    202   } else if (object->IsNull(isolate) || object->IsUndefined(isolate)) {
    203     THROW_NEW_ERROR_RETURN_FAILURE(
    204         isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
    205   }
    206 
    207   return isolate->heap()->false_value();
    208 }
    209 
    210 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
    211                                                Handle<Object> object,
    212                                                Handle<Object> key,
    213                                                Handle<Object> value,
    214                                                LanguageMode language_mode) {
    215   if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
    216     THROW_NEW_ERROR(
    217         isolate,
    218         NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
    219         Object);
    220   }
    221 
    222   // Check if the given key is an array index.
    223   bool success = false;
    224   LookupIterator it =
    225       LookupIterator::PropertyOrElement(isolate, object, key, &success);
    226   if (!success) return MaybeHandle<Object>();
    227 
    228   MAYBE_RETURN_NULL(Object::SetProperty(&it, value, language_mode,
    229                                         Object::MAY_BE_STORE_FROM_KEYED));
    230   return value;
    231 }
    232 
    233 
    234 RUNTIME_FUNCTION(Runtime_GetPrototype) {
    235   HandleScope scope(isolate);
    236   DCHECK(args.length() == 1);
    237   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
    238   RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
    239 }
    240 
    241 
    242 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
    243   HandleScope scope(isolate);
    244   DCHECK(args.length() == 2);
    245   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
    246   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
    247   MAYBE_RETURN(
    248       JSReceiver::SetPrototype(obj, prototype, false, Object::THROW_ON_ERROR),
    249       isolate->heap()->exception());
    250   return *obj;
    251 }
    252 
    253 
    254 RUNTIME_FUNCTION(Runtime_SetPrototype) {
    255   HandleScope scope(isolate);
    256   DCHECK(args.length() == 2);
    257   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
    258   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
    259   MAYBE_RETURN(
    260       JSReceiver::SetPrototype(obj, prototype, true, Object::THROW_ON_ERROR),
    261       isolate->heap()->exception());
    262   return *obj;
    263 }
    264 
    265 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
    266   HandleScope scope(isolate);
    267   DCHECK(args.length() == 2);
    268   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
    269   CONVERT_SMI_ARG_CHECKED(properties, 1);
    270   // Conservative upper limit to prevent fuzz tests from going OOM.
    271   RUNTIME_ASSERT(properties <= 100000);
    272   if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
    273     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
    274                                   "OptimizeForAdding");
    275   }
    276   return *object;
    277 }
    278 
    279 
    280 namespace {
    281 
    282 Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value,
    283                               LanguageMode language_mode) {
    284   // Go up context chain to the script context.
    285   Handle<Context> script_context(isolate->context()->script_context(), isolate);
    286   DCHECK(script_context->IsScriptContext());
    287   DCHECK(script_context->get(slot)->IsPropertyCell());
    288 
    289   // Lookup the named property on the global object.
    290   Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate);
    291   Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
    292   Handle<JSGlobalObject> global_object(script_context->global_object(),
    293                                        isolate);
    294   LookupIterator it(global_object, name, global_object, LookupIterator::OWN);
    295 
    296   // Switch to fast mode only if there is a data property and it's not on
    297   // a hidden prototype.
    298   if (it.state() == LookupIterator::DATA &&
    299       it.GetHolder<Object>().is_identical_to(global_object)) {
    300     // Now update cell in the script context.
    301     Handle<PropertyCell> cell = it.GetPropertyCell();
    302     script_context->set(slot, *cell);
    303   } else {
    304     // This is not a fast case, so keep this access in a slow mode.
    305     // Store empty_property_cell here to release the outdated property cell.
    306     script_context->set(slot, isolate->heap()->empty_property_cell());
    307   }
    308 
    309   MAYBE_RETURN(Object::SetProperty(&it, value, language_mode,
    310                                    Object::CERTAINLY_NOT_STORE_FROM_KEYED),
    311                isolate->heap()->exception());
    312   return *value;
    313 }
    314 
    315 }  // namespace
    316 
    317 
    318 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Sloppy) {
    319   HandleScope scope(isolate);
    320   DCHECK_EQ(2, args.length());
    321   CONVERT_SMI_ARG_CHECKED(slot, 0);
    322   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
    323 
    324   return StoreGlobalViaContext(isolate, slot, value, SLOPPY);
    325 }
    326 
    327 
    328 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Strict) {
    329   HandleScope scope(isolate);
    330   DCHECK_EQ(2, args.length());
    331   CONVERT_SMI_ARG_CHECKED(slot, 0);
    332   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
    333 
    334   return StoreGlobalViaContext(isolate, slot, value, STRICT);
    335 }
    336 
    337 
    338 RUNTIME_FUNCTION(Runtime_GetProperty) {
    339   HandleScope scope(isolate);
    340   DCHECK(args.length() == 2);
    341 
    342   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
    343   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
    344 
    345   RETURN_RESULT_OR_FAILURE(isolate,
    346                            Runtime::GetObjectProperty(isolate, object, key));
    347 }
    348 
    349 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
    350 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
    351   HandleScope scope(isolate);
    352   DCHECK(args.length() == 2);
    353 
    354   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
    355   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
    356 
    357   RETURN_RESULT_OR_FAILURE(
    358       isolate, KeyedGetObjectProperty(isolate, receiver_obj, key_obj));
    359 }
    360 
    361 
    362 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
    363   HandleScope scope(isolate);
    364   DCHECK_EQ(4, args.length());
    365 
    366   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
    367   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
    368   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
    369   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
    370 
    371 #ifdef DEBUG
    372   uint32_t index = 0;
    373   DCHECK(!name->ToArrayIndex(&index));
    374   LookupIterator it(object, name, object, LookupIterator::OWN_SKIP_INTERCEPTOR);
    375   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
    376   if (!maybe.IsJust()) return isolate->heap()->exception();
    377   CHECK(!it.IsFound());
    378 #endif
    379 
    380   RETURN_RESULT_OR_FAILURE(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
    381                                         object, name, value, attrs));
    382 }
    383 
    384 
    385 // Adds an element to an array.
    386 // This is used to create an indexed data property into an array.
    387 RUNTIME_FUNCTION(Runtime_AddElement) {
    388   HandleScope scope(isolate);
    389   DCHECK_EQ(3, args.length());
    390 
    391   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
    392   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
    393   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
    394 
    395   uint32_t index = 0;
    396   CHECK(key->ToArrayIndex(&index));
    397 
    398 #ifdef DEBUG
    399   LookupIterator it(isolate, object, index, object,
    400                     LookupIterator::OWN_SKIP_INTERCEPTOR);
    401   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
    402   if (!maybe.IsJust()) return isolate->heap()->exception();
    403   CHECK(!it.IsFound());
    404 
    405   if (object->IsJSArray()) {
    406     Handle<JSArray> array = Handle<JSArray>::cast(object);
    407     CHECK(!JSArray::WouldChangeReadOnlyLength(array, index));
    408   }
    409 #endif
    410 
    411   RETURN_RESULT_OR_FAILURE(isolate, JSObject::SetOwnElementIgnoreAttributes(
    412                                         object, index, value, NONE));
    413 }
    414 
    415 
    416 RUNTIME_FUNCTION(Runtime_AppendElement) {
    417   HandleScope scope(isolate);
    418   DCHECK_EQ(2, args.length());
    419 
    420   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
    421   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
    422 
    423   uint32_t index;
    424   CHECK(array->length()->ToArrayIndex(&index));
    425 
    426   RETURN_FAILURE_ON_EXCEPTION(
    427       isolate, JSObject::AddDataElement(array, index, value, NONE));
    428   JSObject::ValidateElements(array);
    429   return *array;
    430 }
    431 
    432 
    433 RUNTIME_FUNCTION(Runtime_SetProperty) {
    434   HandleScope scope(isolate);
    435   DCHECK_EQ(4, args.length());
    436 
    437   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
    438   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
    439   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
    440   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
    441   LanguageMode language_mode = language_mode_arg;
    442 
    443   RETURN_RESULT_OR_FAILURE(
    444       isolate,
    445       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
    446 }
    447 
    448 
    449 namespace {
    450 
    451 // ES6 section 12.5.4.
    452 Object* DeleteProperty(Isolate* isolate, Handle<Object> object,
    453                        Handle<Object> key, LanguageMode language_mode) {
    454   Handle<JSReceiver> receiver;
    455   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
    456                                      Object::ToObject(isolate, object));
    457   Maybe<bool> result =
    458       Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode);
    459   MAYBE_RETURN(result, isolate->heap()->exception());
    460   return isolate->heap()->ToBoolean(result.FromJust());
    461 }
    462 
    463 }  // namespace
    464 
    465 
    466 RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy) {
    467   HandleScope scope(isolate);
    468   DCHECK_EQ(2, args.length());
    469   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
    470   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
    471   return DeleteProperty(isolate, object, key, SLOPPY);
    472 }
    473 
    474 
    475 RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict) {
    476   HandleScope scope(isolate);
    477   DCHECK_EQ(2, args.length());
    478   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
    479   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
    480   return DeleteProperty(isolate, object, key, STRICT);
    481 }
    482 
    483 
    484 // ES6 section 12.9.3, operator in.
    485 RUNTIME_FUNCTION(Runtime_HasProperty) {
    486   HandleScope scope(isolate);
    487   DCHECK_EQ(2, args.length());
    488   CONVERT_ARG_HANDLE_CHECKED(Object, key, 0);
    489   CONVERT_ARG_HANDLE_CHECKED(Object, object, 1);
    490 
    491   // Check that {object} is actually a receiver.
    492   if (!object->IsJSReceiver()) {
    493     THROW_NEW_ERROR_RETURN_FAILURE(
    494         isolate,
    495         NewTypeError(MessageTemplate::kInvalidInOperatorUse, key, object));
    496   }
    497   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
    498 
    499   // Convert the {key} to a name.
    500   Handle<Name> name;
    501   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
    502                                      Object::ToName(isolate, key));
    503 
    504   // Lookup the {name} on {receiver}.
    505   Maybe<bool> maybe = JSReceiver::HasProperty(receiver, name);
    506   if (!maybe.IsJust()) return isolate->heap()->exception();
    507   return isolate->heap()->ToBoolean(maybe.FromJust());
    508 }
    509 
    510 
    511 RUNTIME_FUNCTION(Runtime_PropertyIsEnumerable) {
    512   HandleScope scope(isolate);
    513   DCHECK(args.length() == 2);
    514 
    515   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
    516   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
    517 
    518   Maybe<PropertyAttributes> maybe =
    519       JSReceiver::GetOwnPropertyAttributes(object, key);
    520   if (!maybe.IsJust()) return isolate->heap()->exception();
    521   if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value();
    522   return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
    523 }
    524 
    525 
    526 RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) {
    527   HandleScope scope(isolate);
    528   DCHECK(args.length() == 2);
    529   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
    530   CONVERT_SMI_ARG_CHECKED(filter_value, 1);
    531   PropertyFilter filter = static_cast<PropertyFilter>(filter_value);
    532 
    533   Handle<FixedArray> keys;
    534   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    535       isolate, keys,
    536       KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, filter,
    537                               GetKeysConversion::kConvertToString));
    538 
    539   return *isolate->factory()->NewJSArrayWithElements(keys);
    540 }
    541 
    542 
    543 // Return information on whether an object has a named or indexed interceptor.
    544 // args[0]: object
    545 RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
    546   HandleScope scope(isolate);
    547   DCHECK(args.length() == 1);
    548   if (!args[0]->IsJSObject()) {
    549     return Smi::FromInt(0);
    550   }
    551   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
    552 
    553   int result = 0;
    554   if (obj->HasNamedInterceptor()) result |= 2;
    555   if (obj->HasIndexedInterceptor()) result |= 1;
    556 
    557   return Smi::FromInt(result);
    558 }
    559 
    560 
    561 RUNTIME_FUNCTION(Runtime_ToFastProperties) {
    562   HandleScope scope(isolate);
    563   DCHECK(args.length() == 1);
    564   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
    565   if (object->IsJSObject() && !object->IsJSGlobalObject()) {
    566     JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
    567                                 "RuntimeToFastProperties");
    568   }
    569   return *object;
    570 }
    571 
    572 
    573 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
    574   HandleScope scope(isolate);
    575   DCHECK(args.length() == 0);
    576   return *isolate->factory()->NewHeapNumber(0);
    577 }
    578 
    579 
    580 RUNTIME_FUNCTION(Runtime_NewObject) {
    581   HandleScope scope(isolate);
    582   DCHECK_EQ(2, args.length());
    583   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
    584   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1);
    585   RETURN_RESULT_OR_FAILURE(isolate, JSObject::New(target, new_target));
    586 }
    587 
    588 
    589 RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) {
    590   HandleScope scope(isolate);
    591   DCHECK(args.length() == 1);
    592 
    593   CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0);
    594   initial_map->CompleteInobjectSlackTracking();
    595 
    596   return isolate->heap()->undefined_value();
    597 }
    598 
    599 
    600 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
    601   HandleScope scope(isolate);
    602   DCHECK(args.length() == 2);
    603   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
    604   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
    605   CHECK((index->value() & 1) == 1);
    606   FieldIndex field_index =
    607       FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
    608   if (field_index.is_inobject()) {
    609     CHECK(field_index.property_index() <
    610           object->map()->GetInObjectProperties());
    611   } else {
    612     CHECK(field_index.outobject_array_index() < object->properties()->length());
    613   }
    614   return *JSObject::FastPropertyAt(object, Representation::Double(),
    615                                    field_index);
    616 }
    617 
    618 
    619 RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
    620   HandleScope scope(isolate);
    621   DCHECK(args.length() == 1);
    622   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
    623   if (!object->IsJSObject()) return Smi::FromInt(0);
    624   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
    625   if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
    626   // This call must not cause lazy deopts, because it's called from deferred
    627   // code where we can't handle lazy deopts for lack of a suitable bailout
    628   // ID. So we just try migration and signal failure if necessary,
    629   // which will also trigger a deopt.
    630   if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0);
    631   return *object;
    632 }
    633 
    634 
    635 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
    636   SealHandleScope shs(isolate);
    637   DCHECK(args.length() == 1);
    638   CONVERT_ARG_CHECKED(Object, obj, 0);
    639   return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
    640 }
    641 
    642 static bool IsValidAccessor(Isolate* isolate, Handle<Object> obj) {
    643   return obj->IsUndefined(isolate) || obj->IsCallable() || obj->IsNull(isolate);
    644 }
    645 
    646 
    647 // Implements part of 8.12.9 DefineOwnProperty.
    648 // There are 3 cases that lead here:
    649 // Step 4b - define a new accessor property.
    650 // Steps 9c & 12 - replace an existing data property with an accessor property.
    651 // Step 12 - update an existing accessor property with an accessor or generic
    652 //           descriptor.
    653 RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
    654   HandleScope scope(isolate);
    655   DCHECK(args.length() == 5);
    656   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
    657   CHECK(!obj->IsNull(isolate));
    658   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
    659   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
    660   CHECK(IsValidAccessor(isolate, getter));
    661   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
    662   CHECK(IsValidAccessor(isolate, setter));
    663   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
    664 
    665   RETURN_FAILURE_ON_EXCEPTION(
    666       isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
    667   return isolate->heap()->undefined_value();
    668 }
    669 
    670 
    671 RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
    672   HandleScope scope(isolate);
    673   DCHECK(args.length() == 5);
    674   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
    675   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
    676   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
    677   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
    678   CONVERT_SMI_ARG_CHECKED(set_function_name, 4);
    679 
    680   if (set_function_name) {
    681     DCHECK(value->IsJSFunction());
    682     JSFunction::SetName(Handle<JSFunction>::cast(value), name,
    683                         isolate->factory()->empty_string());
    684   }
    685 
    686   LookupIterator it = LookupIterator::PropertyOrElement(
    687       isolate, object, name, object, LookupIterator::OWN);
    688   // Cannot fail since this should only be called when
    689   // creating an object literal.
    690   CHECK(JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attrs,
    691                                                     Object::DONT_THROW)
    692             .IsJust());
    693   return *object;
    694 }
    695 
    696 // Return property without being observable by accessors or interceptors.
    697 RUNTIME_FUNCTION(Runtime_GetDataProperty) {
    698   HandleScope scope(isolate);
    699   DCHECK(args.length() == 2);
    700   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
    701   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
    702   return *JSReceiver::GetDataProperty(object, name);
    703 }
    704 
    705 
    706 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
    707   SealHandleScope shs(isolate);
    708   DCHECK(args.length() == 1);
    709   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
    710   return isolate->heap()->ToBoolean(
    711       IsFastPackedElementsKind(obj->map()->elements_kind()));
    712 }
    713 
    714 
    715 RUNTIME_FUNCTION(Runtime_ValueOf) {
    716   SealHandleScope shs(isolate);
    717   DCHECK(args.length() == 1);
    718   CONVERT_ARG_CHECKED(Object, obj, 0);
    719   if (!obj->IsJSValue()) return obj;
    720   return JSValue::cast(obj)->value();
    721 }
    722 
    723 
    724 RUNTIME_FUNCTION(Runtime_IsJSReceiver) {
    725   SealHandleScope shs(isolate);
    726   DCHECK(args.length() == 1);
    727   CONVERT_ARG_CHECKED(Object, obj, 0);
    728   return isolate->heap()->ToBoolean(obj->IsJSReceiver());
    729 }
    730 
    731 
    732 RUNTIME_FUNCTION(Runtime_ClassOf) {
    733   SealHandleScope shs(isolate);
    734   DCHECK(args.length() == 1);
    735   CONVERT_ARG_CHECKED(Object, obj, 0);
    736   if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
    737   return JSReceiver::cast(obj)->class_name();
    738 }
    739 
    740 
    741 RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
    742   HandleScope scope(isolate);
    743   DCHECK(args.length() == 4);
    744   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
    745   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
    746   CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
    747   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
    748 
    749   if (String::cast(getter->shared()->name())->length() == 0) {
    750     JSFunction::SetName(getter, name, isolate->factory()->get_string());
    751   }
    752 
    753   RETURN_FAILURE_ON_EXCEPTION(
    754       isolate,
    755       JSObject::DefineAccessor(object, name, getter,
    756                                isolate->factory()->null_value(), attrs));
    757   return isolate->heap()->undefined_value();
    758 }
    759 
    760 
    761 RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
    762   HandleScope scope(isolate);
    763   DCHECK(args.length() == 4);
    764   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
    765   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
    766   CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
    767   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
    768 
    769   if (String::cast(setter->shared()->name())->length() == 0) {
    770     JSFunction::SetName(setter, name, isolate->factory()->set_string());
    771   }
    772 
    773   RETURN_FAILURE_ON_EXCEPTION(
    774       isolate,
    775       JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
    776                                setter, attrs));
    777   return isolate->heap()->undefined_value();
    778 }
    779 
    780 
    781 RUNTIME_FUNCTION(Runtime_ToObject) {
    782   HandleScope scope(isolate);
    783   DCHECK_EQ(1, args.length());
    784   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
    785   RETURN_RESULT_OR_FAILURE(isolate, Object::ToObject(isolate, object));
    786 }
    787 
    788 
    789 RUNTIME_FUNCTION(Runtime_ToPrimitive) {
    790   HandleScope scope(isolate);
    791   DCHECK_EQ(1, args.length());
    792   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
    793   RETURN_RESULT_OR_FAILURE(isolate, Object::ToPrimitive(input));
    794 }
    795 
    796 
    797 RUNTIME_FUNCTION(Runtime_ToPrimitive_Number) {
    798   HandleScope scope(isolate);
    799   DCHECK_EQ(1, args.length());
    800   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
    801   RETURN_RESULT_OR_FAILURE(
    802       isolate, Object::ToPrimitive(input, ToPrimitiveHint::kNumber));
    803 }
    804 
    805 
    806 RUNTIME_FUNCTION(Runtime_ToPrimitive_String) {
    807   HandleScope scope(isolate);
    808   DCHECK_EQ(1, args.length());
    809   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
    810   RETURN_RESULT_OR_FAILURE(
    811       isolate, Object::ToPrimitive(input, ToPrimitiveHint::kString));
    812 }
    813 
    814 
    815 RUNTIME_FUNCTION(Runtime_ToNumber) {
    816   HandleScope scope(isolate);
    817   DCHECK_EQ(1, args.length());
    818   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
    819   RETURN_RESULT_OR_FAILURE(isolate, Object::ToNumber(input));
    820 }
    821 
    822 
    823 RUNTIME_FUNCTION(Runtime_ToInteger) {
    824   HandleScope scope(isolate);
    825   DCHECK_EQ(1, args.length());
    826   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
    827   RETURN_RESULT_OR_FAILURE(isolate, Object::ToInteger(isolate, input));
    828 }
    829 
    830 
    831 RUNTIME_FUNCTION(Runtime_ToLength) {
    832   HandleScope scope(isolate);
    833   DCHECK_EQ(1, args.length());
    834   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
    835   RETURN_RESULT_OR_FAILURE(isolate, Object::ToLength(isolate, input));
    836 }
    837 
    838 
    839 RUNTIME_FUNCTION(Runtime_ToString) {
    840   HandleScope scope(isolate);
    841   DCHECK_EQ(1, args.length());
    842   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
    843   RETURN_RESULT_OR_FAILURE(isolate, Object::ToString(isolate, input));
    844 }
    845 
    846 
    847 RUNTIME_FUNCTION(Runtime_ToName) {
    848   HandleScope scope(isolate);
    849   DCHECK_EQ(1, args.length());
    850   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
    851   RETURN_RESULT_OR_FAILURE(isolate, Object::ToName(isolate, input));
    852 }
    853 
    854 
    855 RUNTIME_FUNCTION(Runtime_SameValue) {
    856   SealHandleScope scope(isolate);
    857   DCHECK_EQ(2, args.length());
    858   CONVERT_ARG_CHECKED(Object, x, 0);
    859   CONVERT_ARG_CHECKED(Object, y, 1);
    860   return isolate->heap()->ToBoolean(x->SameValue(y));
    861 }
    862 
    863 
    864 RUNTIME_FUNCTION(Runtime_SameValueZero) {
    865   SealHandleScope scope(isolate);
    866   DCHECK_EQ(2, args.length());
    867   CONVERT_ARG_CHECKED(Object, x, 0);
    868   CONVERT_ARG_CHECKED(Object, y, 1);
    869   return isolate->heap()->ToBoolean(x->SameValueZero(y));
    870 }
    871 
    872 
    873 // TODO(bmeurer): Kill this special wrapper and use TF compatible LessThan,
    874 // GreaterThan, etc. which return true or false.
    875 RUNTIME_FUNCTION(Runtime_Compare) {
    876   HandleScope scope(isolate);
    877   DCHECK_EQ(3, args.length());
    878   CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
    879   CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
    880   CONVERT_ARG_HANDLE_CHECKED(Object, ncr, 2);
    881   Maybe<ComparisonResult> result = Object::Compare(x, y);
    882   if (result.IsJust()) {
    883     switch (result.FromJust()) {
    884       case ComparisonResult::kLessThan:
    885         return Smi::FromInt(LESS);
    886       case ComparisonResult::kEqual:
    887         return Smi::FromInt(EQUAL);
    888       case ComparisonResult::kGreaterThan:
    889         return Smi::FromInt(GREATER);
    890       case ComparisonResult::kUndefined:
    891         return *ncr;
    892     }
    893     UNREACHABLE();
    894   }
    895   return isolate->heap()->exception();
    896 }
    897 
    898 RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
    899   HandleScope scope(isolate);
    900   DCHECK_EQ(2, args.length());
    901   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
    902   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
    903   Maybe<bool> result =
    904       JSReceiver::HasInPrototypeChain(isolate, object, prototype);
    905   MAYBE_RETURN(result, isolate->heap()->exception());
    906   return isolate->heap()->ToBoolean(result.FromJust());
    907 }
    908 
    909 
    910 // ES6 section 7.4.7 CreateIterResultObject ( value, done )
    911 RUNTIME_FUNCTION(Runtime_CreateIterResultObject) {
    912   HandleScope scope(isolate);
    913   DCHECK_EQ(2, args.length());
    914   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
    915   CONVERT_ARG_HANDLE_CHECKED(Object, done, 1);
    916   Handle<JSObject> result =
    917       isolate->factory()->NewJSObjectFromMap(isolate->iterator_result_map());
    918   result->InObjectPropertyAtPut(JSIteratorResult::kValueIndex, *value);
    919   result->InObjectPropertyAtPut(JSIteratorResult::kDoneIndex, *done);
    920   return *result;
    921 }
    922 
    923 
    924 RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) {
    925   SealHandleScope shs(isolate);
    926   DCHECK_EQ(1, args.length());
    927   CONVERT_ARG_CHECKED(Object, object, 0);
    928   return isolate->heap()->ToBoolean(object->IsAccessCheckNeeded());
    929 }
    930 
    931 
    932 RUNTIME_FUNCTION(Runtime_CreateDataProperty) {
    933   HandleScope scope(isolate);
    934   DCHECK(args.length() == 3);
    935   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, o, 0);
    936   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
    937   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
    938   bool success;
    939   LookupIterator it = LookupIterator::PropertyOrElement(
    940       isolate, o, key, &success, LookupIterator::OWN);
    941   if (!success) return isolate->heap()->exception();
    942   MAYBE_RETURN(
    943       JSReceiver::CreateDataProperty(&it, value, Object::THROW_ON_ERROR),
    944       isolate->heap()->exception());
    945   return *value;
    946 }
    947 
    948 }  // namespace internal
    949 }  // namespace v8
    950