7b937fe3d2eb129b0d3a70546946d16cfdb5cd22
[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/v8.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 #include "src/runtime/runtime-utils.h"
13
14 namespace v8 {
15 namespace internal {
16
17
18 MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) {
19   if (key->IsName()) {
20     return Handle<Name>::cast(key);
21   } else {
22     Handle<Object> converted;
23     ASSIGN_RETURN_ON_EXCEPTION(isolate, converted,
24                                Execution::ToString(isolate, key), Name);
25     return Handle<Name>::cast(converted);
26   }
27 }
28
29
30 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
31                                                Handle<Object> object,
32                                                Handle<Object> key,
33                                                LanguageMode language_mode) {
34   if (object->IsUndefined() || object->IsNull()) {
35     THROW_NEW_ERROR(
36         isolate,
37         NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
38         Object);
39   }
40
41   // Check if the given key is an array index.
42   uint32_t index = 0;
43   if (key->ToArrayIndex(&index)) {
44     return Object::GetElement(isolate, object, index, language_mode);
45   }
46
47   // Convert the key to a name - possibly by calling back into JavaScript.
48   Handle<Name> name;
49   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
50
51   // Check if the name is trivially convertible to an index and get
52   // the element if so.
53   // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and
54   // remove the special casing here.
55   if (name->AsArrayIndex(&index)) {
56     return Object::GetElement(isolate, object, index);
57   } else {
58     return Object::GetProperty(object, name, language_mode);
59   }
60 }
61
62
63 MaybeHandle<Object> Runtime::KeyedGetObjectProperty(
64     Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
65     LanguageMode language_mode) {
66   // Fast cases for getting named properties of the receiver JSObject
67   // itself.
68   //
69   // The global proxy objects has to be excluded since LookupOwn on
70   // the global proxy object can return a valid result even though the
71   // global proxy object never has properties.  This is the case
72   // because the global proxy object forwards everything to its hidden
73   // prototype including own lookups.
74   //
75   // Additionally, we need to make sure that we do not cache results
76   // for objects that require access checks.
77   if (receiver_obj->IsJSObject()) {
78     if (!receiver_obj->IsJSGlobalProxy() &&
79         !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
80       DisallowHeapAllocation no_allocation;
81       Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
82       Handle<Name> key = Handle<Name>::cast(key_obj);
83       if (receiver->IsGlobalObject()) {
84         // Attempt dictionary lookup.
85         GlobalDictionary* dictionary = receiver->global_dictionary();
86         int entry = dictionary->FindEntry(key);
87         if (entry != GlobalDictionary::kNotFound) {
88           DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
89           PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
90           if (cell->property_details().type() == DATA) {
91             Object* value = cell->value();
92             if (!value->IsTheHole()) return Handle<Object>(value, isolate);
93             // If value is the hole (meaning, absent) do the general lookup.
94           }
95         }
96       } else if (!receiver->HasFastProperties()) {
97         // Attempt dictionary lookup.
98         NameDictionary* dictionary = receiver->property_dictionary();
99         int entry = dictionary->FindEntry(key);
100         if ((entry != NameDictionary::kNotFound) &&
101             (dictionary->DetailsAt(entry).type() == DATA)) {
102           Object* value = dictionary->ValueAt(entry);
103           return Handle<Object>(value, isolate);
104         }
105       }
106     } else if (key_obj->IsSmi()) {
107       // JSObject without a name key. If the key is a Smi, check for a
108       // definite out-of-bounds access to elements, which is a strong indicator
109       // that subsequent accesses will also call the runtime. Proactively
110       // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
111       // doubles for those future calls in the case that the elements would
112       // become FAST_DOUBLE_ELEMENTS.
113       Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
114       ElementsKind elements_kind = js_object->GetElementsKind();
115       if (IsFastDoubleElementsKind(elements_kind)) {
116         if (Smi::cast(*key_obj)->value() >= js_object->elements()->length()) {
117           elements_kind = IsFastHoleyElementsKind(elements_kind)
118                               ? FAST_HOLEY_ELEMENTS
119                               : FAST_ELEMENTS;
120           JSObject::TransitionElementsKind(js_object, elements_kind);
121         }
122       } else {
123         DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
124                !IsFastElementsKind(elements_kind));
125       }
126     }
127   } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
128     // Fast case for string indexing using [] with a smi index.
129     Handle<String> str = Handle<String>::cast(receiver_obj);
130     int index = Handle<Smi>::cast(key_obj)->value();
131     if (index >= 0 && index < str->length()) {
132       Factory* factory = isolate->factory();
133       return factory->LookupSingleCharacterStringFromCode(
134           String::Flatten(str)->Get(index));
135     }
136   }
137
138   // Fall back to GetObjectProperty.
139   return GetObjectProperty(isolate, receiver_obj, key_obj, language_mode);
140 }
141
142
143 MaybeHandle<Object> Runtime::DeleteObjectProperty(Isolate* isolate,
144                                                   Handle<JSReceiver> receiver,
145                                                   Handle<Object> key,
146                                                   LanguageMode language_mode) {
147   // Check if the given key is an array index.
148   uint32_t index = 0;
149   if (key->ToArrayIndex(&index)) {
150     return JSReceiver::DeleteElement(receiver, index, language_mode);
151   }
152
153   Handle<Name> name;
154   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
155
156   return JSReceiver::DeletePropertyOrElement(receiver, name, language_mode);
157 }
158
159
160 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
161                                                Handle<Object> object,
162                                                Handle<Object> key,
163                                                Handle<Object> value,
164                                                LanguageMode language_mode) {
165   if (object->IsUndefined() || object->IsNull()) {
166     THROW_NEW_ERROR(
167         isolate,
168         NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
169         Object);
170   }
171
172   // Check if the given key is an array index.
173   uint32_t index = 0;
174   if (key->ToArrayIndex(&index)) {
175     return Object::SetElement(isolate, object, index, value, language_mode);
176   }
177
178   Handle<Name> name;
179   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
180
181   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
182   return Object::SetProperty(&it, value, language_mode,
183                              Object::MAY_BE_STORE_FROM_KEYED);
184 }
185
186
187 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate,
188                                           Handle<Object> obj) {
189   // We don't expect access checks to be needed on JSProxy objects.
190   DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
191   PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
192   do {
193     if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() &&
194         !isolate->MayAccess(
195             Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)))) {
196       return isolate->factory()->null_value();
197     }
198     iter.AdvanceIgnoringProxies();
199     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
200       return PrototypeIterator::GetCurrent(iter);
201     }
202   } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
203   return PrototypeIterator::GetCurrent(iter);
204 }
205
206
207 RUNTIME_FUNCTION(Runtime_GetPrototype) {
208   HandleScope scope(isolate);
209   DCHECK(args.length() == 1);
210   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
211   Handle<Object> result;
212   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
213                                      Runtime::GetPrototype(isolate, obj));
214   return *result;
215 }
216
217
218 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
219   HandleScope scope(isolate);
220   DCHECK(args.length() == 2);
221   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
222   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
223   DCHECK(!obj->IsAccessCheckNeeded());
224   DCHECK(!obj->map()->is_observed());
225   Handle<Object> result;
226   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
227       isolate, result, JSObject::SetPrototype(obj, prototype, false));
228   return *result;
229 }
230
231
232 RUNTIME_FUNCTION(Runtime_SetPrototype) {
233   HandleScope scope(isolate);
234   DCHECK(args.length() == 2);
235   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
236   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
237   if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) {
238     isolate->ReportFailedAccessCheck(obj);
239     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
240     return isolate->heap()->undefined_value();
241   }
242   if (obj->map()->is_observed()) {
243     Handle<Object> old_value =
244         Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
245     Handle<Object> result;
246     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
247         isolate, result, JSObject::SetPrototype(obj, prototype, true));
248
249     Handle<Object> new_value =
250         Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
251     if (!new_value->SameValue(*old_value)) {
252       RETURN_FAILURE_ON_EXCEPTION(
253           isolate, JSObject::EnqueueChangeRecord(
254                        obj, "setPrototype", isolate->factory()->proto_string(),
255                        old_value));
256     }
257     return *result;
258   }
259   Handle<Object> result;
260   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
261       isolate, result, JSObject::SetPrototype(obj, prototype, true));
262   return *result;
263 }
264
265
266 RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
267   HandleScope shs(isolate);
268   DCHECK(args.length() == 2);
269   // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
270   CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
271   CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
272   PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER);
273   while (true) {
274     iter.AdvanceIgnoringProxies();
275     if (iter.IsAtEnd()) return isolate->heap()->false_value();
276     if (iter.IsAtEnd(O)) return isolate->heap()->true_value();
277   }
278 }
279
280
281 // Enumerator used as indices into the array returned from GetOwnProperty
282 enum PropertyDescriptorIndices {
283   IS_ACCESSOR_INDEX,
284   VALUE_INDEX,
285   GETTER_INDEX,
286   SETTER_INDEX,
287   WRITABLE_INDEX,
288   ENUMERABLE_INDEX,
289   CONFIGURABLE_INDEX,
290   DESCRIPTOR_SIZE
291 };
292
293
294 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
295                                                           Handle<JSObject> obj,
296                                                           Handle<Name> name) {
297   Heap* heap = isolate->heap();
298   Factory* factory = isolate->factory();
299
300   PropertyAttributes attrs;
301   // Get attributes.
302   LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name,
303                                                         LookupIterator::HIDDEN);
304   Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
305
306   if (!maybe.IsJust()) return MaybeHandle<Object>();
307   attrs = maybe.FromJust();
308   if (attrs == ABSENT) return factory->undefined_value();
309
310   DCHECK(!isolate->has_pending_exception());
311   Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
312   elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
313   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
314
315   bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
316                           it.GetAccessors()->IsAccessorPair();
317   elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
318
319   if (is_accessor_pair) {
320     Handle<AccessorPair> accessors =
321         Handle<AccessorPair>::cast(it.GetAccessors());
322     Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
323     Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
324     elms->set(GETTER_INDEX, *getter);
325     elms->set(SETTER_INDEX, *setter);
326   } else {
327     Handle<Object> value;
328     ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
329                                Object);
330     elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
331     elms->set(VALUE_INDEX, *value);
332   }
333
334   return factory->NewJSArrayWithElements(elms);
335 }
336
337
338 // Returns an array with the property description:
339 //  if args[1] is not a property on args[0]
340 //          returns undefined
341 //  if args[1] is a data property on args[0]
342 //         [false, value, Writeable, Enumerable, Configurable]
343 //  if args[1] is an accessor on args[0]
344 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
345 RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
346   HandleScope scope(isolate);
347   DCHECK(args.length() == 2);
348   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
349   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
350   Handle<Object> result;
351   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
352                                      GetOwnProperty(isolate, obj, name));
353   return *result;
354 }
355
356
357 RUNTIME_FUNCTION(Runtime_PreventExtensions) {
358   HandleScope scope(isolate);
359   DCHECK(args.length() == 1);
360   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
361   Handle<Object> result;
362   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
363                                      JSObject::PreventExtensions(obj));
364   return *result;
365 }
366
367
368 RUNTIME_FUNCTION(Runtime_IsExtensible) {
369   SealHandleScope shs(isolate);
370   DCHECK(args.length() == 1);
371   CONVERT_ARG_CHECKED(JSObject, obj, 0);
372   return isolate->heap()->ToBoolean(obj->IsExtensible());
373 }
374
375
376 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
377   HandleScope scope(isolate);
378   DCHECK(args.length() == 2);
379   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
380   CONVERT_SMI_ARG_CHECKED(properties, 1);
381   // Conservative upper limit to prevent fuzz tests from going OOM.
382   RUNTIME_ASSERT(properties <= 100000);
383   if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
384     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
385                                   "OptimizeForAdding");
386   }
387   return *object;
388 }
389
390
391 RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
392   HandleScope scope(isolate);
393   DCHECK(args.length() == 1);
394   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
395
396   // %ObjectFreeze is a fast path and these cases are handled elsewhere.
397   RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
398                  !object->map()->is_observed() && !object->IsJSProxy());
399
400   Handle<Object> result;
401   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object));
402   return *result;
403 }
404
405
406 RUNTIME_FUNCTION(Runtime_ObjectSeal) {
407   HandleScope scope(isolate);
408   DCHECK(args.length() == 1);
409   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
410
411   // %ObjectSeal is a fast path and these cases are handled elsewhere.
412   RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
413                  !object->map()->is_observed() && !object->IsJSProxy());
414
415   Handle<Object> result;
416   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object));
417   return *result;
418 }
419
420
421 RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) {
422   HandleScope scope(isolate);
423   DCHECK_EQ(1, args.length());
424   CONVERT_SMI_ARG_CHECKED(slot, 0);
425
426   // Go up context chain to the script context.
427   Handle<Context> script_context(isolate->context()->script_context(), isolate);
428   DCHECK(script_context->IsScriptContext());
429   DCHECK(script_context->get(slot)->IsPropertyCell());
430
431   // Lookup the named property on the global object.
432   Handle<ScopeInfo> scope_info(ScopeInfo::cast(script_context->extension()),
433                                isolate);
434   Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
435   Handle<GlobalObject> global_object(script_context->global_object(), isolate);
436   LookupIterator it(global_object, name, LookupIterator::HIDDEN);
437
438   // Switch to fast mode only if there is a data property and it's not on
439   // a hidden prototype.
440   if (it.state() == LookupIterator::DATA &&
441       it.GetHolder<Object>().is_identical_to(global_object)) {
442     // Now update the cell in the script context.
443     Handle<PropertyCell> cell = it.GetPropertyCell();
444     script_context->set(slot, *cell);
445   } else {
446     // This is not a fast case, so keep this access in a slow mode.
447     // Store empty_property_cell here to release the outdated property cell.
448     script_context->set(slot, isolate->heap()->empty_property_cell());
449   }
450
451   Handle<Object> result;
452   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
453   return *result;
454 }
455
456
457 namespace {
458
459 Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value,
460                               LanguageMode language_mode) {
461   // Go up context chain to the script context.
462   Handle<Context> script_context(isolate->context()->script_context(), isolate);
463   DCHECK(script_context->IsScriptContext());
464   DCHECK(script_context->get(slot)->IsPropertyCell());
465
466   // Lookup the named property on the global object.
467   Handle<ScopeInfo> scope_info(ScopeInfo::cast(script_context->extension()),
468                                isolate);
469   Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
470   Handle<GlobalObject> global_object(script_context->global_object(), isolate);
471   LookupIterator it(global_object, name, LookupIterator::HIDDEN);
472
473   // Switch to fast mode only if there is a data property and it's not on
474   // a hidden prototype.
475   if (it.state() == LookupIterator::DATA &&
476       it.GetHolder<Object>().is_identical_to(global_object)) {
477     // Now update cell in the script context.
478     Handle<PropertyCell> cell = it.GetPropertyCell();
479     script_context->set(slot, *cell);
480   } else {
481     // This is not a fast case, so keep this access in a slow mode.
482     // Store empty_property_cell here to release the outdated property cell.
483     script_context->set(slot, isolate->heap()->empty_property_cell());
484   }
485
486   Handle<Object> result;
487   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
488       isolate, result,
489       Object::SetProperty(&it, value, language_mode,
490                           Object::CERTAINLY_NOT_STORE_FROM_KEYED));
491   return *result;
492 }
493
494 }  // namespace
495
496
497 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Sloppy) {
498   HandleScope scope(isolate);
499   DCHECK_EQ(2, args.length());
500   CONVERT_SMI_ARG_CHECKED(slot, 0);
501   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
502
503   return StoreGlobalViaContext(isolate, slot, value, SLOPPY);
504 }
505
506
507 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Strict) {
508   HandleScope scope(isolate);
509   DCHECK_EQ(2, args.length());
510   CONVERT_SMI_ARG_CHECKED(slot, 0);
511   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
512
513   return StoreGlobalViaContext(isolate, slot, value, STRICT);
514 }
515
516
517 RUNTIME_FUNCTION(Runtime_GetProperty) {
518   HandleScope scope(isolate);
519   DCHECK(args.length() == 2);
520
521   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
522   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
523
524   Handle<Object> result;
525   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
526       isolate, result,
527       Runtime::GetObjectProperty(isolate, object, key, SLOPPY));
528   return *result;
529 }
530
531
532 RUNTIME_FUNCTION(Runtime_GetPropertyStrong) {
533   HandleScope scope(isolate);
534   DCHECK(args.length() == 2);
535
536   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
537   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
538
539   Handle<Object> result;
540   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
541       isolate, result,
542       Runtime::GetObjectProperty(isolate, object, key, STRONG));
543   return *result;
544 }
545
546
547 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
548 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
549   HandleScope scope(isolate);
550   DCHECK(args.length() == 2);
551
552   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
553   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
554
555   Handle<Object> result;
556   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
557       isolate, result,
558       Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, SLOPPY));
559   return *result;
560 }
561
562
563 RUNTIME_FUNCTION(Runtime_KeyedGetPropertyStrong) {
564   HandleScope scope(isolate);
565   DCHECK(args.length() == 2);
566
567   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
568   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
569
570   Handle<Object> result;
571   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
572       isolate, result,
573       Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, STRONG));
574   return *result;
575 }
576
577
578 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
579   HandleScope scope(isolate);
580   RUNTIME_ASSERT(args.length() == 4);
581
582   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
583   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
584   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
585   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
586
587 #ifdef DEBUG
588   uint32_t index = 0;
589   DCHECK(!name->ToArrayIndex(&index));
590   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
591   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
592   if (!maybe.IsJust()) return isolate->heap()->exception();
593   RUNTIME_ASSERT(!it.IsFound());
594 #endif
595
596   Handle<Object> result;
597   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
598       isolate, result,
599       JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs));
600   return *result;
601 }
602
603
604 // Adds an element to an array.
605 // This is used to create an indexed data property into an array.
606 RUNTIME_FUNCTION(Runtime_AddElement) {
607   HandleScope scope(isolate);
608   RUNTIME_ASSERT(args.length() == 3);
609
610   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
611   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
612   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
613
614   uint32_t index = 0;
615   CHECK(key->ToArrayIndex(&index));
616
617 #ifdef DEBUG
618   LookupIterator it(isolate, object, index,
619                     LookupIterator::OWN_SKIP_INTERCEPTOR);
620   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
621   if (!maybe.IsJust()) return isolate->heap()->exception();
622   RUNTIME_ASSERT(!it.IsFound());
623
624   if (object->IsJSArray()) {
625     Handle<JSArray> array = Handle<JSArray>::cast(object);
626     RUNTIME_ASSERT(!JSArray::WouldChangeReadOnlyLength(array, index));
627   }
628 #endif
629
630   Handle<Object> result;
631   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
632       isolate, result,
633       JSObject::SetOwnElementIgnoreAttributes(object, index, value, NONE));
634   return *result;
635 }
636
637
638 RUNTIME_FUNCTION(Runtime_AppendElement) {
639   HandleScope scope(isolate);
640   RUNTIME_ASSERT(args.length() == 2);
641
642   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
643   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
644
645   uint32_t index;
646   CHECK(array->length()->ToArrayIndex(&index));
647
648   Handle<Object> result;
649   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
650       isolate, result, JSObject::AddDataElement(array, index, value, NONE));
651   JSObject::ValidateElements(array);
652   return *array;
653 }
654
655
656 RUNTIME_FUNCTION(Runtime_SetProperty) {
657   HandleScope scope(isolate);
658   RUNTIME_ASSERT(args.length() == 4);
659
660   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
661   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
662   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
663   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
664   LanguageMode language_mode = language_mode_arg;
665
666   Handle<Object> result;
667   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
668       isolate, result,
669       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
670   return *result;
671 }
672
673
674 RUNTIME_FUNCTION(Runtime_DeleteProperty) {
675   HandleScope scope(isolate);
676   DCHECK(args.length() == 3);
677   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
678   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
679   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
680   Handle<Object> result;
681   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
682       isolate, result,
683       Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode));
684   return *result;
685 }
686
687
688 static Object* HasOwnPropertyImplementation(Isolate* isolate,
689                                             Handle<JSObject> object,
690                                             Handle<Name> key) {
691   Maybe<bool> maybe = JSReceiver::HasOwnProperty(object, key);
692   if (!maybe.IsJust()) return isolate->heap()->exception();
693   if (maybe.FromJust()) return isolate->heap()->true_value();
694   // Handle hidden prototypes.  If there's a hidden prototype above this thing
695   // then we have to check it for properties, because they are supposed to
696   // look like they are on this object.
697   PrototypeIterator iter(isolate, object);
698   if (!iter.IsAtEnd() &&
699       Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))
700           ->map()
701           ->is_hidden_prototype()) {
702     // TODO(verwaest): The recursion is not necessary for keys that are array
703     // indices. Removing this.
704     return HasOwnPropertyImplementation(
705         isolate, Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
706         key);
707   }
708   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
709   return isolate->heap()->false_value();
710 }
711
712
713 RUNTIME_FUNCTION(Runtime_HasOwnProperty) {
714   HandleScope scope(isolate);
715   DCHECK(args.length() == 2);
716   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0)
717   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
718
719   uint32_t index;
720   const bool key_is_array_index = key->AsArrayIndex(&index);
721
722   // Only JS objects can have properties.
723   if (object->IsJSObject()) {
724     Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
725     // Fast case: either the key is a real named property or it is not
726     // an array index and there are no interceptors or hidden
727     // prototypes.
728     Maybe<bool> maybe = Nothing<bool>();
729     if (key_is_array_index) {
730       maybe = JSObject::HasOwnElement(js_obj, index);
731     } else {
732       maybe = JSObject::HasRealNamedProperty(js_obj, key);
733     }
734     if (!maybe.IsJust()) return isolate->heap()->exception();
735     DCHECK(!isolate->has_pending_exception());
736     if (maybe.FromJust()) {
737       return isolate->heap()->true_value();
738     }
739     Map* map = js_obj->map();
740     if (!key_is_array_index && !map->has_named_interceptor() &&
741         !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
742       return isolate->heap()->false_value();
743     }
744     // Slow case.
745     return HasOwnPropertyImplementation(isolate, Handle<JSObject>(js_obj),
746                                         Handle<Name>(key));
747   } else if (object->IsString() && key_is_array_index) {
748     // Well, there is one exception:  Handle [] on strings.
749     Handle<String> string = Handle<String>::cast(object);
750     if (index < static_cast<uint32_t>(string->length())) {
751       return isolate->heap()->true_value();
752     }
753   }
754   return isolate->heap()->false_value();
755 }
756
757
758 RUNTIME_FUNCTION(Runtime_HasProperty) {
759   HandleScope scope(isolate);
760   DCHECK(args.length() == 2);
761   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
762   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
763
764   Maybe<bool> maybe = JSReceiver::HasProperty(receiver, key);
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::EnsureCompiled(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()->inobject_properties());
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_IsObject) {
1361   SealHandleScope shs(isolate);
1362   DCHECK(args.length() == 1);
1363   CONVERT_ARG_CHECKED(Object, obj, 0);
1364   if (!obj->IsHeapObject()) return isolate->heap()->false_value();
1365   if (obj->IsNull()) return isolate->heap()->true_value();
1366   if (obj->IsUndetectableObject()) return isolate->heap()->false_value();
1367   Map* map = HeapObject::cast(obj)->map();
1368   bool is_non_callable_spec_object =
1369       map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
1370       map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE;
1371   return isolate->heap()->ToBoolean(is_non_callable_spec_object);
1372 }
1373
1374
1375 RUNTIME_FUNCTION(Runtime_IsUndetectableObject) {
1376   SealHandleScope shs(isolate);
1377   DCHECK(args.length() == 1);
1378   CONVERT_ARG_CHECKED(Object, obj, 0);
1379   return isolate->heap()->ToBoolean(obj->IsUndetectableObject());
1380 }
1381
1382
1383 RUNTIME_FUNCTION(Runtime_IsSpecObject) {
1384   SealHandleScope shs(isolate);
1385   DCHECK(args.length() == 1);
1386   CONVERT_ARG_CHECKED(Object, obj, 0);
1387   return isolate->heap()->ToBoolean(obj->IsSpecObject());
1388 }
1389
1390
1391 RUNTIME_FUNCTION(Runtime_IsStrong) {
1392   SealHandleScope shs(isolate);
1393   DCHECK(args.length() == 1);
1394   CONVERT_ARG_CHECKED(Object, obj, 0);
1395   return isolate->heap()->ToBoolean(obj->IsJSReceiver() &&
1396                                     JSReceiver::cast(obj)->map()->is_strong());
1397 }
1398
1399
1400 RUNTIME_FUNCTION(Runtime_ClassOf) {
1401   SealHandleScope shs(isolate);
1402   DCHECK(args.length() == 1);
1403   CONVERT_ARG_CHECKED(Object, obj, 0);
1404   if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
1405   return JSReceiver::cast(obj)->class_name();
1406 }
1407
1408
1409 RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
1410   HandleScope scope(isolate);
1411   DCHECK(args.length() == 4);
1412   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1413   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1414   CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
1415   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1416
1417   RETURN_FAILURE_ON_EXCEPTION(
1418       isolate,
1419       JSObject::DefineAccessor(object, name, getter,
1420                                isolate->factory()->null_value(), attrs));
1421   return isolate->heap()->undefined_value();
1422 }
1423
1424
1425 RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
1426   HandleScope scope(isolate);
1427   DCHECK(args.length() == 4);
1428   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1429   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1430   CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
1431   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1432
1433   RETURN_FAILURE_ON_EXCEPTION(
1434       isolate,
1435       JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1436                                setter, attrs));
1437   return isolate->heap()->undefined_value();
1438 }
1439
1440
1441 RUNTIME_FUNCTION(Runtime_ToObject) {
1442   HandleScope scope(isolate);
1443   DCHECK_EQ(1, args.length());
1444   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1445   Handle<JSReceiver> receiver;
1446   if (JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
1447     return *receiver;
1448   }
1449   THROW_NEW_ERROR_RETURN_FAILURE(
1450       isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
1451 }
1452
1453 }  // namespace internal
1454 }  // namespace v8