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 
GetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,bool * is_found_out)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 
KeyedGetObjectProperty(Isolate * isolate,Handle<Object> receiver_obj,Handle<Object> key_obj)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 
DeleteObjectProperty(Isolate * isolate,Handle<JSReceiver> receiver,Handle<Object> key,LanguageMode language_mode)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
RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty)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 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
211 // TODO(verwaest): Support the common cases with precached map directly in
212 // an Object.create stub.
RUNTIME_FUNCTION(Runtime_ObjectCreate)213 RUNTIME_FUNCTION(Runtime_ObjectCreate) {
214   HandleScope scope(isolate);
215   Handle<Object> prototype = args.at<Object>(0);
216   if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
217     THROW_NEW_ERROR_RETURN_FAILURE(
218         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
219   }
220 
221   // Generate the map with the specified {prototype} based on the Object
222   // function's initial map from the current native context.
223   // TODO(bmeurer): Use a dedicated cache for Object.create; think about
224   // slack tracking for Object.create.
225   Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
226                   isolate);
227   if (map->prototype() != *prototype) {
228     if (prototype->IsNull(isolate)) {
229       map = isolate->slow_object_with_null_prototype_map();
230     } else if (prototype->IsJSObject()) {
231       Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
232       if (!js_prototype->map()->is_prototype_map()) {
233         JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE);
234       }
235       Handle<PrototypeInfo> info =
236           Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
237       // TODO(verwaest): Use inobject slack tracking for this map.
238       if (info->HasObjectCreateMap()) {
239         map = handle(info->ObjectCreateMap(), isolate);
240       } else {
241         map = Map::CopyInitialMap(map);
242         Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
243         PrototypeInfo::SetObjectCreateMap(info, map);
244       }
245     } else {
246       map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
247     }
248   }
249 
250   bool is_dictionary_map = map->is_dictionary_map();
251   Handle<FixedArray> object_properties;
252   if (is_dictionary_map) {
253     // Allocate the actual properties dictionay up front to avoid invalid object
254     // state.
255     object_properties =
256         NameDictionary::New(isolate, NameDictionary::kInitialCapacity);
257   }
258   // Actually allocate the object.
259   Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
260   if (is_dictionary_map) {
261     object->set_properties(*object_properties);
262   }
263 
264   // Define the properties if properties was specified and is not undefined.
265   Handle<Object> properties = args.at<Object>(1);
266   if (!properties->IsUndefined(isolate)) {
267     RETURN_FAILURE_ON_EXCEPTION(
268         isolate, JSReceiver::DefineProperties(isolate, object, properties));
269   }
270 
271   return *object;
272 }
273 
SetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,LanguageMode language_mode)274 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
275                                                Handle<Object> object,
276                                                Handle<Object> key,
277                                                Handle<Object> value,
278                                                LanguageMode language_mode) {
279   if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
280     THROW_NEW_ERROR(
281         isolate,
282         NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
283         Object);
284   }
285 
286   // Check if the given key is an array index.
287   bool success = false;
288   LookupIterator it =
289       LookupIterator::PropertyOrElement(isolate, object, key, &success);
290   if (!success) return MaybeHandle<Object>();
291 
292   MAYBE_RETURN_NULL(Object::SetProperty(&it, value, language_mode,
293                                         Object::MAY_BE_STORE_FROM_KEYED));
294   return value;
295 }
296 
297 
RUNTIME_FUNCTION(Runtime_GetPrototype)298 RUNTIME_FUNCTION(Runtime_GetPrototype) {
299   HandleScope scope(isolate);
300   DCHECK(args.length() == 1);
301   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
302   RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
303 }
304 
305 
RUNTIME_FUNCTION(Runtime_InternalSetPrototype)306 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
307   HandleScope scope(isolate);
308   DCHECK(args.length() == 2);
309   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
310   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
311   MAYBE_RETURN(
312       JSReceiver::SetPrototype(obj, prototype, false, Object::THROW_ON_ERROR),
313       isolate->heap()->exception());
314   return *obj;
315 }
316 
RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties)317 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
318   HandleScope scope(isolate);
319   DCHECK(args.length() == 2);
320   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
321   CONVERT_SMI_ARG_CHECKED(properties, 1);
322   // Conservative upper limit to prevent fuzz tests from going OOM.
323   if (properties > 100000) return isolate->ThrowIllegalOperation();
324   if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
325     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
326                                   "OptimizeForAdding");
327   }
328   return *object;
329 }
330 
331 
RUNTIME_FUNCTION(Runtime_GetProperty)332 RUNTIME_FUNCTION(Runtime_GetProperty) {
333   HandleScope scope(isolate);
334   DCHECK(args.length() == 2);
335 
336   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
337   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
338 
339   RETURN_RESULT_OR_FAILURE(isolate,
340                            Runtime::GetObjectProperty(isolate, object, key));
341 }
342 
343 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(Runtime_KeyedGetProperty)344 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
345   HandleScope scope(isolate);
346   DCHECK(args.length() == 2);
347 
348   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
349   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
350 
351   RETURN_RESULT_OR_FAILURE(
352       isolate, KeyedGetObjectProperty(isolate, receiver_obj, key_obj));
353 }
354 
RUNTIME_FUNCTION(Runtime_AddNamedProperty)355 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
356   HandleScope scope(isolate);
357   DCHECK_EQ(4, args.length());
358 
359   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
360   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
361   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
362   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
363 
364 #ifdef DEBUG
365   uint32_t index = 0;
366   DCHECK(!name->ToArrayIndex(&index));
367   LookupIterator it(object, name, object, LookupIterator::OWN_SKIP_INTERCEPTOR);
368   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
369   if (!maybe.IsJust()) return isolate->heap()->exception();
370   CHECK(!it.IsFound());
371 #endif
372 
373   RETURN_RESULT_OR_FAILURE(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
374                                         object, name, value, attrs));
375 }
376 
377 
378 // Adds an element to an array.
379 // This is used to create an indexed data property into an array.
RUNTIME_FUNCTION(Runtime_AddElement)380 RUNTIME_FUNCTION(Runtime_AddElement) {
381   HandleScope scope(isolate);
382   DCHECK_EQ(3, args.length());
383 
384   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
385   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
386   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
387 
388   uint32_t index = 0;
389   CHECK(key->ToArrayIndex(&index));
390 
391 #ifdef DEBUG
392   LookupIterator it(isolate, object, index, object,
393                     LookupIterator::OWN_SKIP_INTERCEPTOR);
394   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
395   if (!maybe.IsJust()) return isolate->heap()->exception();
396   CHECK(!it.IsFound());
397 
398   if (object->IsJSArray()) {
399     Handle<JSArray> array = Handle<JSArray>::cast(object);
400     CHECK(!JSArray::WouldChangeReadOnlyLength(array, index));
401   }
402 #endif
403 
404   RETURN_RESULT_OR_FAILURE(isolate, JSObject::SetOwnElementIgnoreAttributes(
405                                         object, index, value, NONE));
406 }
407 
408 
RUNTIME_FUNCTION(Runtime_AppendElement)409 RUNTIME_FUNCTION(Runtime_AppendElement) {
410   HandleScope scope(isolate);
411   DCHECK_EQ(2, args.length());
412 
413   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
414   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
415   CHECK(!value->IsTheHole(isolate));
416 
417   uint32_t index;
418   CHECK(array->length()->ToArrayIndex(&index));
419 
420   RETURN_FAILURE_ON_EXCEPTION(
421       isolate, JSObject::AddDataElement(array, index, value, NONE));
422   JSObject::ValidateElements(array);
423   return *array;
424 }
425 
426 
RUNTIME_FUNCTION(Runtime_SetProperty)427 RUNTIME_FUNCTION(Runtime_SetProperty) {
428   HandleScope scope(isolate);
429   DCHECK_EQ(4, args.length());
430 
431   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
432   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
433   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
434   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3);
435 
436   RETURN_RESULT_OR_FAILURE(
437       isolate,
438       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
439 }
440 
441 
442 namespace {
443 
444 // ES6 section 12.5.4.
DeleteProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,LanguageMode language_mode)445 Object* DeleteProperty(Isolate* isolate, Handle<Object> object,
446                        Handle<Object> key, LanguageMode language_mode) {
447   Handle<JSReceiver> receiver;
448   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
449                                      Object::ToObject(isolate, object));
450   Maybe<bool> result =
451       Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode);
452   MAYBE_RETURN(result, isolate->heap()->exception());
453   return isolate->heap()->ToBoolean(result.FromJust());
454 }
455 
456 }  // namespace
457 
458 
RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy)459 RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy) {
460   HandleScope scope(isolate);
461   DCHECK_EQ(2, args.length());
462   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
463   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
464   return DeleteProperty(isolate, object, key, SLOPPY);
465 }
466 
467 
RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict)468 RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict) {
469   HandleScope scope(isolate);
470   DCHECK_EQ(2, args.length());
471   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
472   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
473   return DeleteProperty(isolate, object, key, STRICT);
474 }
475 
476 
477 // ES6 section 12.9.3, operator in.
RUNTIME_FUNCTION(Runtime_HasProperty)478 RUNTIME_FUNCTION(Runtime_HasProperty) {
479   HandleScope scope(isolate);
480   DCHECK_EQ(2, args.length());
481   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
482   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
483 
484   // Check that {object} is actually a receiver.
485   if (!object->IsJSReceiver()) {
486     THROW_NEW_ERROR_RETURN_FAILURE(
487         isolate,
488         NewTypeError(MessageTemplate::kInvalidInOperatorUse, key, object));
489   }
490   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
491 
492   // Convert the {key} to a name.
493   Handle<Name> name;
494   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
495                                      Object::ToName(isolate, key));
496 
497   // Lookup the {name} on {receiver}.
498   Maybe<bool> maybe = JSReceiver::HasProperty(receiver, name);
499   if (!maybe.IsJust()) return isolate->heap()->exception();
500   return isolate->heap()->ToBoolean(maybe.FromJust());
501 }
502 
503 
RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys)504 RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) {
505   HandleScope scope(isolate);
506   DCHECK(args.length() == 2);
507   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
508   CONVERT_SMI_ARG_CHECKED(filter_value, 1);
509   PropertyFilter filter = static_cast<PropertyFilter>(filter_value);
510 
511   Handle<FixedArray> keys;
512   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
513       isolate, keys,
514       KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, filter,
515                               GetKeysConversion::kConvertToString));
516 
517   return *isolate->factory()->NewJSArrayWithElements(keys);
518 }
519 
520 
521 // Return information on whether an object has a named or indexed interceptor.
522 // args[0]: object
RUNTIME_FUNCTION(Runtime_GetInterceptorInfo)523 RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
524   HandleScope scope(isolate);
525   DCHECK(args.length() == 1);
526   if (!args[0]->IsJSObject()) {
527     return Smi::kZero;
528   }
529   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
530 
531   int result = 0;
532   if (obj->HasNamedInterceptor()) result |= 2;
533   if (obj->HasIndexedInterceptor()) result |= 1;
534 
535   return Smi::FromInt(result);
536 }
537 
538 
RUNTIME_FUNCTION(Runtime_ToFastProperties)539 RUNTIME_FUNCTION(Runtime_ToFastProperties) {
540   HandleScope scope(isolate);
541   DCHECK(args.length() == 1);
542   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
543   if (object->IsJSObject() && !object->IsJSGlobalObject()) {
544     JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
545                                 "RuntimeToFastProperties");
546   }
547   return *object;
548 }
549 
550 
RUNTIME_FUNCTION(Runtime_AllocateHeapNumber)551 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
552   HandleScope scope(isolate);
553   DCHECK(args.length() == 0);
554   return *isolate->factory()->NewHeapNumber(0);
555 }
556 
557 
RUNTIME_FUNCTION(Runtime_NewObject)558 RUNTIME_FUNCTION(Runtime_NewObject) {
559   HandleScope scope(isolate);
560   DCHECK_EQ(2, args.length());
561   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
562   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1);
563   RETURN_RESULT_OR_FAILURE(isolate, JSObject::New(target, new_target));
564 }
565 
566 
RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize)567 RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) {
568   HandleScope scope(isolate);
569   DCHECK(args.length() == 1);
570 
571   CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0);
572   initial_map->CompleteInobjectSlackTracking();
573 
574   return isolate->heap()->undefined_value();
575 }
576 
577 
RUNTIME_FUNCTION(Runtime_LoadMutableDouble)578 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
579   HandleScope scope(isolate);
580   DCHECK(args.length() == 2);
581   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
582   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
583   CHECK((index->value() & 1) == 1);
584   FieldIndex field_index =
585       FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
586   if (field_index.is_inobject()) {
587     CHECK(field_index.property_index() <
588           object->map()->GetInObjectProperties());
589   } else {
590     CHECK(field_index.outobject_array_index() < object->properties()->length());
591   }
592   return *JSObject::FastPropertyAt(object, Representation::Double(),
593                                    field_index);
594 }
595 
596 
RUNTIME_FUNCTION(Runtime_TryMigrateInstance)597 RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
598   HandleScope scope(isolate);
599   DCHECK(args.length() == 1);
600   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
601   if (!object->IsJSObject()) return Smi::kZero;
602   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
603   if (!js_object->map()->is_deprecated()) return Smi::kZero;
604   // This call must not cause lazy deopts, because it's called from deferred
605   // code where we can't handle lazy deopts for lack of a suitable bailout
606   // ID. So we just try migration and signal failure if necessary,
607   // which will also trigger a deopt.
608   if (!JSObject::TryMigrateInstance(js_object)) return Smi::kZero;
609   return *object;
610 }
611 
612 
RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy)613 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
614   SealHandleScope shs(isolate);
615   DCHECK(args.length() == 1);
616   CONVERT_ARG_CHECKED(Object, obj, 0);
617   return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
618 }
619 
IsValidAccessor(Isolate * isolate,Handle<Object> obj)620 static bool IsValidAccessor(Isolate* isolate, Handle<Object> obj) {
621   return obj->IsUndefined(isolate) || obj->IsCallable() || obj->IsNull(isolate);
622 }
623 
624 
625 // Implements part of 8.12.9 DefineOwnProperty.
626 // There are 3 cases that lead here:
627 // Step 4b - define a new accessor property.
628 // Steps 9c & 12 - replace an existing data property with an accessor property.
629 // Step 12 - update an existing accessor property with an accessor or generic
630 //           descriptor.
RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked)631 RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
632   HandleScope scope(isolate);
633   DCHECK(args.length() == 5);
634   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
635   CHECK(!obj->IsNull(isolate));
636   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
637   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
638   CHECK(IsValidAccessor(isolate, getter));
639   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
640   CHECK(IsValidAccessor(isolate, setter));
641   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
642 
643   RETURN_FAILURE_ON_EXCEPTION(
644       isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
645   return isolate->heap()->undefined_value();
646 }
647 
648 
RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral)649 RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
650   HandleScope scope(isolate);
651   DCHECK(args.length() == 5);
652   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
653   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
654   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
655   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
656   CONVERT_SMI_ARG_CHECKED(set_function_name, 4);
657 
658   if (set_function_name) {
659     DCHECK(value->IsJSFunction());
660     JSFunction::SetName(Handle<JSFunction>::cast(value), name,
661                         isolate->factory()->empty_string());
662   }
663 
664   LookupIterator it = LookupIterator::PropertyOrElement(
665       isolate, object, name, object, LookupIterator::OWN);
666   // Cannot fail since this should only be called when
667   // creating an object literal.
668   CHECK(JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attrs,
669                                                     Object::DONT_THROW)
670             .IsJust());
671   return *object;
672 }
673 
RUNTIME_FUNCTION(Runtime_DefineDataProperty)674 RUNTIME_FUNCTION(Runtime_DefineDataProperty) {
675   HandleScope scope(isolate);
676   DCHECK(args.length() == 5);
677   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
678   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
679   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
680   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
681   CONVERT_SMI_ARG_CHECKED(set_function_name, 4);
682 
683   if (set_function_name) {
684     DCHECK(value->IsJSFunction());
685     JSFunction::SetName(Handle<JSFunction>::cast(value), name,
686                         isolate->factory()->empty_string());
687   }
688 
689   PropertyDescriptor desc;
690   desc.set_writable(!(attrs & ReadOnly));
691   desc.set_enumerable(!(attrs & DontEnum));
692   desc.set_configurable(!(attrs & DontDelete));
693   desc.set_value(value);
694 
695   Maybe<bool> result = JSReceiver::DefineOwnProperty(isolate, receiver, name,
696                                                      &desc, Object::DONT_THROW);
697   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
698   if (result.IsNothing()) {
699     DCHECK(isolate->has_pending_exception());
700     return isolate->heap()->exception();
701   }
702 
703   return *receiver;
704 }
705 
706 // Return property without being observable by accessors or interceptors.
RUNTIME_FUNCTION(Runtime_GetDataProperty)707 RUNTIME_FUNCTION(Runtime_GetDataProperty) {
708   HandleScope scope(isolate);
709   DCHECK(args.length() == 2);
710   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
711   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
712   return *JSReceiver::GetDataProperty(object, name);
713 }
714 
RUNTIME_FUNCTION(Runtime_GetConstructorName)715 RUNTIME_FUNCTION(Runtime_GetConstructorName) {
716   HandleScope scope(isolate);
717   DCHECK(args.length() == 1);
718   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
719 
720   CHECK(!object->IsUndefined(isolate) && !object->IsNull(isolate));
721   Handle<JSReceiver> recv = Object::ToObject(isolate, object).ToHandleChecked();
722   return *JSReceiver::GetConstructorName(recv);
723 }
724 
RUNTIME_FUNCTION(Runtime_HasFastPackedElements)725 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
726   SealHandleScope shs(isolate);
727   DCHECK(args.length() == 1);
728   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
729   return isolate->heap()->ToBoolean(
730       IsFastPackedElementsKind(obj->map()->elements_kind()));
731 }
732 
733 
RUNTIME_FUNCTION(Runtime_ValueOf)734 RUNTIME_FUNCTION(Runtime_ValueOf) {
735   SealHandleScope shs(isolate);
736   DCHECK(args.length() == 1);
737   CONVERT_ARG_CHECKED(Object, obj, 0);
738   if (!obj->IsJSValue()) return obj;
739   return JSValue::cast(obj)->value();
740 }
741 
742 
RUNTIME_FUNCTION(Runtime_IsJSReceiver)743 RUNTIME_FUNCTION(Runtime_IsJSReceiver) {
744   SealHandleScope shs(isolate);
745   DCHECK(args.length() == 1);
746   CONVERT_ARG_CHECKED(Object, obj, 0);
747   return isolate->heap()->ToBoolean(obj->IsJSReceiver());
748 }
749 
750 
RUNTIME_FUNCTION(Runtime_ClassOf)751 RUNTIME_FUNCTION(Runtime_ClassOf) {
752   SealHandleScope shs(isolate);
753   DCHECK(args.length() == 1);
754   CONVERT_ARG_CHECKED(Object, obj, 0);
755   if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
756   return JSReceiver::cast(obj)->class_name();
757 }
758 
759 
RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked)760 RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
761   HandleScope scope(isolate);
762   DCHECK(args.length() == 4);
763   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
764   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
765   CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
766   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
767 
768   if (String::cast(getter->shared()->name())->length() == 0) {
769     JSFunction::SetName(getter, name, isolate->factory()->get_string());
770   }
771 
772   RETURN_FAILURE_ON_EXCEPTION(
773       isolate,
774       JSObject::DefineAccessor(object, name, getter,
775                                isolate->factory()->null_value(), attrs));
776   return isolate->heap()->undefined_value();
777 }
778 
779 
RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked)780 RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
781   HandleScope scope(isolate);
782   DCHECK(args.length() == 4);
783   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
784   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
785   CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
786   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
787 
788   if (String::cast(setter->shared()->name())->length() == 0) {
789     JSFunction::SetName(setter, name, isolate->factory()->set_string());
790   }
791 
792   RETURN_FAILURE_ON_EXCEPTION(
793       isolate,
794       JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
795                                setter, attrs));
796   return isolate->heap()->undefined_value();
797 }
798 
799 
RUNTIME_FUNCTION(Runtime_ToObject)800 RUNTIME_FUNCTION(Runtime_ToObject) {
801   HandleScope scope(isolate);
802   DCHECK_EQ(1, args.length());
803   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
804   RETURN_RESULT_OR_FAILURE(isolate, Object::ToObject(isolate, object));
805 }
806 
807 
RUNTIME_FUNCTION(Runtime_ToPrimitive)808 RUNTIME_FUNCTION(Runtime_ToPrimitive) {
809   HandleScope scope(isolate);
810   DCHECK_EQ(1, args.length());
811   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
812   RETURN_RESULT_OR_FAILURE(isolate, Object::ToPrimitive(input));
813 }
814 
815 
RUNTIME_FUNCTION(Runtime_ToPrimitive_Number)816 RUNTIME_FUNCTION(Runtime_ToPrimitive_Number) {
817   HandleScope scope(isolate);
818   DCHECK_EQ(1, args.length());
819   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
820   RETURN_RESULT_OR_FAILURE(
821       isolate, Object::ToPrimitive(input, ToPrimitiveHint::kNumber));
822 }
823 
RUNTIME_FUNCTION(Runtime_ToNumber)824 RUNTIME_FUNCTION(Runtime_ToNumber) {
825   HandleScope scope(isolate);
826   DCHECK_EQ(1, args.length());
827   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
828   RETURN_RESULT_OR_FAILURE(isolate, Object::ToNumber(input));
829 }
830 
831 
RUNTIME_FUNCTION(Runtime_ToInteger)832 RUNTIME_FUNCTION(Runtime_ToInteger) {
833   HandleScope scope(isolate);
834   DCHECK_EQ(1, args.length());
835   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
836   RETURN_RESULT_OR_FAILURE(isolate, Object::ToInteger(isolate, input));
837 }
838 
839 
RUNTIME_FUNCTION(Runtime_ToLength)840 RUNTIME_FUNCTION(Runtime_ToLength) {
841   HandleScope scope(isolate);
842   DCHECK_EQ(1, args.length());
843   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
844   RETURN_RESULT_OR_FAILURE(isolate, Object::ToLength(isolate, input));
845 }
846 
847 
RUNTIME_FUNCTION(Runtime_ToString)848 RUNTIME_FUNCTION(Runtime_ToString) {
849   HandleScope scope(isolate);
850   DCHECK_EQ(1, args.length());
851   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
852   RETURN_RESULT_OR_FAILURE(isolate, Object::ToString(isolate, input));
853 }
854 
855 
RUNTIME_FUNCTION(Runtime_ToName)856 RUNTIME_FUNCTION(Runtime_ToName) {
857   HandleScope scope(isolate);
858   DCHECK_EQ(1, args.length());
859   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
860   RETURN_RESULT_OR_FAILURE(isolate, Object::ToName(isolate, input));
861 }
862 
863 
RUNTIME_FUNCTION(Runtime_SameValue)864 RUNTIME_FUNCTION(Runtime_SameValue) {
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->SameValue(y));
870 }
871 
872 
RUNTIME_FUNCTION(Runtime_SameValueZero)873 RUNTIME_FUNCTION(Runtime_SameValueZero) {
874   SealHandleScope scope(isolate);
875   DCHECK_EQ(2, args.length());
876   CONVERT_ARG_CHECKED(Object, x, 0);
877   CONVERT_ARG_CHECKED(Object, y, 1);
878   return isolate->heap()->ToBoolean(x->SameValueZero(y));
879 }
880 
881 
882 // TODO(bmeurer): Kill this special wrapper and use TF compatible LessThan,
883 // GreaterThan, etc. which return true or false.
RUNTIME_FUNCTION(Runtime_Compare)884 RUNTIME_FUNCTION(Runtime_Compare) {
885   HandleScope scope(isolate);
886   DCHECK_EQ(3, args.length());
887   CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
888   CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
889   CONVERT_ARG_HANDLE_CHECKED(Object, ncr, 2);
890   Maybe<ComparisonResult> result = Object::Compare(x, y);
891   if (result.IsJust()) {
892     switch (result.FromJust()) {
893       case ComparisonResult::kLessThan:
894         return Smi::FromInt(LESS);
895       case ComparisonResult::kEqual:
896         return Smi::FromInt(EQUAL);
897       case ComparisonResult::kGreaterThan:
898         return Smi::FromInt(GREATER);
899       case ComparisonResult::kUndefined:
900         return *ncr;
901     }
902     UNREACHABLE();
903   }
904   return isolate->heap()->exception();
905 }
906 
RUNTIME_FUNCTION(Runtime_HasInPrototypeChain)907 RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
908   HandleScope scope(isolate);
909   DCHECK_EQ(2, args.length());
910   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
911   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
912   Maybe<bool> result =
913       JSReceiver::HasInPrototypeChain(isolate, object, prototype);
914   MAYBE_RETURN(result, isolate->heap()->exception());
915   return isolate->heap()->ToBoolean(result.FromJust());
916 }
917 
918 
919 // ES6 section 7.4.7 CreateIterResultObject ( value, done )
RUNTIME_FUNCTION(Runtime_CreateIterResultObject)920 RUNTIME_FUNCTION(Runtime_CreateIterResultObject) {
921   HandleScope scope(isolate);
922   DCHECK_EQ(2, args.length());
923   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
924   CONVERT_ARG_HANDLE_CHECKED(Object, done, 1);
925   return *isolate->factory()->NewJSIteratorResult(value, done->BooleanValue());
926 }
927 
RUNTIME_FUNCTION(Runtime_CreateKeyValueArray)928 RUNTIME_FUNCTION(Runtime_CreateKeyValueArray) {
929   HandleScope scope(isolate);
930   DCHECK_EQ(2, args.length());
931   CONVERT_ARG_HANDLE_CHECKED(Object, key, 0);
932   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
933   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(2);
934   elements->set(0, *key);
935   elements->set(1, *value);
936   return *isolate->factory()->NewJSArrayWithElements(elements, FAST_ELEMENTS,
937                                                      2);
938 }
939 
RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded)940 RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) {
941   SealHandleScope shs(isolate);
942   DCHECK_EQ(1, args.length());
943   CONVERT_ARG_CHECKED(Object, object, 0);
944   return isolate->heap()->ToBoolean(object->IsAccessCheckNeeded());
945 }
946 
947 
RUNTIME_FUNCTION(Runtime_CreateDataProperty)948 RUNTIME_FUNCTION(Runtime_CreateDataProperty) {
949   HandleScope scope(isolate);
950   DCHECK(args.length() == 3);
951   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, o, 0);
952   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
953   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
954   bool success;
955   LookupIterator it = LookupIterator::PropertyOrElement(
956       isolate, o, key, &success, LookupIterator::OWN);
957   if (!success) return isolate->heap()->exception();
958   MAYBE_RETURN(
959       JSReceiver::CreateDataProperty(&it, value, Object::THROW_ON_ERROR),
960       isolate->heap()->exception());
961   return *value;
962 }
963 
964 
965 }  // namespace internal
966 }  // namespace v8
967