[es6] Implement spec compliant ToName (actually ToPropertyKey).
[platform/upstream/v8.git] / src / runtime / runtime-object.cc
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/messages.h"
11 #include "src/runtime/runtime.h"
12
13 namespace v8 {
14 namespace internal {
15
16
17 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
18                                                Handle<Object> object,
19                                                Handle<Object> key,
20                                                LanguageMode language_mode) {
21   if (object->IsUndefined() || object->IsNull()) {
22     THROW_NEW_ERROR(
23         isolate,
24         NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
25         Object);
26   }
27
28   // Check if the given key is an array index.
29   uint32_t index = 0;
30   if (key->ToArrayIndex(&index)) {
31     return Object::GetElement(isolate, object, index, language_mode);
32   }
33
34   // Convert the key to a name - possibly by calling back into JavaScript.
35   Handle<Name> name;
36   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
37                              Object);
38
39   // Check if the name is trivially convertible to an index and get
40   // the element if so.
41   // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and
42   // remove the special casing here.
43   if (name->AsArrayIndex(&index)) {
44     return Object::GetElement(isolate, object, index);
45   } else {
46     return Object::GetProperty(object, name, language_mode);
47   }
48 }
49
50
51 MaybeHandle<Object> Runtime::KeyedGetObjectProperty(
52     Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
53     LanguageMode language_mode) {
54   // Fast cases for getting named properties of the receiver JSObject
55   // itself.
56   //
57   // The global proxy objects has to be excluded since LookupOwn on
58   // the global proxy object can return a valid result even though the
59   // global proxy object never has properties.  This is the case
60   // because the global proxy object forwards everything to its hidden
61   // prototype including own lookups.
62   //
63   // Additionally, we need to make sure that we do not cache results
64   // for objects that require access checks.
65   if (receiver_obj->IsJSObject()) {
66     if (!receiver_obj->IsJSGlobalProxy() &&
67         !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
68       DisallowHeapAllocation no_allocation;
69       Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
70       Handle<Name> key = Handle<Name>::cast(key_obj);
71       if (receiver->IsGlobalObject()) {
72         // Attempt dictionary lookup.
73         GlobalDictionary* dictionary = receiver->global_dictionary();
74         int entry = dictionary->FindEntry(key);
75         if (entry != GlobalDictionary::kNotFound) {
76           DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
77           PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
78           if (cell->property_details().type() == DATA) {
79             Object* value = cell->value();
80             if (!value->IsTheHole()) return Handle<Object>(value, isolate);
81             // If value is the hole (meaning, absent) do the general lookup.
82           }
83         }
84       } else if (!receiver->HasFastProperties()) {
85         // Attempt dictionary lookup.
86         NameDictionary* dictionary = receiver->property_dictionary();
87         int entry = dictionary->FindEntry(key);
88         if ((entry != NameDictionary::kNotFound) &&
89             (dictionary->DetailsAt(entry).type() == DATA)) {
90           Object* value = dictionary->ValueAt(entry);
91           return Handle<Object>(value, isolate);
92         }
93       }
94     } else if (key_obj->IsSmi()) {
95       // JSObject without a name key. If the key is a Smi, check for a
96       // definite out-of-bounds access to elements, which is a strong indicator
97       // that subsequent accesses will also call the runtime. Proactively
98       // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
99       // doubles for those future calls in the case that the elements would
100       // become FAST_DOUBLE_ELEMENTS.
101       Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
102       ElementsKind elements_kind = js_object->GetElementsKind();
103       if (IsFastDoubleElementsKind(elements_kind)) {
104         if (Smi::cast(*key_obj)->value() >= js_object->elements()->length()) {
105           elements_kind = IsFastHoleyElementsKind(elements_kind)
106                               ? FAST_HOLEY_ELEMENTS
107                               : FAST_ELEMENTS;
108           JSObject::TransitionElementsKind(js_object, elements_kind);
109         }
110       } else {
111         DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
112                !IsFastElementsKind(elements_kind));
113       }
114     }
115   } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
116     // Fast case for string indexing using [] with a smi index.
117     Handle<String> str = Handle<String>::cast(receiver_obj);
118     int index = Handle<Smi>::cast(key_obj)->value();
119     if (index >= 0 && index < str->length()) {
120       Factory* factory = isolate->factory();
121       return factory->LookupSingleCharacterStringFromCode(
122           String::Flatten(str)->Get(index));
123     }
124   }
125
126   // Fall back to GetObjectProperty.
127   return GetObjectProperty(isolate, receiver_obj, key_obj, language_mode);
128 }
129
130
131 MaybeHandle<Object> Runtime::DeleteObjectProperty(Isolate* isolate,
132                                                   Handle<JSReceiver> receiver,
133                                                   Handle<Object> key,
134                                                   LanguageMode language_mode) {
135   // Check if the given key is an array index.
136   uint32_t index = 0;
137   if (key->ToArrayIndex(&index)) {
138     return JSReceiver::DeleteElement(receiver, index, language_mode);
139   }
140
141   Handle<Name> name;
142   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
143                              Object);
144
145   return JSReceiver::DeletePropertyOrElement(receiver, name, language_mode);
146 }
147
148
149 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
150                                                Handle<Object> object,
151                                                Handle<Object> key,
152                                                Handle<Object> value,
153                                                LanguageMode language_mode) {
154   if (object->IsUndefined() || object->IsNull()) {
155     THROW_NEW_ERROR(
156         isolate,
157         NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
158         Object);
159   }
160
161   // Check if the given key is an array index.
162   uint32_t index = 0;
163   if (key->ToArrayIndex(&index)) {
164     return Object::SetElement(isolate, object, index, value, language_mode);
165   }
166
167   Handle<Name> name;
168   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
169                              Object);
170
171   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
172   return Object::SetProperty(&it, value, language_mode,
173                              Object::MAY_BE_STORE_FROM_KEYED);
174 }
175
176
177 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate,
178                                           Handle<Object> obj) {
179   // We don't expect access checks to be needed on JSProxy objects.
180   DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
181   PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
182   do {
183     if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() &&
184         !isolate->MayAccess(
185             Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)))) {
186       return isolate->factory()->null_value();
187     }
188     iter.AdvanceIgnoringProxies();
189     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
190       return PrototypeIterator::GetCurrent(iter);
191     }
192   } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
193   return PrototypeIterator::GetCurrent(iter);
194 }
195
196
197 RUNTIME_FUNCTION(Runtime_GetPrototype) {
198   HandleScope scope(isolate);
199   DCHECK(args.length() == 1);
200   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
201   Handle<Object> result;
202   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
203                                      Runtime::GetPrototype(isolate, obj));
204   return *result;
205 }
206
207
208 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
209   HandleScope scope(isolate);
210   DCHECK(args.length() == 2);
211   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
212   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
213   DCHECK(!obj->IsAccessCheckNeeded());
214   DCHECK(!obj->map()->is_observed());
215   Handle<Object> result;
216   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
217       isolate, result, JSObject::SetPrototype(obj, prototype, false));
218   return *result;
219 }
220
221
222 RUNTIME_FUNCTION(Runtime_SetPrototype) {
223   HandleScope scope(isolate);
224   DCHECK(args.length() == 2);
225   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
226   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
227   if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) {
228     isolate->ReportFailedAccessCheck(obj);
229     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
230     return isolate->heap()->undefined_value();
231   }
232   if (obj->map()->is_observed()) {
233     Handle<Object> old_value =
234         Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
235     Handle<Object> result;
236     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
237         isolate, result, JSObject::SetPrototype(obj, prototype, true));
238
239     Handle<Object> new_value =
240         Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
241     if (!new_value->SameValue(*old_value)) {
242       RETURN_FAILURE_ON_EXCEPTION(
243           isolate, JSObject::EnqueueChangeRecord(
244                        obj, "setPrototype", isolate->factory()->proto_string(),
245                        old_value));
246     }
247     return *result;
248   }
249   Handle<Object> result;
250   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
251       isolate, result, JSObject::SetPrototype(obj, prototype, true));
252   return *result;
253 }
254
255
256 // Enumerator used as indices into the array returned from GetOwnProperty
257 enum PropertyDescriptorIndices {
258   IS_ACCESSOR_INDEX,
259   VALUE_INDEX,
260   GETTER_INDEX,
261   SETTER_INDEX,
262   WRITABLE_INDEX,
263   ENUMERABLE_INDEX,
264   CONFIGURABLE_INDEX,
265   DESCRIPTOR_SIZE
266 };
267
268
269 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
270                                                           Handle<JSObject> obj,
271                                                           Handle<Name> name) {
272   Heap* heap = isolate->heap();
273   Factory* factory = isolate->factory();
274
275   PropertyAttributes attrs;
276   // Get attributes.
277   LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name,
278                                                         LookupIterator::HIDDEN);
279   Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
280
281   if (!maybe.IsJust()) return MaybeHandle<Object>();
282   attrs = maybe.FromJust();
283   if (attrs == ABSENT) return factory->undefined_value();
284
285   DCHECK(!isolate->has_pending_exception());
286   Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
287   elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
288   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
289
290   bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
291                           it.GetAccessors()->IsAccessorPair();
292   elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
293
294   if (is_accessor_pair) {
295     Handle<AccessorPair> accessors =
296         Handle<AccessorPair>::cast(it.GetAccessors());
297     Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
298     Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
299     elms->set(GETTER_INDEX, *getter);
300     elms->set(SETTER_INDEX, *setter);
301   } else {
302     Handle<Object> value;
303     ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
304                                Object);
305     elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
306     elms->set(VALUE_INDEX, *value);
307   }
308
309   return factory->NewJSArrayWithElements(elms);
310 }
311
312
313 // Returns an array with the property description:
314 //  if args[1] is not a property on args[0]
315 //          returns undefined
316 //  if args[1] is a data property on args[0]
317 //         [false, value, Writeable, Enumerable, Configurable]
318 //  if args[1] is an accessor on args[0]
319 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
320 RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
321   HandleScope scope(isolate);
322   DCHECK(args.length() == 2);
323   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
324   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
325   Handle<Object> result;
326   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
327                                      GetOwnProperty(isolate, obj, name));
328   return *result;
329 }
330
331
332 RUNTIME_FUNCTION(Runtime_PreventExtensions) {
333   HandleScope scope(isolate);
334   DCHECK(args.length() == 1);
335   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
336   Handle<Object> result;
337   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
338                                      JSObject::PreventExtensions(obj));
339   return *result;
340 }
341
342
343 RUNTIME_FUNCTION(Runtime_IsExtensible) {
344   SealHandleScope shs(isolate);
345   DCHECK(args.length() == 1);
346   CONVERT_ARG_CHECKED(JSObject, obj, 0);
347   return isolate->heap()->ToBoolean(obj->IsExtensible());
348 }
349
350
351 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
352   HandleScope scope(isolate);
353   DCHECK(args.length() == 2);
354   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
355   CONVERT_SMI_ARG_CHECKED(properties, 1);
356   // Conservative upper limit to prevent fuzz tests from going OOM.
357   RUNTIME_ASSERT(properties <= 100000);
358   if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
359     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
360                                   "OptimizeForAdding");
361   }
362   return *object;
363 }
364
365
366 RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
367   HandleScope scope(isolate);
368   DCHECK(args.length() == 1);
369   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
370
371   // %ObjectFreeze is a fast path and these cases are handled elsewhere.
372   RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
373                  !object->map()->is_observed() && !object->IsJSProxy());
374
375   Handle<Object> result;
376   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object));
377   return *result;
378 }
379
380
381 RUNTIME_FUNCTION(Runtime_ObjectSeal) {
382   HandleScope scope(isolate);
383   DCHECK(args.length() == 1);
384   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
385
386   // %ObjectSeal is a fast path and these cases are handled elsewhere.
387   RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
388                  !object->map()->is_observed() && !object->IsJSProxy());
389
390   Handle<Object> result;
391   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object));
392   return *result;
393 }
394
395
396 RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) {
397   HandleScope scope(isolate);
398   DCHECK_EQ(1, args.length());
399   CONVERT_SMI_ARG_CHECKED(slot, 0);
400
401   // Go up context chain to the script context.
402   Handle<Context> script_context(isolate->context()->script_context(), isolate);
403   DCHECK(script_context->IsScriptContext());
404   DCHECK(script_context->get(slot)->IsPropertyCell());
405
406   // Lookup the named property on the global object.
407   Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate);
408   Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
409   Handle<GlobalObject> global_object(script_context->global_object(), isolate);
410   LookupIterator it(global_object, name, LookupIterator::HIDDEN);
411
412   // Switch to fast mode only if there is a data property and it's not on
413   // a hidden prototype.
414   if (it.state() == LookupIterator::DATA &&
415       it.GetHolder<Object>().is_identical_to(global_object)) {
416     // Now update the cell in the script context.
417     Handle<PropertyCell> cell = it.GetPropertyCell();
418     script_context->set(slot, *cell);
419   } else {
420     // This is not a fast case, so keep this access in a slow mode.
421     // Store empty_property_cell here to release the outdated property cell.
422     script_context->set(slot, isolate->heap()->empty_property_cell());
423   }
424
425   Handle<Object> result;
426   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
427   return *result;
428 }
429
430
431 namespace {
432
433 Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value,
434                               LanguageMode language_mode) {
435   // Go up context chain to the script context.
436   Handle<Context> script_context(isolate->context()->script_context(), isolate);
437   DCHECK(script_context->IsScriptContext());
438   DCHECK(script_context->get(slot)->IsPropertyCell());
439
440   // Lookup the named property on the global object.
441   Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate);
442   Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
443   Handle<GlobalObject> global_object(script_context->global_object(), isolate);
444   LookupIterator it(global_object, name, LookupIterator::HIDDEN);
445
446   // Switch to fast mode only if there is a data property and it's not on
447   // a hidden prototype.
448   if (it.state() == LookupIterator::DATA &&
449       it.GetHolder<Object>().is_identical_to(global_object)) {
450     // Now update cell in the script context.
451     Handle<PropertyCell> cell = it.GetPropertyCell();
452     script_context->set(slot, *cell);
453   } else {
454     // This is not a fast case, so keep this access in a slow mode.
455     // Store empty_property_cell here to release the outdated property cell.
456     script_context->set(slot, isolate->heap()->empty_property_cell());
457   }
458
459   Handle<Object> result;
460   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
461       isolate, result,
462       Object::SetProperty(&it, value, language_mode,
463                           Object::CERTAINLY_NOT_STORE_FROM_KEYED));
464   return *result;
465 }
466
467 }  // namespace
468
469
470 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Sloppy) {
471   HandleScope scope(isolate);
472   DCHECK_EQ(2, args.length());
473   CONVERT_SMI_ARG_CHECKED(slot, 0);
474   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
475
476   return StoreGlobalViaContext(isolate, slot, value, SLOPPY);
477 }
478
479
480 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Strict) {
481   HandleScope scope(isolate);
482   DCHECK_EQ(2, args.length());
483   CONVERT_SMI_ARG_CHECKED(slot, 0);
484   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
485
486   return StoreGlobalViaContext(isolate, slot, value, STRICT);
487 }
488
489
490 RUNTIME_FUNCTION(Runtime_GetProperty) {
491   HandleScope scope(isolate);
492   DCHECK(args.length() == 2);
493
494   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
495   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
496
497   Handle<Object> result;
498   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
499       isolate, result,
500       Runtime::GetObjectProperty(isolate, object, key, SLOPPY));
501   return *result;
502 }
503
504
505 RUNTIME_FUNCTION(Runtime_GetPropertyStrong) {
506   HandleScope scope(isolate);
507   DCHECK(args.length() == 2);
508
509   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
510   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
511
512   Handle<Object> result;
513   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
514       isolate, result,
515       Runtime::GetObjectProperty(isolate, object, key, STRONG));
516   return *result;
517 }
518
519
520 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
521 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
522   HandleScope scope(isolate);
523   DCHECK(args.length() == 2);
524
525   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
526   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
527
528   Handle<Object> result;
529   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
530       isolate, result,
531       Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, SLOPPY));
532   return *result;
533 }
534
535
536 RUNTIME_FUNCTION(Runtime_KeyedGetPropertyStrong) {
537   HandleScope scope(isolate);
538   DCHECK(args.length() == 2);
539
540   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
541   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
542
543   Handle<Object> result;
544   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
545       isolate, result,
546       Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, STRONG));
547   return *result;
548 }
549
550
551 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
552   HandleScope scope(isolate);
553   RUNTIME_ASSERT(args.length() == 4);
554
555   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
556   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
557   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
558   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
559
560 #ifdef DEBUG
561   uint32_t index = 0;
562   DCHECK(!name->ToArrayIndex(&index));
563   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
564   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
565   if (!maybe.IsJust()) return isolate->heap()->exception();
566   RUNTIME_ASSERT(!it.IsFound());
567 #endif
568
569   Handle<Object> result;
570   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
571       isolate, result,
572       JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs));
573   return *result;
574 }
575
576
577 // Adds an element to an array.
578 // This is used to create an indexed data property into an array.
579 RUNTIME_FUNCTION(Runtime_AddElement) {
580   HandleScope scope(isolate);
581   RUNTIME_ASSERT(args.length() == 3);
582
583   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
584   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
585   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
586
587   uint32_t index = 0;
588   CHECK(key->ToArrayIndex(&index));
589
590 #ifdef DEBUG
591   LookupIterator it(isolate, object, index,
592                     LookupIterator::OWN_SKIP_INTERCEPTOR);
593   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
594   if (!maybe.IsJust()) return isolate->heap()->exception();
595   RUNTIME_ASSERT(!it.IsFound());
596
597   if (object->IsJSArray()) {
598     Handle<JSArray> array = Handle<JSArray>::cast(object);
599     RUNTIME_ASSERT(!JSArray::WouldChangeReadOnlyLength(array, index));
600   }
601 #endif
602
603   Handle<Object> result;
604   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
605       isolate, result,
606       JSObject::SetOwnElementIgnoreAttributes(object, index, value, NONE));
607   return *result;
608 }
609
610
611 RUNTIME_FUNCTION(Runtime_AppendElement) {
612   HandleScope scope(isolate);
613   RUNTIME_ASSERT(args.length() == 2);
614
615   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
616   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
617
618   uint32_t index;
619   CHECK(array->length()->ToArrayIndex(&index));
620
621   Handle<Object> result;
622   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
623       isolate, result, JSObject::AddDataElement(array, index, value, NONE));
624   JSObject::ValidateElements(array);
625   return *array;
626 }
627
628
629 RUNTIME_FUNCTION(Runtime_SetProperty) {
630   HandleScope scope(isolate);
631   RUNTIME_ASSERT(args.length() == 4);
632
633   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
634   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
635   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
636   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
637   LanguageMode language_mode = language_mode_arg;
638
639   Handle<Object> result;
640   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
641       isolate, result,
642       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
643   return *result;
644 }
645
646
647 namespace {
648
649 // ES6 section 12.5.4.
650 Object* DeleteProperty(Isolate* isolate, Handle<Object> object,
651                        Handle<Object> key, LanguageMode language_mode) {
652   Handle<JSReceiver> receiver;
653   if (!JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
654     THROW_NEW_ERROR_RETURN_FAILURE(
655         isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
656   }
657   Handle<Object> result;
658   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
659       isolate, result,
660       Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode));
661   return *result;
662 }
663
664 }  // namespace
665
666
667 RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy) {
668   HandleScope scope(isolate);
669   DCHECK_EQ(2, args.length());
670   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
671   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
672   return DeleteProperty(isolate, object, key, SLOPPY);
673 }
674
675
676 RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict) {
677   HandleScope scope(isolate);
678   DCHECK_EQ(2, args.length());
679   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
680   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
681   return DeleteProperty(isolate, object, key, STRICT);
682 }
683
684
685 static Object* HasOwnPropertyImplementation(Isolate* isolate,
686                                             Handle<JSObject> object,
687                                             Handle<Name> key) {
688   Maybe<bool> maybe = JSReceiver::HasOwnProperty(object, key);
689   if (!maybe.IsJust()) return isolate->heap()->exception();
690   if (maybe.FromJust()) return isolate->heap()->true_value();
691   // Handle hidden prototypes.  If there's a hidden prototype above this thing
692   // then we have to check it for properties, because they are supposed to
693   // look like they are on this object.
694   PrototypeIterator iter(isolate, object);
695   if (!iter.IsAtEnd() &&
696       Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))
697           ->map()
698           ->is_hidden_prototype()) {
699     // TODO(verwaest): The recursion is not necessary for keys that are array
700     // indices. Removing this.
701     return HasOwnPropertyImplementation(
702         isolate, Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
703         key);
704   }
705   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
706   return isolate->heap()->false_value();
707 }
708
709
710 RUNTIME_FUNCTION(Runtime_HasOwnProperty) {
711   HandleScope scope(isolate);
712   DCHECK(args.length() == 2);
713   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0)
714   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
715
716   uint32_t index;
717   const bool key_is_array_index = key->AsArrayIndex(&index);
718
719   // Only JS objects can have properties.
720   if (object->IsJSObject()) {
721     Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
722     // Fast case: either the key is a real named property or it is not
723     // an array index and there are no interceptors or hidden
724     // prototypes.
725     Maybe<bool> maybe = Nothing<bool>();
726     if (key_is_array_index) {
727       maybe = JSObject::HasOwnElement(js_obj, index);
728     } else {
729       maybe = JSObject::HasRealNamedProperty(js_obj, key);
730     }
731     if (!maybe.IsJust()) return isolate->heap()->exception();
732     DCHECK(!isolate->has_pending_exception());
733     if (maybe.FromJust()) {
734       return isolate->heap()->true_value();
735     }
736     Map* map = js_obj->map();
737     if (!key_is_array_index && !map->has_named_interceptor() &&
738         !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
739       return isolate->heap()->false_value();
740     }
741     // Slow case.
742     return HasOwnPropertyImplementation(isolate, Handle<JSObject>(js_obj),
743                                         Handle<Name>(key));
744   } else if (object->IsString() && key_is_array_index) {
745     // Well, there is one exception:  Handle [] on strings.
746     Handle<String> string = Handle<String>::cast(object);
747     if (index < static_cast<uint32_t>(string->length())) {
748       return isolate->heap()->true_value();
749     }
750   }
751   return isolate->heap()->false_value();
752 }
753
754
755 RUNTIME_FUNCTION(Runtime_HasProperty) {
756   HandleScope scope(isolate);
757   DCHECK(args.length() == 2);
758   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
759   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
760
761   Handle<Name> name;
762   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
763                                      Object::ToName(isolate, key));
764   Maybe<bool> maybe = JSReceiver::HasProperty(receiver, name);
765   if (!maybe.IsJust()) return isolate->heap()->exception();
766   return isolate->heap()->ToBoolean(maybe.FromJust());
767 }
768
769
770 RUNTIME_FUNCTION(Runtime_HasElement) {
771   HandleScope scope(isolate);
772   DCHECK(args.length() == 2);
773   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
774   CONVERT_SMI_ARG_CHECKED(index, 1);
775
776   Maybe<bool> maybe = JSReceiver::HasElement(receiver, index);
777   if (!maybe.IsJust()) return isolate->heap()->exception();
778   return isolate->heap()->ToBoolean(maybe.FromJust());
779 }
780
781
782 RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) {
783   HandleScope scope(isolate);
784   DCHECK(args.length() == 2);
785
786   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
787   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
788
789   Maybe<PropertyAttributes> maybe =
790       JSReceiver::GetOwnPropertyAttributes(object, key);
791   if (!maybe.IsJust()) return isolate->heap()->exception();
792   if (maybe.FromJust() == ABSENT) maybe = Just(DONT_ENUM);
793   return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
794 }
795
796
797 // Returns either a FixedArray or, if the given object has an enum cache that
798 // contains all enumerable properties of the object and its prototypes have
799 // none, the map of the object. This is used to speed up the check for
800 // deletions during a for-in.
801 RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
802   SealHandleScope shs(isolate);
803   DCHECK(args.length() == 1);
804
805   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
806
807   if (raw_object->IsSimpleEnum()) return raw_object->map();
808
809   HandleScope scope(isolate);
810   Handle<JSReceiver> object(raw_object);
811   Handle<FixedArray> content;
812   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
813       isolate, content,
814       JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
815
816   // Test again, since cache may have been built by preceding call.
817   if (object->IsSimpleEnum()) return object->map();
818
819   return *content;
820 }
821
822
823 // Return the names of the own named properties.
824 // args[0]: object
825 // args[1]: PropertyAttributes as int
826 RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
827   HandleScope scope(isolate);
828   DCHECK(args.length() == 2);
829   if (!args[0]->IsJSObject()) {
830     return isolate->heap()->undefined_value();
831   }
832   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
833   CONVERT_SMI_ARG_CHECKED(filter_value, 1);
834   PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
835
836   // Find the number of own properties for each of the objects.
837   int total_property_count = 0;
838   for (PrototypeIterator iter(isolate, object,
839                               PrototypeIterator::START_AT_RECEIVER);
840        !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
841     Handle<JSObject> jsproto =
842         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
843     total_property_count += jsproto->NumberOfOwnProperties(filter);
844   }
845
846   // Allocate an array with storage for all the property names.
847   Handle<FixedArray> names =
848       isolate->factory()->NewFixedArray(total_property_count);
849
850   // Get the property names.
851   int next_copy_index = 0;
852   int hidden_strings = 0;
853   Handle<Object> hidden_string = isolate->factory()->hidden_string();
854   for (PrototypeIterator iter(isolate, object,
855                               PrototypeIterator::START_AT_RECEIVER);
856        !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
857     Handle<JSObject> jsproto =
858         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
859     int own = jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
860     // Names from hidden prototypes may already have been added
861     // for inherited function template instances. Count the duplicates
862     // and stub them out; the final copy pass at the end ignores holes.
863     for (int j = next_copy_index; j < next_copy_index + own; j++) {
864       Object* name_from_hidden_proto = names->get(j);
865       if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) {
866         hidden_strings++;
867       } else {
868         for (int k = 0; k < next_copy_index; k++) {
869           Object* name = names->get(k);
870           if (name_from_hidden_proto == name) {
871             names->set(j, *hidden_string);
872             hidden_strings++;
873             break;
874           }
875         }
876       }
877     }
878     next_copy_index += own;
879   }
880
881   CHECK_EQ(total_property_count, next_copy_index);
882
883   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
884     for (int i = 0; i < total_property_count; i++) {
885       Handle<Name> name(Name::cast(names->get(i)));
886       if (name.is_identical_to(hidden_string)) continue;
887       LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
888       if (!JSObject::AllCanRead(&it)) {
889         names->set(i, *hidden_string);
890         hidden_strings++;
891       }
892     }
893   }
894
895   // Filter out name of hidden properties object and
896   // hidden prototype duplicates.
897   if (hidden_strings > 0) {
898     if (hidden_strings == total_property_count) {
899       names = isolate->factory()->empty_fixed_array();
900     } else {
901       int i;
902       for (i = 0; i < total_property_count; i++) {
903         Object* name = names->get(i);
904         if (name == *hidden_string) break;
905       }
906       int dest_pos = i;
907       for (; i < total_property_count; i++) {
908         Object* name = names->get(i);
909         if (name == *hidden_string) continue;
910         names->set(dest_pos++, name);
911       }
912
913       isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
914           *names, hidden_strings);
915     }
916   }
917
918   return *isolate->factory()->NewJSArrayWithElements(names);
919 }
920
921
922 // Return the names of the own indexed properties.
923 // args[0]: object
924 RUNTIME_FUNCTION(Runtime_GetOwnElementNames) {
925   HandleScope scope(isolate);
926   DCHECK(args.length() == 1);
927   if (!args[0]->IsJSObject()) {
928     return isolate->heap()->undefined_value();
929   }
930   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
931
932   int n = obj->NumberOfOwnElements(NONE);
933   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
934   obj->GetOwnElementKeys(*names, NONE);
935   return *isolate->factory()->NewJSArrayWithElements(names);
936 }
937
938
939 // Return information on whether an object has a named or indexed interceptor.
940 // args[0]: object
941 RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
942   HandleScope scope(isolate);
943   DCHECK(args.length() == 1);
944   if (!args[0]->IsJSObject()) {
945     return Smi::FromInt(0);
946   }
947   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
948
949   int result = 0;
950   if (obj->HasNamedInterceptor()) result |= 2;
951   if (obj->HasIndexedInterceptor()) result |= 1;
952
953   return Smi::FromInt(result);
954 }
955
956
957 // Return property names from named interceptor.
958 // args[0]: object
959 RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames) {
960   HandleScope scope(isolate);
961   DCHECK(args.length() == 1);
962   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
963
964   if (obj->HasNamedInterceptor()) {
965     Handle<JSObject> result;
966     if (JSObject::GetKeysForNamedInterceptor(obj, obj).ToHandle(&result)) {
967       return *result;
968     }
969   }
970   return isolate->heap()->undefined_value();
971 }
972
973
974 // Return element names from indexed interceptor.
975 // args[0]: object
976 RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames) {
977   HandleScope scope(isolate);
978   DCHECK(args.length() == 1);
979   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
980
981   if (obj->HasIndexedInterceptor()) {
982     Handle<JSObject> result;
983     if (JSObject::GetKeysForIndexedInterceptor(obj, obj).ToHandle(&result)) {
984       return *result;
985     }
986   }
987   return isolate->heap()->undefined_value();
988 }
989
990
991 RUNTIME_FUNCTION(Runtime_OwnKeys) {
992   HandleScope scope(isolate);
993   DCHECK(args.length() == 1);
994   CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
995   Handle<JSObject> object(raw_object);
996
997   Handle<FixedArray> contents;
998   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
999       isolate, contents, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY));
1000
1001   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
1002   // property array and since the result is mutable we have to create
1003   // a fresh clone on each invocation.
1004   int length = contents->length();
1005   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
1006   for (int i = 0; i < length; i++) {
1007     Object* entry = contents->get(i);
1008     if (entry->IsString()) {
1009       copy->set(i, entry);
1010     } else {
1011       DCHECK(entry->IsNumber());
1012       HandleScope scope(isolate);
1013       Handle<Object> entry_handle(entry, isolate);
1014       Handle<Object> entry_str =
1015           isolate->factory()->NumberToString(entry_handle);
1016       copy->set(i, *entry_str);
1017     }
1018   }
1019   return *isolate->factory()->NewJSArrayWithElements(copy);
1020 }
1021
1022
1023 RUNTIME_FUNCTION(Runtime_ToFastProperties) {
1024   HandleScope scope(isolate);
1025   DCHECK(args.length() == 1);
1026   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1027   if (object->IsJSObject() && !object->IsGlobalObject()) {
1028     JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
1029                                 "RuntimeToFastProperties");
1030   }
1031   return *object;
1032 }
1033
1034
1035 RUNTIME_FUNCTION(Runtime_NewStringWrapper) {
1036   HandleScope scope(isolate);
1037   DCHECK(args.length() == 1);
1038   CONVERT_ARG_HANDLE_CHECKED(String, value, 0);
1039   return *Object::ToObject(isolate, value).ToHandleChecked();
1040 }
1041
1042
1043 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
1044   HandleScope scope(isolate);
1045   DCHECK(args.length() == 0);
1046   return *isolate->factory()->NewHeapNumber(0);
1047 }
1048
1049
1050 static Object* Runtime_NewObjectHelper(Isolate* isolate,
1051                                        Handle<Object> constructor,
1052                                        Handle<Object> original_constructor,
1053                                        Handle<AllocationSite> site) {
1054   // If the constructor isn't a proper function we throw a type error.
1055   if (!constructor->IsJSFunction()) {
1056     THROW_NEW_ERROR_RETURN_FAILURE(
1057         isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor));
1058   }
1059
1060   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
1061
1062   CHECK(original_constructor->IsJSFunction());
1063   Handle<JSFunction> original_function =
1064       Handle<JSFunction>::cast(original_constructor);
1065
1066
1067   // If function should not have prototype, construction is not allowed. In this
1068   // case generated code bailouts here, since function has no initial_map.
1069   if (!function->should_have_prototype() && !function->shared()->bound()) {
1070     THROW_NEW_ERROR_RETURN_FAILURE(
1071         isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor));
1072   }
1073
1074   Debug* debug = isolate->debug();
1075   // Handle stepping into constructors if step into is active.
1076   if (debug->StepInActive()) debug->HandleStepIn(function, true);
1077
1078   if (function->has_initial_map()) {
1079     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
1080       // The 'Function' function ignores the receiver object when
1081       // called using 'new' and creates a new JSFunction object that
1082       // is returned.  The receiver object is only used for error
1083       // reporting if an error occurs when constructing the new
1084       // JSFunction. Factory::NewJSObject() should not be used to
1085       // allocate JSFunctions since it does not properly initialize
1086       // the shared part of the function. Since the receiver is
1087       // ignored anyway, we use the global object as the receiver
1088       // instead of a new JSFunction object. This way, errors are
1089       // reported the same way whether or not 'Function' is called
1090       // using 'new'.
1091       return isolate->global_proxy();
1092     }
1093   }
1094
1095   // The function should be compiled for the optimization hints to be
1096   // available.
1097   Compiler::Compile(function, CLEAR_EXCEPTION);
1098
1099   Handle<JSObject> result;
1100   if (site.is_null()) {
1101     result = isolate->factory()->NewJSObject(function);
1102   } else {
1103     result = isolate->factory()->NewJSObjectWithMemento(function, site);
1104   }
1105
1106   // Set up the prototoype using original function.
1107   // TODO(dslomov): instead of setting the __proto__,
1108   // use and cache the correct map.
1109   if (*original_function != *function) {
1110     if (original_function->has_instance_prototype()) {
1111       Handle<Object> prototype =
1112           handle(original_function->instance_prototype(), isolate);
1113       RETURN_FAILURE_ON_EXCEPTION(
1114           isolate, JSObject::SetPrototype(result, prototype, false));
1115     }
1116   }
1117
1118   isolate->counters()->constructed_objects()->Increment();
1119   isolate->counters()->constructed_objects_runtime()->Increment();
1120
1121   return *result;
1122 }
1123
1124
1125 RUNTIME_FUNCTION(Runtime_NewObject) {
1126   HandleScope scope(isolate);
1127   DCHECK(args.length() == 2);
1128   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
1129   CONVERT_ARG_HANDLE_CHECKED(Object, original_constructor, 1);
1130   return Runtime_NewObjectHelper(isolate, constructor, original_constructor,
1131                                  Handle<AllocationSite>::null());
1132 }
1133
1134
1135 RUNTIME_FUNCTION(Runtime_NewObjectWithAllocationSite) {
1136   HandleScope scope(isolate);
1137   DCHECK(args.length() == 3);
1138   CONVERT_ARG_HANDLE_CHECKED(Object, original_constructor, 2);
1139   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 1);
1140   CONVERT_ARG_HANDLE_CHECKED(Object, feedback, 0);
1141   Handle<AllocationSite> site;
1142   if (feedback->IsAllocationSite()) {
1143     // The feedback can be an AllocationSite or undefined.
1144     site = Handle<AllocationSite>::cast(feedback);
1145   }
1146   return Runtime_NewObjectHelper(isolate, constructor, original_constructor,
1147                                  site);
1148 }
1149
1150
1151 RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) {
1152   HandleScope scope(isolate);
1153   DCHECK(args.length() == 1);
1154
1155   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1156   function->CompleteInobjectSlackTracking();
1157
1158   return isolate->heap()->undefined_value();
1159 }
1160
1161
1162 RUNTIME_FUNCTION(Runtime_GlobalProxy) {
1163   SealHandleScope shs(isolate);
1164   DCHECK(args.length() == 1);
1165   CONVERT_ARG_CHECKED(JSFunction, function, 0);
1166   return function->context()->global_proxy();
1167 }
1168
1169
1170 RUNTIME_FUNCTION(Runtime_LookupAccessor) {
1171   HandleScope scope(isolate);
1172   DCHECK(args.length() == 3);
1173   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
1174   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1175   CONVERT_SMI_ARG_CHECKED(flag, 2);
1176   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
1177   if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
1178   Handle<Object> result;
1179   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1180       isolate, result,
1181       JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
1182   return *result;
1183 }
1184
1185
1186 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
1187   HandleScope scope(isolate);
1188   DCHECK(args.length() == 2);
1189   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1190   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
1191   RUNTIME_ASSERT((index->value() & 1) == 1);
1192   FieldIndex field_index =
1193       FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
1194   if (field_index.is_inobject()) {
1195     RUNTIME_ASSERT(field_index.property_index() <
1196                    object->map()->GetInObjectProperties());
1197   } else {
1198     RUNTIME_ASSERT(field_index.outobject_array_index() <
1199                    object->properties()->length());
1200   }
1201   return *JSObject::FastPropertyAt(object, Representation::Double(),
1202                                    field_index);
1203 }
1204
1205
1206 RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
1207   HandleScope scope(isolate);
1208   DCHECK(args.length() == 1);
1209   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1210   if (!object->IsJSObject()) return Smi::FromInt(0);
1211   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
1212   if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
1213   // This call must not cause lazy deopts, because it's called from deferred
1214   // code where we can't handle lazy deopts for lack of a suitable bailout
1215   // ID. So we just try migration and signal failure if necessary,
1216   // which will also trigger a deopt.
1217   if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0);
1218   return *object;
1219 }
1220
1221
1222 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
1223   SealHandleScope shs(isolate);
1224   DCHECK(args.length() == 1);
1225   CONVERT_ARG_CHECKED(Object, obj, 0);
1226   return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
1227 }
1228
1229
1230 static bool IsValidAccessor(Handle<Object> obj) {
1231   return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
1232 }
1233
1234
1235 // Implements part of 8.12.9 DefineOwnProperty.
1236 // There are 3 cases that lead here:
1237 // Step 4b - define a new accessor property.
1238 // Steps 9c & 12 - replace an existing data property with an accessor property.
1239 // Step 12 - update an existing accessor property with an accessor or generic
1240 //           descriptor.
1241 RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
1242   HandleScope scope(isolate);
1243   DCHECK(args.length() == 5);
1244   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1245   RUNTIME_ASSERT(!obj->IsNull());
1246   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1247   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
1248   RUNTIME_ASSERT(IsValidAccessor(getter));
1249   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
1250   RUNTIME_ASSERT(IsValidAccessor(setter));
1251   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
1252
1253   RETURN_FAILURE_ON_EXCEPTION(
1254       isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
1255   return isolate->heap()->undefined_value();
1256 }
1257
1258
1259 // Implements part of 8.12.9 DefineOwnProperty.
1260 // There are 3 cases that lead here:
1261 // Step 4a - define a new data property.
1262 // Steps 9b & 12 - replace an existing accessor property with a data property.
1263 // Step 12 - update an existing data property with a data or generic
1264 //           descriptor.
1265 RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
1266   HandleScope scope(isolate);
1267   DCHECK(args.length() == 4);
1268   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1269   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1270   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1271   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1272
1273   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
1274                                                         LookupIterator::OWN);
1275   if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) {
1276     return isolate->heap()->undefined_value();
1277   }
1278
1279   Handle<Object> result;
1280   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1281       isolate, result, JSObject::DefineOwnPropertyIgnoreAttributes(
1282                            &it, value, attrs, JSObject::DONT_FORCE_FIELD));
1283
1284   return *result;
1285 }
1286
1287
1288 // Return property without being observable by accessors or interceptors.
1289 RUNTIME_FUNCTION(Runtime_GetDataProperty) {
1290   HandleScope scope(isolate);
1291   DCHECK(args.length() == 2);
1292   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
1293   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1294   return *JSReceiver::GetDataProperty(object, name);
1295 }
1296
1297
1298 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
1299   SealHandleScope shs(isolate);
1300   DCHECK(args.length() == 1);
1301   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
1302   return isolate->heap()->ToBoolean(
1303       IsFastPackedElementsKind(obj->map()->elements_kind()));
1304 }
1305
1306
1307 RUNTIME_FUNCTION(Runtime_ValueOf) {
1308   SealHandleScope shs(isolate);
1309   DCHECK(args.length() == 1);
1310   CONVERT_ARG_CHECKED(Object, obj, 0);
1311   if (!obj->IsJSValue()) return obj;
1312   return JSValue::cast(obj)->value();
1313 }
1314
1315
1316 RUNTIME_FUNCTION(Runtime_SetValueOf) {
1317   SealHandleScope shs(isolate);
1318   DCHECK(args.length() == 2);
1319   CONVERT_ARG_CHECKED(Object, obj, 0);
1320   CONVERT_ARG_CHECKED(Object, value, 1);
1321   if (!obj->IsJSValue()) return value;
1322   JSValue::cast(obj)->set_value(value);
1323   return value;
1324 }
1325
1326
1327 RUNTIME_FUNCTION(Runtime_JSValueGetValue) {
1328   SealHandleScope shs(isolate);
1329   DCHECK(args.length() == 1);
1330   CONVERT_ARG_CHECKED(JSValue, obj, 0);
1331   return JSValue::cast(obj)->value();
1332 }
1333
1334
1335 RUNTIME_FUNCTION(Runtime_HeapObjectGetMap) {
1336   SealHandleScope shs(isolate);
1337   DCHECK(args.length() == 1);
1338   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
1339   return obj->map();
1340 }
1341
1342
1343 RUNTIME_FUNCTION(Runtime_MapGetInstanceType) {
1344   SealHandleScope shs(isolate);
1345   DCHECK(args.length() == 1);
1346   CONVERT_ARG_CHECKED(Map, map, 0);
1347   return Smi::FromInt(map->instance_type());
1348 }
1349
1350
1351 RUNTIME_FUNCTION(Runtime_ObjectEquals) {
1352   SealHandleScope shs(isolate);
1353   DCHECK(args.length() == 2);
1354   CONVERT_ARG_CHECKED(Object, obj1, 0);
1355   CONVERT_ARG_CHECKED(Object, obj2, 1);
1356   return isolate->heap()->ToBoolean(obj1 == obj2);
1357 }
1358
1359
1360 RUNTIME_FUNCTION(Runtime_IsSpecObject) {
1361   SealHandleScope shs(isolate);
1362   DCHECK(args.length() == 1);
1363   CONVERT_ARG_CHECKED(Object, obj, 0);
1364   return isolate->heap()->ToBoolean(obj->IsSpecObject());
1365 }
1366
1367
1368 RUNTIME_FUNCTION(Runtime_IsStrong) {
1369   SealHandleScope shs(isolate);
1370   DCHECK(args.length() == 1);
1371   CONVERT_ARG_CHECKED(Object, obj, 0);
1372   return isolate->heap()->ToBoolean(obj->IsJSReceiver() &&
1373                                     JSReceiver::cast(obj)->map()->is_strong());
1374 }
1375
1376
1377 RUNTIME_FUNCTION(Runtime_ClassOf) {
1378   SealHandleScope shs(isolate);
1379   DCHECK(args.length() == 1);
1380   CONVERT_ARG_CHECKED(Object, obj, 0);
1381   if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
1382   return JSReceiver::cast(obj)->class_name();
1383 }
1384
1385
1386 RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
1387   HandleScope scope(isolate);
1388   DCHECK(args.length() == 4);
1389   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1390   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1391   CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
1392   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1393
1394   RETURN_FAILURE_ON_EXCEPTION(
1395       isolate,
1396       JSObject::DefineAccessor(object, name, getter,
1397                                isolate->factory()->null_value(), attrs));
1398   return isolate->heap()->undefined_value();
1399 }
1400
1401
1402 RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
1403   HandleScope scope(isolate);
1404   DCHECK(args.length() == 4);
1405   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1406   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1407   CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
1408   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1409
1410   RETURN_FAILURE_ON_EXCEPTION(
1411       isolate,
1412       JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1413                                setter, attrs));
1414   return isolate->heap()->undefined_value();
1415 }
1416
1417
1418 RUNTIME_FUNCTION(Runtime_ToObject) {
1419   HandleScope scope(isolate);
1420   DCHECK_EQ(1, args.length());
1421   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1422   Handle<JSReceiver> receiver;
1423   if (JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
1424     return *receiver;
1425   }
1426   THROW_NEW_ERROR_RETURN_FAILURE(
1427       isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
1428 }
1429
1430
1431 RUNTIME_FUNCTION(Runtime_ToPrimitive) {
1432   HandleScope scope(isolate);
1433   DCHECK_EQ(1, args.length());
1434   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1435   Handle<Object> result;
1436   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1437                                      Object::ToPrimitive(input));
1438   return *result;
1439 }
1440
1441
1442 RUNTIME_FUNCTION(Runtime_ToPrimitive_Number) {
1443   HandleScope scope(isolate);
1444   DCHECK_EQ(1, args.length());
1445   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1446   Handle<Object> result;
1447   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1448       isolate, result, Object::ToPrimitive(input, ToPrimitiveHint::kNumber));
1449   return *result;
1450 }
1451
1452
1453 RUNTIME_FUNCTION(Runtime_ToPrimitive_String) {
1454   HandleScope scope(isolate);
1455   DCHECK_EQ(1, args.length());
1456   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1457   Handle<Object> result;
1458   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1459       isolate, result, Object::ToPrimitive(input, ToPrimitiveHint::kString));
1460   return *result;
1461 }
1462
1463
1464 RUNTIME_FUNCTION(Runtime_OrdinaryToPrimitive) {
1465   HandleScope scope(isolate);
1466   DCHECK_EQ(2, args.length());
1467   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
1468   CONVERT_ARG_HANDLE_CHECKED(String, hint, 1);
1469   Handle<Object> result;
1470   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1471       isolate, result, JSReceiver::OrdinaryToPrimitive(receiver, hint));
1472   return *result;
1473 }
1474
1475
1476 RUNTIME_FUNCTION(Runtime_ToNumber) {
1477   HandleScope scope(isolate);
1478   DCHECK_EQ(1, args.length());
1479   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1480   Handle<Object> result;
1481   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1482                                      Object::ToNumber(isolate, input));
1483   return *result;
1484 }
1485
1486
1487 RUNTIME_FUNCTION(Runtime_ToName) {
1488   HandleScope scope(isolate);
1489   DCHECK_EQ(1, args.length());
1490   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1491   Handle<Object> result;
1492   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1493                                      Object::ToName(isolate, input));
1494   return *result;
1495 }
1496
1497
1498 RUNTIME_FUNCTION(Runtime_StrictEquals) {
1499   SealHandleScope scope(isolate);
1500   DCHECK_EQ(2, args.length());
1501   CONVERT_ARG_CHECKED(Object, x, 0);
1502   CONVERT_ARG_CHECKED(Object, y, 1);
1503   // TODO(bmeurer): Change this at some point to return true/false instead.
1504   return Smi::FromInt(x->StrictEquals(y) ? EQUAL : NOT_EQUAL);
1505 }
1506
1507
1508 RUNTIME_FUNCTION(Runtime_InstanceOf) {
1509   // ECMA-262, section 11.8.6, page 54.
1510   HandleScope shs(isolate);
1511   DCHECK_EQ(2, args.length());
1512   DCHECK(args.length() == 2);
1513   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1514   CONVERT_ARG_HANDLE_CHECKED(Object, callable, 1);
1515   // {callable} must have a [[Call]] internal method.
1516   if (!callable->IsCallable()) {
1517     THROW_NEW_ERROR_RETURN_FAILURE(
1518         isolate,
1519         NewTypeError(MessageTemplate::kInstanceofFunctionExpected, callable));
1520   }
1521   // If {object} is not a receiver, return false.
1522   if (!object->IsJSReceiver()) {
1523     return isolate->heap()->false_value();
1524   }
1525   // Check if {callable} is bound, if so, get [[BoundFunction]] from it and use
1526   // that instead of {callable}.
1527   if (callable->IsJSFunction()) {
1528     Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
1529     if (function->shared()->bound()) {
1530       Handle<FixedArray> bindings(function->function_bindings(), isolate);
1531       callable =
1532           handle(bindings->get(JSFunction::kBoundFunctionIndex), isolate);
1533     }
1534   }
1535   DCHECK(callable->IsCallable());
1536   // Get the "prototype" of {callable}; raise an error if it's not a receiver.
1537   Handle<Object> prototype;
1538   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1539       isolate, prototype,
1540       Object::GetProperty(callable, isolate->factory()->prototype_string()));
1541   if (!prototype->IsJSReceiver()) {
1542     THROW_NEW_ERROR_RETURN_FAILURE(
1543         isolate,
1544         NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype));
1545   }
1546   // Return whether or not {prototype} is in the prototype chain of {object}.
1547   return isolate->heap()->ToBoolean(
1548       object->HasInPrototypeChain(isolate, *prototype));
1549 }
1550
1551
1552 RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
1553   SealHandleScope scope(isolate);
1554   DCHECK_EQ(2, args.length());
1555   CONVERT_ARG_CHECKED(Object, object, 0);
1556   CONVERT_ARG_CHECKED(Object, prototype, 1);
1557   return isolate->heap()->ToBoolean(
1558       object->HasInPrototypeChain(isolate, prototype));
1559 }
1560
1561 }  // namespace internal
1562 }  // namespace v8