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