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 
GetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,LanguageMode language_mode)19 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
20                                                Handle<Object> object,
21                                                Handle<Object> key,
22                                                LanguageMode language_mode) {
23   if (object->IsUndefined() || object->IsNull()) {
24     THROW_NEW_ERROR(
25         isolate,
26         NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
27         Object);
28   }
29 
30   bool success = false;
31   LookupIterator it =
32       LookupIterator::PropertyOrElement(isolate, object, key, &success);
33   if (!success) return MaybeHandle<Object>();
34 
35   return Object::GetProperty(&it, language_mode);
36 }
37 
38 
KeyedGetObjectProperty(Isolate * isolate,Handle<Object> receiver_obj,Handle<Object> key_obj,LanguageMode language_mode)39 static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate,
40                                                   Handle<Object> receiver_obj,
41                                                   Handle<Object> key_obj,
42                                                   LanguageMode language_mode) {
43   // Fast cases for getting named properties of the receiver JSObject
44   // itself.
45   //
46   // The global proxy objects has to be excluded since LookupOwn on
47   // the global proxy object can return a valid result even though the
48   // global proxy object never has properties.  This is the case
49   // because the global proxy object forwards everything to its hidden
50   // prototype including own lookups.
51   //
52   // Additionally, we need to make sure that we do not cache results
53   // for objects that require access checks.
54   if (receiver_obj->IsJSObject()) {
55     if (!receiver_obj->IsJSGlobalProxy() &&
56         !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
57       DisallowHeapAllocation no_allocation;
58       Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
59       Handle<Name> key = Handle<Name>::cast(key_obj);
60       if (receiver->IsJSGlobalObject()) {
61         // Attempt dictionary lookup.
62         GlobalDictionary* dictionary = receiver->global_dictionary();
63         int entry = dictionary->FindEntry(key);
64         if (entry != GlobalDictionary::kNotFound) {
65           DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
66           PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
67           if (cell->property_details().type() == DATA) {
68             Object* value = cell->value();
69             if (!value->IsTheHole()) return Handle<Object>(value, isolate);
70             // If value is the hole (meaning, absent) do the general lookup.
71           }
72         }
73       } else if (!receiver->HasFastProperties()) {
74         // Attempt dictionary lookup.
75         NameDictionary* dictionary = receiver->property_dictionary();
76         int entry = dictionary->FindEntry(key);
77         if ((entry != NameDictionary::kNotFound) &&
78             (dictionary->DetailsAt(entry).type() == DATA)) {
79           Object* value = dictionary->ValueAt(entry);
80           return Handle<Object>(value, isolate);
81         }
82       }
83     } else if (key_obj->IsSmi()) {
84       // JSObject without a name key. If the key is a Smi, check for a
85       // definite out-of-bounds access to elements, which is a strong indicator
86       // that subsequent accesses will also call the runtime. Proactively
87       // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
88       // doubles for those future calls in the case that the elements would
89       // become FAST_DOUBLE_ELEMENTS.
90       Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
91       ElementsKind elements_kind = js_object->GetElementsKind();
92       if (IsFastDoubleElementsKind(elements_kind)) {
93         if (Smi::cast(*key_obj)->value() >= js_object->elements()->length()) {
94           elements_kind = IsFastHoleyElementsKind(elements_kind)
95                               ? FAST_HOLEY_ELEMENTS
96                               : FAST_ELEMENTS;
97           JSObject::TransitionElementsKind(js_object, elements_kind);
98         }
99       } else {
100         DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
101                !IsFastElementsKind(elements_kind));
102       }
103     }
104   } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
105     // Fast case for string indexing using [] with a smi index.
106     Handle<String> str = Handle<String>::cast(receiver_obj);
107     int index = Handle<Smi>::cast(key_obj)->value();
108     if (index >= 0 && index < str->length()) {
109       Factory* factory = isolate->factory();
110       return factory->LookupSingleCharacterStringFromCode(
111           String::Flatten(str)->Get(index));
112     }
113   }
114 
115   // Fall back to GetObjectProperty.
116   return Runtime::GetObjectProperty(isolate, receiver_obj, key_obj,
117                                     language_mode);
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::HIDDEN);
128   if (!success) return Nothing<bool>();
129 
130   return JSReceiver::DeleteProperty(&it, language_mode);
131 }
132 
133 
SetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,LanguageMode language_mode)134 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
135                                                Handle<Object> object,
136                                                Handle<Object> key,
137                                                Handle<Object> value,
138                                                LanguageMode language_mode) {
139   if (object->IsUndefined() || object->IsNull()) {
140     THROW_NEW_ERROR(
141         isolate,
142         NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
143         Object);
144   }
145 
146   // Check if the given key is an array index.
147   bool success = false;
148   LookupIterator it =
149       LookupIterator::PropertyOrElement(isolate, object, key, &success);
150   if (!success) return MaybeHandle<Object>();
151 
152   MAYBE_RETURN_NULL(Object::SetProperty(&it, value, language_mode,
153                                         Object::MAY_BE_STORE_FROM_KEYED));
154   return value;
155 }
156 
157 
RUNTIME_FUNCTION(Runtime_GetPrototype)158 RUNTIME_FUNCTION(Runtime_GetPrototype) {
159   HandleScope scope(isolate);
160   DCHECK(args.length() == 1);
161   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
162   Handle<Object> prototype;
163   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype,
164                                      Object::GetPrototype(isolate, obj));
165   return *prototype;
166 }
167 
168 
RUNTIME_FUNCTION(Runtime_InternalSetPrototype)169 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
170   HandleScope scope(isolate);
171   DCHECK(args.length() == 2);
172   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
173   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
174   MAYBE_RETURN(
175       JSReceiver::SetPrototype(obj, prototype, false, Object::THROW_ON_ERROR),
176       isolate->heap()->exception());
177   return *obj;
178 }
179 
180 
RUNTIME_FUNCTION(Runtime_SetPrototype)181 RUNTIME_FUNCTION(Runtime_SetPrototype) {
182   HandleScope scope(isolate);
183   DCHECK(args.length() == 2);
184   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
185   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
186   MAYBE_RETURN(
187       JSReceiver::SetPrototype(obj, prototype, true, Object::THROW_ON_ERROR),
188       isolate->heap()->exception());
189   return *obj;
190 }
191 
192 
193 // Enumerator used as indices into the array returned from GetOwnProperty
194 enum PropertyDescriptorIndices {
195   IS_ACCESSOR_INDEX,
196   VALUE_INDEX,
197   GETTER_INDEX,
198   SETTER_INDEX,
199   WRITABLE_INDEX,
200   ENUMERABLE_INDEX,
201   CONFIGURABLE_INDEX,
202   DESCRIPTOR_SIZE
203 };
204 
205 
GetOwnProperty(Isolate * isolate,Handle<JSObject> obj,Handle<Name> name)206 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
207                                                           Handle<JSObject> obj,
208                                                           Handle<Name> name) {
209   Heap* heap = isolate->heap();
210   Factory* factory = isolate->factory();
211 
212   // Get attributes.
213   LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name,
214                                                         LookupIterator::HIDDEN);
215   Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
216 
217   if (!maybe.IsJust()) return MaybeHandle<Object>();
218   PropertyAttributes attrs = maybe.FromJust();
219   if (attrs == ABSENT) return factory->undefined_value();
220 
221   DCHECK(!isolate->has_pending_exception());
222   Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
223   elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
224   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
225 
226   bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
227                           it.GetAccessors()->IsAccessorPair();
228   elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
229 
230   if (is_accessor_pair) {
231     Handle<AccessorPair> accessors =
232         Handle<AccessorPair>::cast(it.GetAccessors());
233     Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
234     Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
235     elms->set(GETTER_INDEX, *getter);
236     elms->set(SETTER_INDEX, *setter);
237   } else {
238     Handle<Object> value;
239     ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
240                                Object);
241     elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
242     elms->set(VALUE_INDEX, *value);
243   }
244 
245   return factory->NewJSArrayWithElements(elms);
246 }
247 
248 
249 // Returns an array with the property description:
250 //  if args[1] is not a property on args[0]
251 //          returns undefined
252 //  if args[1] is a data property on args[0]
253 //         [false, value, Writeable, Enumerable, Configurable]
254 //  if args[1] is an accessor on args[0]
255 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
256 // TODO(jkummerow): Deprecated. Remove all callers and delete.
RUNTIME_FUNCTION(Runtime_GetOwnProperty_Legacy)257 RUNTIME_FUNCTION(Runtime_GetOwnProperty_Legacy) {
258   HandleScope scope(isolate);
259   DCHECK(args.length() == 2);
260   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
261   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
262   Handle<Object> result;
263   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
264                                      GetOwnProperty(isolate, obj, name));
265   return *result;
266 }
267 
268 
269 // ES6 19.1.2.6
RUNTIME_FUNCTION(Runtime_GetOwnProperty)270 RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
271   HandleScope scope(isolate);
272   DCHECK(args.length() == 2);
273   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
274   CONVERT_ARG_HANDLE_CHECKED(Object, raw_name, 1);
275   // 1. Let obj be ? ToObject(O).
276   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
277                                      Execution::ToObject(isolate, object));
278   // 2. Let key be ? ToPropertyKey(P).
279   Handle<Name> key;
280   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
281                                      Object::ToName(isolate, raw_name));
282 
283   // 3. Let desc be ? obj.[[GetOwnProperty]](key).
284   PropertyDescriptor desc;
285   Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
286       isolate, Handle<JSReceiver>::cast(object), key, &desc);
287   MAYBE_RETURN(found, isolate->heap()->exception());
288   // 4. Return FromPropertyDescriptor(desc).
289   if (!found.FromJust()) return isolate->heap()->undefined_value();
290   return *desc.ToObject(isolate);
291 }
292 
293 
RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties)294 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
295   HandleScope scope(isolate);
296   DCHECK(args.length() == 2);
297   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
298   CONVERT_SMI_ARG_CHECKED(properties, 1);
299   // Conservative upper limit to prevent fuzz tests from going OOM.
300   RUNTIME_ASSERT(properties <= 100000);
301   if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
302     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
303                                   "OptimizeForAdding");
304   }
305   return *object;
306 }
307 
308 
RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext)309 RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) {
310   HandleScope scope(isolate);
311   DCHECK_EQ(1, args.length());
312   CONVERT_SMI_ARG_CHECKED(slot, 0);
313 
314   // Go up context chain to the script context.
315   Handle<Context> script_context(isolate->context()->script_context(), isolate);
316   DCHECK(script_context->IsScriptContext());
317   DCHECK(script_context->get(slot)->IsPropertyCell());
318 
319   // Lookup the named property on the global object.
320   Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate);
321   Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
322   Handle<JSGlobalObject> global_object(script_context->global_object(),
323                                        isolate);
324   LookupIterator it(global_object, name, LookupIterator::HIDDEN);
325 
326   // Switch to fast mode only if there is a data property and it's not on
327   // a hidden prototype.
328   if (it.state() == LookupIterator::DATA &&
329       it.GetHolder<Object>().is_identical_to(global_object)) {
330     // Now update the cell in the script context.
331     Handle<PropertyCell> cell = it.GetPropertyCell();
332     script_context->set(slot, *cell);
333   } else {
334     // This is not a fast case, so keep this access in a slow mode.
335     // Store empty_property_cell here to release the outdated property cell.
336     script_context->set(slot, isolate->heap()->empty_property_cell());
337   }
338 
339   Handle<Object> result;
340   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
341   return *result;
342 }
343 
344 
345 namespace {
346 
StoreGlobalViaContext(Isolate * isolate,int slot,Handle<Object> value,LanguageMode language_mode)347 Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value,
348                               LanguageMode language_mode) {
349   // Go up context chain to the script context.
350   Handle<Context> script_context(isolate->context()->script_context(), isolate);
351   DCHECK(script_context->IsScriptContext());
352   DCHECK(script_context->get(slot)->IsPropertyCell());
353 
354   // Lookup the named property on the global object.
355   Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate);
356   Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
357   Handle<JSGlobalObject> global_object(script_context->global_object(),
358                                        isolate);
359   LookupIterator it(global_object, name, LookupIterator::HIDDEN);
360 
361   // Switch to fast mode only if there is a data property and it's not on
362   // a hidden prototype.
363   if (it.state() == LookupIterator::DATA &&
364       it.GetHolder<Object>().is_identical_to(global_object)) {
365     // Now update cell in the script context.
366     Handle<PropertyCell> cell = it.GetPropertyCell();
367     script_context->set(slot, *cell);
368   } else {
369     // This is not a fast case, so keep this access in a slow mode.
370     // Store empty_property_cell here to release the outdated property cell.
371     script_context->set(slot, isolate->heap()->empty_property_cell());
372   }
373 
374   MAYBE_RETURN(Object::SetProperty(&it, value, language_mode,
375                                    Object::CERTAINLY_NOT_STORE_FROM_KEYED),
376                isolate->heap()->exception());
377   return *value;
378 }
379 
380 }  // namespace
381 
382 
RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Sloppy)383 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Sloppy) {
384   HandleScope scope(isolate);
385   DCHECK_EQ(2, args.length());
386   CONVERT_SMI_ARG_CHECKED(slot, 0);
387   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
388 
389   return StoreGlobalViaContext(isolate, slot, value, SLOPPY);
390 }
391 
392 
RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Strict)393 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Strict) {
394   HandleScope scope(isolate);
395   DCHECK_EQ(2, args.length());
396   CONVERT_SMI_ARG_CHECKED(slot, 0);
397   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
398 
399   return StoreGlobalViaContext(isolate, slot, value, STRICT);
400 }
401 
402 
RUNTIME_FUNCTION(Runtime_GetProperty)403 RUNTIME_FUNCTION(Runtime_GetProperty) {
404   HandleScope scope(isolate);
405   DCHECK(args.length() == 2);
406 
407   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
408   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
409 
410   Handle<Object> result;
411   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
412       isolate, result,
413       Runtime::GetObjectProperty(isolate, object, key, SLOPPY));
414   return *result;
415 }
416 
417 
RUNTIME_FUNCTION(Runtime_GetPropertyStrong)418 RUNTIME_FUNCTION(Runtime_GetPropertyStrong) {
419   HandleScope scope(isolate);
420   DCHECK(args.length() == 2);
421 
422   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
423   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
424 
425   Handle<Object> result;
426   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
427       isolate, result,
428       Runtime::GetObjectProperty(isolate, object, key, STRONG));
429   return *result;
430 }
431 
432 
433 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(Runtime_KeyedGetProperty)434 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
435   HandleScope scope(isolate);
436   DCHECK(args.length() == 2);
437 
438   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
439   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
440 
441   Handle<Object> result;
442   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
443       isolate, result,
444       KeyedGetObjectProperty(isolate, receiver_obj, key_obj, SLOPPY));
445   return *result;
446 }
447 
448 
RUNTIME_FUNCTION(Runtime_KeyedGetPropertyStrong)449 RUNTIME_FUNCTION(Runtime_KeyedGetPropertyStrong) {
450   HandleScope scope(isolate);
451   DCHECK(args.length() == 2);
452 
453   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
454   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
455 
456   Handle<Object> result;
457   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
458       isolate, result,
459       KeyedGetObjectProperty(isolate, receiver_obj, key_obj, STRONG));
460   return *result;
461 }
462 
463 
RUNTIME_FUNCTION(Runtime_AddNamedProperty)464 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
465   HandleScope scope(isolate);
466   RUNTIME_ASSERT(args.length() == 4);
467 
468   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
469   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
470   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
471   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
472 
473 #ifdef DEBUG
474   uint32_t index = 0;
475   DCHECK(!name->ToArrayIndex(&index));
476   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
477   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
478   if (!maybe.IsJust()) return isolate->heap()->exception();
479   RUNTIME_ASSERT(!it.IsFound());
480 #endif
481 
482   Handle<Object> result;
483   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
484       isolate, result,
485       JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs));
486   return *result;
487 }
488 
489 
490 // Adds an element to an array.
491 // This is used to create an indexed data property into an array.
RUNTIME_FUNCTION(Runtime_AddElement)492 RUNTIME_FUNCTION(Runtime_AddElement) {
493   HandleScope scope(isolate);
494   RUNTIME_ASSERT(args.length() == 3);
495 
496   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
497   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
498   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
499 
500   uint32_t index = 0;
501   CHECK(key->ToArrayIndex(&index));
502 
503 #ifdef DEBUG
504   LookupIterator it(isolate, object, index,
505                     LookupIterator::OWN_SKIP_INTERCEPTOR);
506   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
507   if (!maybe.IsJust()) return isolate->heap()->exception();
508   RUNTIME_ASSERT(!it.IsFound());
509 
510   if (object->IsJSArray()) {
511     Handle<JSArray> array = Handle<JSArray>::cast(object);
512     RUNTIME_ASSERT(!JSArray::WouldChangeReadOnlyLength(array, index));
513   }
514 #endif
515 
516   Handle<Object> result;
517   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
518       isolate, result,
519       JSObject::SetOwnElementIgnoreAttributes(object, index, value, NONE));
520   return *result;
521 }
522 
523 
RUNTIME_FUNCTION(Runtime_AppendElement)524 RUNTIME_FUNCTION(Runtime_AppendElement) {
525   HandleScope scope(isolate);
526   RUNTIME_ASSERT(args.length() == 2);
527 
528   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
529   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
530 
531   uint32_t index;
532   CHECK(array->length()->ToArrayIndex(&index));
533 
534   Handle<Object> result;
535   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
536       isolate, result, JSObject::AddDataElement(array, index, value, NONE));
537   JSObject::ValidateElements(array);
538   return *array;
539 }
540 
541 
RUNTIME_FUNCTION(Runtime_SetProperty)542 RUNTIME_FUNCTION(Runtime_SetProperty) {
543   HandleScope scope(isolate);
544   RUNTIME_ASSERT(args.length() == 4);
545 
546   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
547   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
548   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
549   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
550   LanguageMode language_mode = language_mode_arg;
551 
552   Handle<Object> result;
553   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
554       isolate, result,
555       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
556   return *result;
557 }
558 
559 
560 namespace {
561 
562 // ES6 section 12.5.4.
DeleteProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,LanguageMode language_mode)563 Object* DeleteProperty(Isolate* isolate, Handle<Object> object,
564                        Handle<Object> key, LanguageMode language_mode) {
565   Handle<JSReceiver> receiver;
566   if (!JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
567     THROW_NEW_ERROR_RETURN_FAILURE(
568         isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
569   }
570   Maybe<bool> result =
571       Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode);
572   MAYBE_RETURN(result, isolate->heap()->exception());
573   return isolate->heap()->ToBoolean(result.FromJust());
574 }
575 
576 }  // namespace
577 
578 
RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy)579 RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy) {
580   HandleScope scope(isolate);
581   DCHECK_EQ(2, args.length());
582   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
583   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
584   return DeleteProperty(isolate, object, key, SLOPPY);
585 }
586 
587 
RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict)588 RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict) {
589   HandleScope scope(isolate);
590   DCHECK_EQ(2, args.length());
591   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
592   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
593   return DeleteProperty(isolate, object, key, STRICT);
594 }
595 
596 
HasOwnPropertyImplementation(Isolate * isolate,Handle<JSObject> object,Handle<Name> key)597 static Object* HasOwnPropertyImplementation(Isolate* isolate,
598                                             Handle<JSObject> object,
599                                             Handle<Name> key) {
600   Maybe<bool> maybe = JSReceiver::HasOwnProperty(object, key);
601   if (!maybe.IsJust()) return isolate->heap()->exception();
602   if (maybe.FromJust()) return isolate->heap()->true_value();
603   // Handle hidden prototypes.  If there's a hidden prototype above this thing
604   // then we have to check it for properties, because they are supposed to
605   // look like they are on this object.
606   PrototypeIterator iter(isolate, object);
607   if (!iter.IsAtEnd() &&
608       PrototypeIterator::GetCurrent<HeapObject>(iter)
609           ->map()
610           ->is_hidden_prototype()) {
611     // TODO(verwaest): The recursion is not necessary for keys that are array
612     // indices. Removing this.
613     // Casting to JSObject is fine because JSProxies are never used as
614     // hidden prototypes.
615     return HasOwnPropertyImplementation(
616         isolate, PrototypeIterator::GetCurrent<JSObject>(iter), key);
617   }
618   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
619   return isolate->heap()->false_value();
620 }
621 
622 
RUNTIME_FUNCTION(Runtime_HasOwnProperty)623 RUNTIME_FUNCTION(Runtime_HasOwnProperty) {
624   HandleScope scope(isolate);
625   DCHECK(args.length() == 2);
626   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0)
627   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
628 
629   uint32_t index;
630   const bool key_is_array_index = key->AsArrayIndex(&index);
631 
632   // Only JS objects can have properties.
633   if (object->IsJSObject()) {
634     Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
635     // Fast case: either the key is a real named property or it is not
636     // an array index and there are no interceptors or hidden
637     // prototypes.
638     // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to
639     // handle all cases directly (without this custom fast path).
640     Maybe<bool> maybe = Nothing<bool>();
641     if (key_is_array_index) {
642       LookupIterator it(js_obj->GetIsolate(), js_obj, index,
643                         LookupIterator::HIDDEN);
644       maybe = JSReceiver::HasProperty(&it);
645     } else {
646       maybe = JSObject::HasRealNamedProperty(js_obj, key);
647     }
648     if (!maybe.IsJust()) return isolate->heap()->exception();
649     DCHECK(!isolate->has_pending_exception());
650     if (maybe.FromJust()) {
651       return isolate->heap()->true_value();
652     }
653     Map* map = js_obj->map();
654     if (!key_is_array_index && !map->has_named_interceptor() &&
655         !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
656       return isolate->heap()->false_value();
657     }
658     // Slow case.
659     return HasOwnPropertyImplementation(isolate, Handle<JSObject>(js_obj),
660                                         Handle<Name>(key));
661   } else if (object->IsString() && key_is_array_index) {
662     // Well, there is one exception:  Handle [] on strings.
663     Handle<String> string = Handle<String>::cast(object);
664     if (index < static_cast<uint32_t>(string->length())) {
665       return isolate->heap()->true_value();
666     }
667   } else if (object->IsJSProxy()) {
668     Maybe<bool> result =
669         JSReceiver::HasOwnProperty(Handle<JSProxy>::cast(object), key);
670     if (!result.IsJust()) return isolate->heap()->exception();
671     return isolate->heap()->ToBoolean(result.FromJust());
672   }
673   return isolate->heap()->false_value();
674 }
675 
676 
677 // ES6 section 12.9.3, operator in.
RUNTIME_FUNCTION(Runtime_HasProperty)678 RUNTIME_FUNCTION(Runtime_HasProperty) {
679   HandleScope scope(isolate);
680   DCHECK_EQ(2, args.length());
681   CONVERT_ARG_HANDLE_CHECKED(Object, key, 0);
682   CONVERT_ARG_HANDLE_CHECKED(Object, object, 1);
683 
684   // Check that {object} is actually a receiver.
685   if (!object->IsJSReceiver()) {
686     THROW_NEW_ERROR_RETURN_FAILURE(
687         isolate,
688         NewTypeError(MessageTemplate::kInvalidInOperatorUse, key, object));
689   }
690   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
691 
692   // Convert the {key} to a name.
693   Handle<Name> name;
694   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
695                                      Object::ToName(isolate, key));
696 
697   // Lookup the {name} on {receiver}.
698   Maybe<bool> maybe = JSReceiver::HasProperty(receiver, name);
699   if (!maybe.IsJust()) return isolate->heap()->exception();
700   return isolate->heap()->ToBoolean(maybe.FromJust());
701 }
702 
703 
RUNTIME_FUNCTION(Runtime_PropertyIsEnumerable)704 RUNTIME_FUNCTION(Runtime_PropertyIsEnumerable) {
705   HandleScope scope(isolate);
706   DCHECK(args.length() == 2);
707 
708   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
709   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
710 
711   Maybe<PropertyAttributes> maybe =
712       JSReceiver::GetOwnPropertyAttributes(object, key);
713   if (!maybe.IsJust()) return isolate->heap()->exception();
714   if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value();
715   return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
716 }
717 
718 
719 // Returns either a FixedArray or, if the given object has an enum cache that
720 // contains all enumerable properties of the object and its prototypes have
721 // none, the map of the object. This is used to speed up the check for
722 // deletions during a for-in.
RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast)723 RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
724   SealHandleScope shs(isolate);
725   DCHECK(args.length() == 1);
726 
727   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
728 
729   if (raw_object->IsSimpleEnum()) return raw_object->map();
730 
731   HandleScope scope(isolate);
732   Handle<JSReceiver> object(raw_object);
733   Handle<FixedArray> content;
734   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
735       isolate, content, JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS,
736                                             ENUMERABLE_STRINGS));
737 
738   // Test again, since cache may have been built by preceding call.
739   if (object->IsSimpleEnum()) return object->map();
740 
741   return *content;
742 }
743 
744 
RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys)745 RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) {
746   HandleScope scope(isolate);
747   DCHECK(args.length() == 2);
748   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
749   CONVERT_SMI_ARG_CHECKED(filter_value, 1);
750   PropertyFilter filter = static_cast<PropertyFilter>(filter_value);
751 
752   Handle<FixedArray> keys;
753   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
754       isolate, keys, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY, filter,
755                                          CONVERT_TO_STRING));
756 
757   return *isolate->factory()->NewJSArrayWithElements(keys);
758 }
759 
760 
761 // Return information on whether an object has a named or indexed interceptor.
762 // args[0]: object
RUNTIME_FUNCTION(Runtime_GetInterceptorInfo)763 RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
764   HandleScope scope(isolate);
765   DCHECK(args.length() == 1);
766   if (!args[0]->IsJSObject()) {
767     return Smi::FromInt(0);
768   }
769   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
770 
771   int result = 0;
772   if (obj->HasNamedInterceptor()) result |= 2;
773   if (obj->HasIndexedInterceptor()) result |= 1;
774 
775   return Smi::FromInt(result);
776 }
777 
778 
RUNTIME_FUNCTION(Runtime_ToFastProperties)779 RUNTIME_FUNCTION(Runtime_ToFastProperties) {
780   HandleScope scope(isolate);
781   DCHECK(args.length() == 1);
782   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
783   if (object->IsJSObject() && !object->IsJSGlobalObject()) {
784     JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
785                                 "RuntimeToFastProperties");
786   }
787   return *object;
788 }
789 
790 
RUNTIME_FUNCTION(Runtime_AllocateHeapNumber)791 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
792   HandleScope scope(isolate);
793   DCHECK(args.length() == 0);
794   return *isolate->factory()->NewHeapNumber(0);
795 }
796 
797 
RUNTIME_FUNCTION(Runtime_NewObject)798 RUNTIME_FUNCTION(Runtime_NewObject) {
799   HandleScope scope(isolate);
800   DCHECK_EQ(2, args.length());
801   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
802   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1);
803   Handle<JSObject> result;
804   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
805                                      JSObject::New(target, new_target));
806   return *result;
807 }
808 
809 
RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize)810 RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) {
811   HandleScope scope(isolate);
812   DCHECK(args.length() == 1);
813 
814   CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0);
815   initial_map->CompleteInobjectSlackTracking();
816 
817   return isolate->heap()->undefined_value();
818 }
819 
820 
RUNTIME_FUNCTION(Runtime_GlobalProxy)821 RUNTIME_FUNCTION(Runtime_GlobalProxy) {
822   SealHandleScope shs(isolate);
823   DCHECK(args.length() == 1);
824   CONVERT_ARG_CHECKED(JSFunction, function, 0);
825   return function->context()->global_proxy();
826 }
827 
828 
RUNTIME_FUNCTION(Runtime_LookupAccessor)829 RUNTIME_FUNCTION(Runtime_LookupAccessor) {
830   HandleScope scope(isolate);
831   DCHECK(args.length() == 3);
832   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
833   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
834   CONVERT_SMI_ARG_CHECKED(flag, 2);
835   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
836   if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
837   Handle<Object> result;
838   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
839       isolate, result,
840       JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
841   return *result;
842 }
843 
844 
RUNTIME_FUNCTION(Runtime_LoadMutableDouble)845 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
846   HandleScope scope(isolate);
847   DCHECK(args.length() == 2);
848   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
849   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
850   RUNTIME_ASSERT((index->value() & 1) == 1);
851   FieldIndex field_index =
852       FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
853   if (field_index.is_inobject()) {
854     RUNTIME_ASSERT(field_index.property_index() <
855                    object->map()->GetInObjectProperties());
856   } else {
857     RUNTIME_ASSERT(field_index.outobject_array_index() <
858                    object->properties()->length());
859   }
860   return *JSObject::FastPropertyAt(object, Representation::Double(),
861                                    field_index);
862 }
863 
864 
RUNTIME_FUNCTION(Runtime_TryMigrateInstance)865 RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
866   HandleScope scope(isolate);
867   DCHECK(args.length() == 1);
868   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
869   if (!object->IsJSObject()) return Smi::FromInt(0);
870   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
871   if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
872   // This call must not cause lazy deopts, because it's called from deferred
873   // code where we can't handle lazy deopts for lack of a suitable bailout
874   // ID. So we just try migration and signal failure if necessary,
875   // which will also trigger a deopt.
876   if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0);
877   return *object;
878 }
879 
880 
RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy)881 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
882   SealHandleScope shs(isolate);
883   DCHECK(args.length() == 1);
884   CONVERT_ARG_CHECKED(Object, obj, 0);
885   return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
886 }
887 
888 
IsValidAccessor(Handle<Object> obj)889 static bool IsValidAccessor(Handle<Object> obj) {
890   return obj->IsUndefined() || obj->IsCallable() || obj->IsNull();
891 }
892 
893 
894 // Implements part of 8.12.9 DefineOwnProperty.
895 // There are 3 cases that lead here:
896 // Step 4b - define a new accessor property.
897 // Steps 9c & 12 - replace an existing data property with an accessor property.
898 // Step 12 - update an existing accessor property with an accessor or generic
899 //           descriptor.
RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked)900 RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
901   HandleScope scope(isolate);
902   DCHECK(args.length() == 5);
903   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
904   RUNTIME_ASSERT(!obj->IsNull());
905   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
906   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
907   RUNTIME_ASSERT(IsValidAccessor(getter));
908   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
909   RUNTIME_ASSERT(IsValidAccessor(setter));
910   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
911 
912   RETURN_FAILURE_ON_EXCEPTION(
913       isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
914   return isolate->heap()->undefined_value();
915 }
916 
917 
918 // Implements part of 8.12.9 DefineOwnProperty.
919 // There are 3 cases that lead here:
920 // Step 4a - define a new data property.
921 // Steps 9b & 12 - replace an existing accessor property with a data property.
922 // Step 12 - update an existing data property with a data or generic
923 //           descriptor.
RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked)924 RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
925   HandleScope scope(isolate);
926   DCHECK(args.length() == 4);
927   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
928   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
929   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
930   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
931 
932   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
933                                                         LookupIterator::OWN);
934   if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) {
935     return isolate->heap()->undefined_value();
936   }
937 
938   Handle<Object> result;
939   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
940       isolate, result, JSObject::DefineOwnPropertyIgnoreAttributes(
941                            &it, value, attrs, JSObject::DONT_FORCE_FIELD));
942 
943   return *result;
944 }
945 
946 
947 // Return property without being observable by accessors or interceptors.
RUNTIME_FUNCTION(Runtime_GetDataProperty)948 RUNTIME_FUNCTION(Runtime_GetDataProperty) {
949   HandleScope scope(isolate);
950   DCHECK(args.length() == 2);
951   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
952   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
953   return *JSReceiver::GetDataProperty(object, name);
954 }
955 
956 
RUNTIME_FUNCTION(Runtime_HasFastPackedElements)957 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
958   SealHandleScope shs(isolate);
959   DCHECK(args.length() == 1);
960   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
961   return isolate->heap()->ToBoolean(
962       IsFastPackedElementsKind(obj->map()->elements_kind()));
963 }
964 
965 
RUNTIME_FUNCTION(Runtime_ValueOf)966 RUNTIME_FUNCTION(Runtime_ValueOf) {
967   SealHandleScope shs(isolate);
968   DCHECK(args.length() == 1);
969   CONVERT_ARG_CHECKED(Object, obj, 0);
970   if (!obj->IsJSValue()) return obj;
971   return JSValue::cast(obj)->value();
972 }
973 
974 
RUNTIME_FUNCTION(Runtime_SetValueOf)975 RUNTIME_FUNCTION(Runtime_SetValueOf) {
976   SealHandleScope shs(isolate);
977   DCHECK(args.length() == 2);
978   CONVERT_ARG_CHECKED(Object, obj, 0);
979   CONVERT_ARG_CHECKED(Object, value, 1);
980   if (!obj->IsJSValue()) return value;
981   JSValue::cast(obj)->set_value(value);
982   return value;
983 }
984 
985 
RUNTIME_FUNCTION(Runtime_JSValueGetValue)986 RUNTIME_FUNCTION(Runtime_JSValueGetValue) {
987   SealHandleScope shs(isolate);
988   DCHECK(args.length() == 1);
989   CONVERT_ARG_CHECKED(JSValue, obj, 0);
990   return JSValue::cast(obj)->value();
991 }
992 
993 
RUNTIME_FUNCTION(Runtime_ObjectEquals)994 RUNTIME_FUNCTION(Runtime_ObjectEquals) {
995   SealHandleScope shs(isolate);
996   DCHECK(args.length() == 2);
997   CONVERT_ARG_CHECKED(Object, obj1, 0);
998   CONVERT_ARG_CHECKED(Object, obj2, 1);
999   return isolate->heap()->ToBoolean(obj1 == obj2);
1000 }
1001 
1002 
RUNTIME_FUNCTION(Runtime_IsJSReceiver)1003 RUNTIME_FUNCTION(Runtime_IsJSReceiver) {
1004   SealHandleScope shs(isolate);
1005   DCHECK(args.length() == 1);
1006   CONVERT_ARG_CHECKED(Object, obj, 0);
1007   return isolate->heap()->ToBoolean(obj->IsJSReceiver());
1008 }
1009 
1010 
RUNTIME_FUNCTION(Runtime_IsStrong)1011 RUNTIME_FUNCTION(Runtime_IsStrong) {
1012   SealHandleScope shs(isolate);
1013   DCHECK(args.length() == 1);
1014   CONVERT_ARG_CHECKED(Object, obj, 0);
1015   return isolate->heap()->ToBoolean(obj->IsJSReceiver() &&
1016                                     JSReceiver::cast(obj)->map()->is_strong());
1017 }
1018 
1019 
RUNTIME_FUNCTION(Runtime_ClassOf)1020 RUNTIME_FUNCTION(Runtime_ClassOf) {
1021   SealHandleScope shs(isolate);
1022   DCHECK(args.length() == 1);
1023   CONVERT_ARG_CHECKED(Object, obj, 0);
1024   if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
1025   return JSReceiver::cast(obj)->class_name();
1026 }
1027 
1028 
RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked)1029 RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
1030   HandleScope scope(isolate);
1031   DCHECK(args.length() == 4);
1032   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1033   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1034   CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
1035   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1036 
1037   RETURN_FAILURE_ON_EXCEPTION(
1038       isolate,
1039       JSObject::DefineAccessor(object, name, getter,
1040                                isolate->factory()->null_value(), attrs));
1041   return isolate->heap()->undefined_value();
1042 }
1043 
1044 
RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked)1045 RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
1046   HandleScope scope(isolate);
1047   DCHECK(args.length() == 4);
1048   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1049   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1050   CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
1051   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1052 
1053   RETURN_FAILURE_ON_EXCEPTION(
1054       isolate,
1055       JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1056                                setter, attrs));
1057   return isolate->heap()->undefined_value();
1058 }
1059 
1060 
RUNTIME_FUNCTION(Runtime_ToObject)1061 RUNTIME_FUNCTION(Runtime_ToObject) {
1062   HandleScope scope(isolate);
1063   DCHECK_EQ(1, args.length());
1064   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1065   Handle<JSReceiver> receiver;
1066   if (JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
1067     return *receiver;
1068   }
1069   THROW_NEW_ERROR_RETURN_FAILURE(
1070       isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
1071 }
1072 
1073 
RUNTIME_FUNCTION(Runtime_ToPrimitive)1074 RUNTIME_FUNCTION(Runtime_ToPrimitive) {
1075   HandleScope scope(isolate);
1076   DCHECK_EQ(1, args.length());
1077   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1078   Handle<Object> result;
1079   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1080                                      Object::ToPrimitive(input));
1081   return *result;
1082 }
1083 
1084 
RUNTIME_FUNCTION(Runtime_ToPrimitive_Number)1085 RUNTIME_FUNCTION(Runtime_ToPrimitive_Number) {
1086   HandleScope scope(isolate);
1087   DCHECK_EQ(1, args.length());
1088   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1089   Handle<Object> result;
1090   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1091       isolate, result, Object::ToPrimitive(input, ToPrimitiveHint::kNumber));
1092   return *result;
1093 }
1094 
1095 
RUNTIME_FUNCTION(Runtime_ToPrimitive_String)1096 RUNTIME_FUNCTION(Runtime_ToPrimitive_String) {
1097   HandleScope scope(isolate);
1098   DCHECK_EQ(1, args.length());
1099   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1100   Handle<Object> result;
1101   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1102       isolate, result, Object::ToPrimitive(input, ToPrimitiveHint::kString));
1103   return *result;
1104 }
1105 
1106 
RUNTIME_FUNCTION(Runtime_ToNumber)1107 RUNTIME_FUNCTION(Runtime_ToNumber) {
1108   HandleScope scope(isolate);
1109   DCHECK_EQ(1, args.length());
1110   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1111   Handle<Object> result;
1112   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::ToNumber(input));
1113   return *result;
1114 }
1115 
1116 
RUNTIME_FUNCTION(Runtime_ToInteger)1117 RUNTIME_FUNCTION(Runtime_ToInteger) {
1118   HandleScope scope(isolate);
1119   DCHECK_EQ(1, args.length());
1120   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1121   Handle<Object> result;
1122   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1123                                      Object::ToInteger(isolate, input));
1124   return *result;
1125 }
1126 
1127 
RUNTIME_FUNCTION(Runtime_ToLength)1128 RUNTIME_FUNCTION(Runtime_ToLength) {
1129   HandleScope scope(isolate);
1130   DCHECK_EQ(1, args.length());
1131   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1132   Handle<Object> result;
1133   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1134                                      Object::ToLength(isolate, input));
1135   return *result;
1136 }
1137 
1138 
RUNTIME_FUNCTION(Runtime_ToString)1139 RUNTIME_FUNCTION(Runtime_ToString) {
1140   HandleScope scope(isolate);
1141   DCHECK_EQ(1, args.length());
1142   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1143   Handle<Object> result;
1144   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1145                                      Object::ToString(isolate, input));
1146   return *result;
1147 }
1148 
1149 
RUNTIME_FUNCTION(Runtime_ToName)1150 RUNTIME_FUNCTION(Runtime_ToName) {
1151   HandleScope scope(isolate);
1152   DCHECK_EQ(1, args.length());
1153   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1154   Handle<Object> result;
1155   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1156                                      Object::ToName(isolate, input));
1157   return *result;
1158 }
1159 
1160 
RUNTIME_FUNCTION(Runtime_Equals)1161 RUNTIME_FUNCTION(Runtime_Equals) {
1162   HandleScope scope(isolate);
1163   DCHECK_EQ(2, args.length());
1164   CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
1165   CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
1166   Maybe<bool> result = Object::Equals(x, y);
1167   if (!result.IsJust()) return isolate->heap()->exception();
1168   // TODO(bmeurer): Change this at some point to return true/false instead.
1169   return Smi::FromInt(result.FromJust() ? EQUAL : NOT_EQUAL);
1170 }
1171 
1172 
RUNTIME_FUNCTION(Runtime_StrictEquals)1173 RUNTIME_FUNCTION(Runtime_StrictEquals) {
1174   SealHandleScope scope(isolate);
1175   DCHECK_EQ(2, args.length());
1176   CONVERT_ARG_CHECKED(Object, x, 0);
1177   CONVERT_ARG_CHECKED(Object, y, 1);
1178   // TODO(bmeurer): Change this at some point to return true/false instead.
1179   return Smi::FromInt(x->StrictEquals(y) ? EQUAL : NOT_EQUAL);
1180 }
1181 
1182 
1183 // TODO(bmeurer): Kill this special wrapper and use TF compatible LessThan,
1184 // GreaterThan, etc. which return true or false.
RUNTIME_FUNCTION(Runtime_Compare)1185 RUNTIME_FUNCTION(Runtime_Compare) {
1186   HandleScope scope(isolate);
1187   DCHECK_EQ(3, args.length());
1188   CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
1189   CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
1190   CONVERT_ARG_HANDLE_CHECKED(Object, ncr, 2);
1191   Maybe<ComparisonResult> result = Object::Compare(x, y);
1192   if (result.IsJust()) {
1193     switch (result.FromJust()) {
1194       case ComparisonResult::kLessThan:
1195         return Smi::FromInt(LESS);
1196       case ComparisonResult::kEqual:
1197         return Smi::FromInt(EQUAL);
1198       case ComparisonResult::kGreaterThan:
1199         return Smi::FromInt(GREATER);
1200       case ComparisonResult::kUndefined:
1201         return *ncr;
1202     }
1203     UNREACHABLE();
1204   }
1205   return isolate->heap()->exception();
1206 }
1207 
1208 
1209 // TODO(bmeurer): Kill this special wrapper and use TF compatible LessThan,
1210 // GreaterThan, etc. which return true or false.
RUNTIME_FUNCTION(Runtime_Compare_Strong)1211 RUNTIME_FUNCTION(Runtime_Compare_Strong) {
1212   HandleScope scope(isolate);
1213   DCHECK_EQ(3, args.length());
1214   CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
1215   CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
1216   CONVERT_ARG_HANDLE_CHECKED(Object, ncr, 2);
1217   Maybe<ComparisonResult> result = Object::Compare(x, y, Strength::STRONG);
1218   if (result.IsJust()) {
1219     switch (result.FromJust()) {
1220       case ComparisonResult::kLessThan:
1221         return Smi::FromInt(LESS);
1222       case ComparisonResult::kEqual:
1223         return Smi::FromInt(EQUAL);
1224       case ComparisonResult::kGreaterThan:
1225         return Smi::FromInt(GREATER);
1226       case ComparisonResult::kUndefined:
1227         return *ncr;
1228     }
1229     UNREACHABLE();
1230   }
1231   return isolate->heap()->exception();
1232 }
1233 
1234 
RUNTIME_FUNCTION(Runtime_InstanceOf)1235 RUNTIME_FUNCTION(Runtime_InstanceOf) {
1236   // ECMA-262, section 11.8.6, page 54.
1237   HandleScope shs(isolate);
1238   DCHECK_EQ(2, args.length());
1239   DCHECK(args.length() == 2);
1240   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1241   CONVERT_ARG_HANDLE_CHECKED(Object, callable, 1);
1242   // {callable} must have a [[Call]] internal method.
1243   if (!callable->IsCallable()) {
1244     THROW_NEW_ERROR_RETURN_FAILURE(
1245         isolate,
1246         NewTypeError(MessageTemplate::kInstanceofFunctionExpected, callable));
1247   }
1248   // If {object} is not a receiver, return false.
1249   if (!object->IsJSReceiver()) {
1250     return isolate->heap()->false_value();
1251   }
1252   // Check if {callable} is bound, if so, get [[BoundTargetFunction]] from it
1253   // and use that instead of {callable}.
1254   while (callable->IsJSBoundFunction()) {
1255     callable =
1256         handle(Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
1257                isolate);
1258   }
1259   DCHECK(callable->IsCallable());
1260   // Get the "prototype" of {callable}; raise an error if it's not a receiver.
1261   Handle<Object> prototype;
1262   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1263       isolate, prototype,
1264       Object::GetProperty(callable, isolate->factory()->prototype_string()));
1265   if (!prototype->IsJSReceiver()) {
1266     THROW_NEW_ERROR_RETURN_FAILURE(
1267         isolate,
1268         NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype));
1269   }
1270   // Return whether or not {prototype} is in the prototype chain of {object}.
1271   Maybe<bool> result = Object::HasInPrototypeChain(isolate, object, prototype);
1272   MAYBE_RETURN(result, isolate->heap()->exception());
1273   return isolate->heap()->ToBoolean(result.FromJust());
1274 }
1275 
1276 
RUNTIME_FUNCTION(Runtime_HasInPrototypeChain)1277 RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
1278   HandleScope scope(isolate);
1279   DCHECK_EQ(2, args.length());
1280   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1281   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1282   Maybe<bool> result = Object::HasInPrototypeChain(isolate, object, prototype);
1283   MAYBE_RETURN(result, isolate->heap()->exception());
1284   return isolate->heap()->ToBoolean(result.FromJust());
1285 }
1286 
1287 
1288 // ES6 section 7.4.7 CreateIterResultObject ( value, done )
RUNTIME_FUNCTION(Runtime_CreateIterResultObject)1289 RUNTIME_FUNCTION(Runtime_CreateIterResultObject) {
1290   HandleScope scope(isolate);
1291   DCHECK_EQ(2, args.length());
1292   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
1293   CONVERT_ARG_HANDLE_CHECKED(Object, done, 1);
1294   return *isolate->factory()->NewJSIteratorResult(value, done);
1295 }
1296 
1297 
RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded)1298 RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) {
1299   SealHandleScope shs(isolate);
1300   DCHECK_EQ(1, args.length());
1301   CONVERT_ARG_CHECKED(Object, object, 0);
1302   return isolate->heap()->ToBoolean(object->IsAccessCheckNeeded());
1303 }
1304 
1305 
RUNTIME_FUNCTION(Runtime_ObjectDefineProperty)1306 RUNTIME_FUNCTION(Runtime_ObjectDefineProperty) {
1307   HandleScope scope(isolate);
1308   DCHECK(args.length() == 3);
1309   CONVERT_ARG_HANDLE_CHECKED(Object, o, 0);
1310   CONVERT_ARG_HANDLE_CHECKED(Object, name, 1);
1311   CONVERT_ARG_HANDLE_CHECKED(Object, attributes, 2);
1312   return JSReceiver::DefineProperty(isolate, o, name, attributes);
1313 }
1314 
1315 
RUNTIME_FUNCTION(Runtime_ObjectDefineProperties)1316 RUNTIME_FUNCTION(Runtime_ObjectDefineProperties) {
1317   HandleScope scope(isolate);
1318   DCHECK(args.length() == 2);
1319   CONVERT_ARG_HANDLE_CHECKED(Object, o, 0);
1320   CONVERT_ARG_HANDLE_CHECKED(Object, properties, 1);
1321   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1322       isolate, o, JSReceiver::DefineProperties(isolate, o, properties));
1323   return *o;
1324 }
1325 
1326 }  // namespace internal
1327 }  // namespace v8
1328