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