• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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->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 
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       // 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 
DeleteObjectProperty(Isolate * isolate,Handle<JSReceiver> receiver,Handle<Object> key,LanguageMode language_mode)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
RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty)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.
RUNTIME_FUNCTION(Runtime_ObjectCreate)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 
SetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,LanguageMode language_mode)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 
RUNTIME_FUNCTION(Runtime_GetPrototype)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 
RUNTIME_FUNCTION(Runtime_InternalSetPrototype)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 
RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties)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 
RUNTIME_FUNCTION(Runtime_GetProperty)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.
RUNTIME_FUNCTION(Runtime_KeyedGetProperty)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 
RUNTIME_FUNCTION(Runtime_AddNamedProperty)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.
RUNTIME_FUNCTION(Runtime_AddElement)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 
RUNTIME_FUNCTION(Runtime_AppendElement)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 
RUNTIME_FUNCTION(Runtime_SetProperty)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.
DeleteProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,LanguageMode language_mode)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 
RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy)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 
RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict)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.
RUNTIME_FUNCTION(Runtime_HasProperty)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 
RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys)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
RUNTIME_FUNCTION(Runtime_GetInterceptorInfo)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 
RUNTIME_FUNCTION(Runtime_ToFastProperties)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 
RUNTIME_FUNCTION(Runtime_AllocateHeapNumber)537 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
538   HandleScope scope(isolate);
539   DCHECK_EQ(0, args.length());
540   return *isolate->factory()->NewHeapNumber(0);
541 }
542 
543 
RUNTIME_FUNCTION(Runtime_NewObject)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 
RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize)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 
RUNTIME_FUNCTION(Runtime_LoadMutableDouble)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 
RUNTIME_FUNCTION(Runtime_TryMigrateInstance)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 
RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy)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 
IsValidAccessor(Isolate * isolate,Handle<Object> obj)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.
RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked)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 
RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral)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.
RUNTIME_FUNCTION(Runtime_GetDataProperty)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 
RUNTIME_FUNCTION(Runtime_GetConstructorName)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 
RUNTIME_FUNCTION(Runtime_HasFastPackedElements)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 
RUNTIME_FUNCTION(Runtime_ValueOf)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 
RUNTIME_FUNCTION(Runtime_IsJSReceiver)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 
RUNTIME_FUNCTION(Runtime_ClassOf)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 
RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked)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 
RUNTIME_FUNCTION(Runtime_CopyDataProperties)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 
RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedProperties)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 
RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked)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 
RUNTIME_FUNCTION(Runtime_ToObject)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 
RUNTIME_FUNCTION(Runtime_ToPrimitive)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 
RUNTIME_FUNCTION(Runtime_ToPrimitive_Number)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 
RUNTIME_FUNCTION(Runtime_ToNumber)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 
RUNTIME_FUNCTION(Runtime_ToInteger)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 
RUNTIME_FUNCTION(Runtime_ToLength)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 
RUNTIME_FUNCTION(Runtime_ToString)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 
RUNTIME_FUNCTION(Runtime_ToName)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 
RUNTIME_FUNCTION(Runtime_SameValue)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 
RUNTIME_FUNCTION(Runtime_SameValueZero)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.
RUNTIME_FUNCTION(Runtime_Compare)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 
RUNTIME_FUNCTION(Runtime_HasInPrototypeChain)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 )
RUNTIME_FUNCTION(Runtime_CreateIterResultObject)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 
RUNTIME_FUNCTION(Runtime_CreateKeyValueArray)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 
RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded)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 
RUNTIME_FUNCTION(Runtime_CreateDataProperty)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