[stubs] Optimize LoadGlobalViaContextStub and StoreGlobalViaContextStub.
[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.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(2, args.length());
424   CONVERT_SMI_ARG_CHECKED(slot, 0);
425   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
426
427   // Go up context chain to the script context.
428   Handle<Context> script_context(isolate->context()->script_context(), isolate);
429   DCHECK(script_context->IsScriptContext());
430   DCHECK(script_context->get(slot)->IsPropertyCell());
431
432   // Lookup the named property on the global object.
433   Handle<GlobalObject> global_object(script_context->global_object(), isolate);
434   LookupIterator it(global_object, name, LookupIterator::HIDDEN);
435
436   // Switch to fast mode only if there is a data property and it's not on
437   // a hidden prototype.
438   if (it.state() == LookupIterator::DATA &&
439       it.GetHolder<Object>()->IsJSGlobalObject()) {
440     // Now update the cell in the script context.
441     Handle<PropertyCell> cell = it.GetPropertyCell();
442     script_context->set(slot, *cell);
443   } else {
444     // This is not a fast case, so keep this access in a slow mode.
445     // Store empty_property_cell here to release the outdated property cell.
446     script_context->set(slot, isolate->heap()->empty_property_cell());
447   }
448
449   Handle<Object> result;
450   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
451   return *result;
452 }
453
454
455 namespace {
456
457 Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Name> name,
458                               Handle<Object> value,
459                               LanguageMode language_mode) {
460   // Go up context chain to the script context.
461   Handle<Context> script_context(isolate->context()->script_context(), isolate);
462   DCHECK(script_context->IsScriptContext());
463   DCHECK(script_context->get(slot)->IsPropertyCell());
464
465   // Lookup the named property on the global object.
466   Handle<GlobalObject> global_object(script_context->global_object(), isolate);
467   LookupIterator it(global_object, name, LookupIterator::HIDDEN);
468   // Switch to fast mode only if there is a data property and it's not on
469   // a hidden prototype.
470   if (LookupIterator::DATA == it.state() &&
471       it.GetHolder<Object>()->IsJSGlobalObject()) {
472     // Now update cell in the script context.
473     Handle<PropertyCell> cell = it.GetPropertyCell();
474     script_context->set(slot, *cell);
475   } else {
476     // This is not a fast case, so keep this access in a slow mode.
477     // Store empty_property_cell here to release the outdated property cell.
478     script_context->set(slot, isolate->heap()->empty_property_cell());
479   }
480
481   Handle<Object> result;
482   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
483       isolate, result,
484       Object::SetProperty(&it, value, language_mode,
485                           Object::CERTAINLY_NOT_STORE_FROM_KEYED));
486   return *result;
487 }
488
489 }  // namespace
490
491
492 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Sloppy) {
493   HandleScope scope(isolate);
494   DCHECK_EQ(3, args.length());
495   CONVERT_SMI_ARG_CHECKED(slot, 0);
496   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
497   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
498
499   return StoreGlobalViaContext(isolate, slot, name, value, SLOPPY);
500 }
501
502
503 RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Strict) {
504   HandleScope scope(isolate);
505   DCHECK_EQ(3, args.length());
506   CONVERT_SMI_ARG_CHECKED(slot, 0);
507   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
508   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
509
510   return StoreGlobalViaContext(isolate, slot, name, value, STRICT);
511 }
512
513
514 RUNTIME_FUNCTION(Runtime_GetProperty) {
515   HandleScope scope(isolate);
516   DCHECK(args.length() == 2);
517
518   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
519   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
520
521   Handle<Object> result;
522   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
523       isolate, result,
524       Runtime::GetObjectProperty(isolate, object, key, SLOPPY));
525   return *result;
526 }
527
528
529 RUNTIME_FUNCTION(Runtime_GetPropertyStrong) {
530   HandleScope scope(isolate);
531   DCHECK(args.length() == 2);
532
533   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
534   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
535
536   Handle<Object> result;
537   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
538       isolate, result,
539       Runtime::GetObjectProperty(isolate, object, key, STRONG));
540   return *result;
541 }
542
543
544 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
545 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
546   HandleScope scope(isolate);
547   DCHECK(args.length() == 2);
548
549   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
550   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
551
552   Handle<Object> result;
553   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
554       isolate, result,
555       Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, SLOPPY));
556   return *result;
557 }
558
559
560 RUNTIME_FUNCTION(Runtime_KeyedGetPropertyStrong) {
561   HandleScope scope(isolate);
562   DCHECK(args.length() == 2);
563
564   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
565   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
566
567   Handle<Object> result;
568   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
569       isolate, result,
570       Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, STRONG));
571   return *result;
572 }
573
574
575 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
576   HandleScope scope(isolate);
577   RUNTIME_ASSERT(args.length() == 4);
578
579   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
580   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
581   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
582   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
583
584 #ifdef DEBUG
585   uint32_t index = 0;
586   DCHECK(!name->ToArrayIndex(&index));
587   LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
588   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
589   if (!maybe.IsJust()) return isolate->heap()->exception();
590   RUNTIME_ASSERT(!it.IsFound());
591 #endif
592
593   Handle<Object> result;
594   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
595       isolate, result,
596       JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs));
597   return *result;
598 }
599
600
601 // Adds an element to an array.
602 // This is used to create an indexed data property into an array.
603 RUNTIME_FUNCTION(Runtime_AddElement) {
604   HandleScope scope(isolate);
605   RUNTIME_ASSERT(args.length() == 3);
606
607   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
608   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
609   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
610
611   uint32_t index = 0;
612   CHECK(key->ToArrayIndex(&index));
613
614 #ifdef DEBUG
615   LookupIterator it(isolate, object, index,
616                     LookupIterator::OWN_SKIP_INTERCEPTOR);
617   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
618   if (!maybe.IsJust()) return isolate->heap()->exception();
619   RUNTIME_ASSERT(!it.IsFound());
620
621   if (object->IsJSArray()) {
622     Handle<JSArray> array = Handle<JSArray>::cast(object);
623     RUNTIME_ASSERT(!JSArray::WouldChangeReadOnlyLength(array, index));
624   }
625 #endif
626
627   Handle<Object> result;
628   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
629       isolate, result,
630       JSObject::SetOwnElementIgnoreAttributes(object, index, value, NONE));
631   return *result;
632 }
633
634
635 RUNTIME_FUNCTION(Runtime_AppendElement) {
636   HandleScope scope(isolate);
637   RUNTIME_ASSERT(args.length() == 2);
638
639   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
640   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
641
642   uint32_t index;
643   CHECK(array->length()->ToArrayIndex(&index));
644
645   Handle<Object> result;
646   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
647       isolate, result, JSObject::AddDataElement(array, index, value, NONE));
648   JSObject::ValidateElements(array);
649   return *array;
650 }
651
652
653 RUNTIME_FUNCTION(Runtime_SetProperty) {
654   HandleScope scope(isolate);
655   RUNTIME_ASSERT(args.length() == 4);
656
657   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
658   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
659   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
660   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
661   LanguageMode language_mode = language_mode_arg;
662
663   Handle<Object> result;
664   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
665       isolate, result,
666       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
667   return *result;
668 }
669
670
671 RUNTIME_FUNCTION(Runtime_DeleteProperty) {
672   HandleScope scope(isolate);
673   DCHECK(args.length() == 3);
674   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
675   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
676   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
677   Handle<Object> result;
678   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
679       isolate, result,
680       Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode));
681   return *result;
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(Name, key, 1);
760
761   Maybe<bool> maybe = JSReceiver::HasProperty(receiver, key);
762   if (!maybe.IsJust()) return isolate->heap()->exception();
763   return isolate->heap()->ToBoolean(maybe.FromJust());
764 }
765
766
767 RUNTIME_FUNCTION(Runtime_HasElement) {
768   HandleScope scope(isolate);
769   DCHECK(args.length() == 2);
770   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
771   CONVERT_SMI_ARG_CHECKED(index, 1);
772
773   Maybe<bool> maybe = JSReceiver::HasElement(receiver, index);
774   if (!maybe.IsJust()) return isolate->heap()->exception();
775   return isolate->heap()->ToBoolean(maybe.FromJust());
776 }
777
778
779 RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) {
780   HandleScope scope(isolate);
781   DCHECK(args.length() == 2);
782
783   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
784   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
785
786   Maybe<PropertyAttributes> maybe =
787       JSReceiver::GetOwnPropertyAttributes(object, key);
788   if (!maybe.IsJust()) return isolate->heap()->exception();
789   if (maybe.FromJust() == ABSENT) maybe = Just(DONT_ENUM);
790   return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
791 }
792
793
794 RUNTIME_FUNCTION(Runtime_GetPropertyNames) {
795   HandleScope scope(isolate);
796   DCHECK(args.length() == 1);
797   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
798   Handle<JSArray> result;
799
800   isolate->counters()->for_in()->Increment();
801   Handle<FixedArray> elements;
802   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
803       isolate, elements,
804       JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
805   return *isolate->factory()->NewJSArrayWithElements(elements);
806 }
807
808
809 // Returns either a FixedArray as Runtime_GetPropertyNames,
810 // or, if the given object has an enum cache that contains
811 // all enumerable properties of the object and its prototypes
812 // have none, the map of the object. This is used to speed up
813 // the check for deletions during a for-in.
814 RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
815   SealHandleScope shs(isolate);
816   DCHECK(args.length() == 1);
817
818   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
819
820   if (raw_object->IsSimpleEnum()) return raw_object->map();
821
822   HandleScope scope(isolate);
823   Handle<JSReceiver> object(raw_object);
824   Handle<FixedArray> content;
825   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
826       isolate, content,
827       JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
828
829   // Test again, since cache may have been built by preceding call.
830   if (object->IsSimpleEnum()) return object->map();
831
832   return *content;
833 }
834
835
836 // Return the names of the own named properties.
837 // args[0]: object
838 // args[1]: PropertyAttributes as int
839 RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
840   HandleScope scope(isolate);
841   DCHECK(args.length() == 2);
842   if (!args[0]->IsJSObject()) {
843     return isolate->heap()->undefined_value();
844   }
845   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
846   CONVERT_SMI_ARG_CHECKED(filter_value, 1);
847   PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
848
849   // Find the number of own properties for each of the objects.
850   int total_property_count = 0;
851   for (PrototypeIterator iter(isolate, object,
852                               PrototypeIterator::START_AT_RECEIVER);
853        !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
854     Handle<JSObject> jsproto =
855         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
856     total_property_count += jsproto->NumberOfOwnProperties(filter);
857   }
858
859   // Allocate an array with storage for all the property names.
860   Handle<FixedArray> names =
861       isolate->factory()->NewFixedArray(total_property_count);
862
863   // Get the property names.
864   int next_copy_index = 0;
865   int hidden_strings = 0;
866   Handle<Object> hidden_string = isolate->factory()->hidden_string();
867   for (PrototypeIterator iter(isolate, object,
868                               PrototypeIterator::START_AT_RECEIVER);
869        !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
870     Handle<JSObject> jsproto =
871         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
872     int own = jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
873     // Names from hidden prototypes may already have been added
874     // for inherited function template instances. Count the duplicates
875     // and stub them out; the final copy pass at the end ignores holes.
876     for (int j = next_copy_index; j < next_copy_index + own; j++) {
877       Object* name_from_hidden_proto = names->get(j);
878       if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) {
879         hidden_strings++;
880       } else {
881         for (int k = 0; k < next_copy_index; k++) {
882           Object* name = names->get(k);
883           if (name_from_hidden_proto == name) {
884             names->set(j, *hidden_string);
885             hidden_strings++;
886             break;
887           }
888         }
889       }
890     }
891     next_copy_index += own;
892   }
893
894   CHECK_EQ(total_property_count, next_copy_index);
895
896   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
897     for (int i = 0; i < total_property_count; i++) {
898       Handle<Name> name(Name::cast(names->get(i)));
899       if (name.is_identical_to(hidden_string)) continue;
900       LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
901       if (!JSObject::AllCanRead(&it)) {
902         names->set(i, *hidden_string);
903         hidden_strings++;
904       }
905     }
906   }
907
908   // Filter out name of hidden properties object and
909   // hidden prototype duplicates.
910   if (hidden_strings > 0) {
911     if (hidden_strings == total_property_count) {
912       names = isolate->factory()->empty_fixed_array();
913     } else {
914       int i;
915       for (i = 0; i < total_property_count; i++) {
916         Object* name = names->get(i);
917         if (name == *hidden_string) break;
918       }
919       int dest_pos = i;
920       for (; i < total_property_count; i++) {
921         Object* name = names->get(i);
922         if (name == *hidden_string) continue;
923         names->set(dest_pos++, name);
924       }
925
926       isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
927           *names, hidden_strings);
928     }
929   }
930
931   return *isolate->factory()->NewJSArrayWithElements(names);
932 }
933
934
935 // Return the names of the own indexed properties.
936 // args[0]: object
937 RUNTIME_FUNCTION(Runtime_GetOwnElementNames) {
938   HandleScope scope(isolate);
939   DCHECK(args.length() == 1);
940   if (!args[0]->IsJSObject()) {
941     return isolate->heap()->undefined_value();
942   }
943   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
944
945   int n = obj->NumberOfOwnElements(NONE);
946   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
947   obj->GetOwnElementKeys(*names, NONE);
948   return *isolate->factory()->NewJSArrayWithElements(names);
949 }
950
951
952 // Return information on whether an object has a named or indexed interceptor.
953 // args[0]: object
954 RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
955   HandleScope scope(isolate);
956   DCHECK(args.length() == 1);
957   if (!args[0]->IsJSObject()) {
958     return Smi::FromInt(0);
959   }
960   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
961
962   int result = 0;
963   if (obj->HasNamedInterceptor()) result |= 2;
964   if (obj->HasIndexedInterceptor()) result |= 1;
965
966   return Smi::FromInt(result);
967 }
968
969
970 // Return property names from named interceptor.
971 // args[0]: object
972 RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames) {
973   HandleScope scope(isolate);
974   DCHECK(args.length() == 1);
975   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
976
977   if (obj->HasNamedInterceptor()) {
978     Handle<JSObject> result;
979     if (JSObject::GetKeysForNamedInterceptor(obj, obj).ToHandle(&result)) {
980       return *result;
981     }
982   }
983   return isolate->heap()->undefined_value();
984 }
985
986
987 // Return element names from indexed interceptor.
988 // args[0]: object
989 RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames) {
990   HandleScope scope(isolate);
991   DCHECK(args.length() == 1);
992   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
993
994   if (obj->HasIndexedInterceptor()) {
995     Handle<JSObject> result;
996     if (JSObject::GetKeysForIndexedInterceptor(obj, obj).ToHandle(&result)) {
997       return *result;
998     }
999   }
1000   return isolate->heap()->undefined_value();
1001 }
1002
1003
1004 RUNTIME_FUNCTION(Runtime_OwnKeys) {
1005   HandleScope scope(isolate);
1006   DCHECK(args.length() == 1);
1007   CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
1008   Handle<JSObject> object(raw_object);
1009
1010   Handle<FixedArray> contents;
1011   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1012       isolate, contents, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY));
1013
1014   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
1015   // property array and since the result is mutable we have to create
1016   // a fresh clone on each invocation.
1017   int length = contents->length();
1018   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
1019   for (int i = 0; i < length; i++) {
1020     Object* entry = contents->get(i);
1021     if (entry->IsString()) {
1022       copy->set(i, entry);
1023     } else {
1024       DCHECK(entry->IsNumber());
1025       HandleScope scope(isolate);
1026       Handle<Object> entry_handle(entry, isolate);
1027       Handle<Object> entry_str =
1028           isolate->factory()->NumberToString(entry_handle);
1029       copy->set(i, *entry_str);
1030     }
1031   }
1032   return *isolate->factory()->NewJSArrayWithElements(copy);
1033 }
1034
1035
1036 RUNTIME_FUNCTION(Runtime_ToFastProperties) {
1037   HandleScope scope(isolate);
1038   DCHECK(args.length() == 1);
1039   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1040   if (object->IsJSObject() && !object->IsGlobalObject()) {
1041     JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
1042                                 "RuntimeToFastProperties");
1043   }
1044   return *object;
1045 }
1046
1047
1048 RUNTIME_FUNCTION(Runtime_ToBool) {
1049   SealHandleScope shs(isolate);
1050   DCHECK(args.length() == 1);
1051   CONVERT_ARG_CHECKED(Object, object, 0);
1052
1053   return isolate->heap()->ToBoolean(object->BooleanValue());
1054 }
1055
1056
1057 RUNTIME_FUNCTION(Runtime_NewStringWrapper) {
1058   HandleScope scope(isolate);
1059   DCHECK(args.length() == 1);
1060   CONVERT_ARG_HANDLE_CHECKED(String, value, 0);
1061   return *Object::ToObject(isolate, value).ToHandleChecked();
1062 }
1063
1064
1065 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
1066   HandleScope scope(isolate);
1067   DCHECK(args.length() == 0);
1068   return *isolate->factory()->NewHeapNumber(0);
1069 }
1070
1071
1072 static Object* Runtime_NewObjectHelper(Isolate* isolate,
1073                                        Handle<Object> constructor,
1074                                        Handle<Object> original_constructor,
1075                                        Handle<AllocationSite> site) {
1076   // If the constructor isn't a proper function we throw a type error.
1077   if (!constructor->IsJSFunction()) {
1078     THROW_NEW_ERROR_RETURN_FAILURE(
1079         isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor));
1080   }
1081
1082   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
1083
1084   CHECK(original_constructor->IsJSFunction());
1085   Handle<JSFunction> original_function =
1086       Handle<JSFunction>::cast(original_constructor);
1087
1088
1089   // If function should not have prototype, construction is not allowed. In this
1090   // case generated code bailouts here, since function has no initial_map.
1091   if (!function->should_have_prototype() && !function->shared()->bound()) {
1092     THROW_NEW_ERROR_RETURN_FAILURE(
1093         isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor));
1094   }
1095
1096   Debug* debug = isolate->debug();
1097   // Handle stepping into constructors if step into is active.
1098   if (debug->StepInActive()) debug->HandleStepIn(function, true);
1099
1100   if (function->has_initial_map()) {
1101     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
1102       // The 'Function' function ignores the receiver object when
1103       // called using 'new' and creates a new JSFunction object that
1104       // is returned.  The receiver object is only used for error
1105       // reporting if an error occurs when constructing the new
1106       // JSFunction. Factory::NewJSObject() should not be used to
1107       // allocate JSFunctions since it does not properly initialize
1108       // the shared part of the function. Since the receiver is
1109       // ignored anyway, we use the global object as the receiver
1110       // instead of a new JSFunction object. This way, errors are
1111       // reported the same way whether or not 'Function' is called
1112       // using 'new'.
1113       return isolate->global_proxy();
1114     }
1115   }
1116
1117   // The function should be compiled for the optimization hints to be
1118   // available.
1119   Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
1120
1121   Handle<JSObject> result;
1122   if (site.is_null()) {
1123     result = isolate->factory()->NewJSObject(function);
1124   } else {
1125     result = isolate->factory()->NewJSObjectWithMemento(function, site);
1126   }
1127
1128   // Set up the prototoype using original function.
1129   // TODO(dslomov): instead of setting the __proto__,
1130   // use and cache the correct map.
1131   if (*original_function != *function) {
1132     if (original_function->has_instance_prototype()) {
1133       Handle<Object> prototype =
1134           handle(original_function->instance_prototype(), isolate);
1135       RETURN_FAILURE_ON_EXCEPTION(
1136           isolate, JSObject::SetPrototype(result, prototype, false));
1137     }
1138   }
1139
1140   isolate->counters()->constructed_objects()->Increment();
1141   isolate->counters()->constructed_objects_runtime()->Increment();
1142
1143   return *result;
1144 }
1145
1146
1147 RUNTIME_FUNCTION(Runtime_NewObject) {
1148   HandleScope scope(isolate);
1149   DCHECK(args.length() == 2);
1150   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
1151   CONVERT_ARG_HANDLE_CHECKED(Object, original_constructor, 1);
1152   return Runtime_NewObjectHelper(isolate, constructor, original_constructor,
1153                                  Handle<AllocationSite>::null());
1154 }
1155
1156
1157 RUNTIME_FUNCTION(Runtime_NewObjectWithAllocationSite) {
1158   HandleScope scope(isolate);
1159   DCHECK(args.length() == 3);
1160   CONVERT_ARG_HANDLE_CHECKED(Object, original_constructor, 2);
1161   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 1);
1162   CONVERT_ARG_HANDLE_CHECKED(Object, feedback, 0);
1163   Handle<AllocationSite> site;
1164   if (feedback->IsAllocationSite()) {
1165     // The feedback can be an AllocationSite or undefined.
1166     site = Handle<AllocationSite>::cast(feedback);
1167   }
1168   return Runtime_NewObjectHelper(isolate, constructor, original_constructor,
1169                                  site);
1170 }
1171
1172
1173 RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) {
1174   HandleScope scope(isolate);
1175   DCHECK(args.length() == 1);
1176
1177   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1178   function->CompleteInobjectSlackTracking();
1179
1180   return isolate->heap()->undefined_value();
1181 }
1182
1183
1184 RUNTIME_FUNCTION(Runtime_GlobalProxy) {
1185   SealHandleScope shs(isolate);
1186   DCHECK(args.length() == 1);
1187   CONVERT_ARG_CHECKED(JSFunction, function, 0);
1188   return function->context()->global_proxy();
1189 }
1190
1191
1192 RUNTIME_FUNCTION(Runtime_LookupAccessor) {
1193   HandleScope scope(isolate);
1194   DCHECK(args.length() == 3);
1195   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
1196   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1197   CONVERT_SMI_ARG_CHECKED(flag, 2);
1198   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
1199   if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
1200   Handle<Object> result;
1201   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1202       isolate, result,
1203       JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
1204   return *result;
1205 }
1206
1207
1208 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
1209   HandleScope scope(isolate);
1210   DCHECK(args.length() == 2);
1211   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1212   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
1213   RUNTIME_ASSERT((index->value() & 1) == 1);
1214   FieldIndex field_index =
1215       FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
1216   if (field_index.is_inobject()) {
1217     RUNTIME_ASSERT(field_index.property_index() <
1218                    object->map()->inobject_properties());
1219   } else {
1220     RUNTIME_ASSERT(field_index.outobject_array_index() <
1221                    object->properties()->length());
1222   }
1223   return *JSObject::FastPropertyAt(object, Representation::Double(),
1224                                    field_index);
1225 }
1226
1227
1228 RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
1229   HandleScope scope(isolate);
1230   DCHECK(args.length() == 1);
1231   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1232   if (!object->IsJSObject()) return Smi::FromInt(0);
1233   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
1234   if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
1235   // This call must not cause lazy deopts, because it's called from deferred
1236   // code where we can't handle lazy deopts for lack of a suitable bailout
1237   // ID. So we just try migration and signal failure if necessary,
1238   // which will also trigger a deopt.
1239   if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0);
1240   return *object;
1241 }
1242
1243
1244 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
1245   SealHandleScope shs(isolate);
1246   DCHECK(args.length() == 1);
1247   CONVERT_ARG_CHECKED(Object, obj, 0);
1248   return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
1249 }
1250
1251
1252 static bool IsValidAccessor(Handle<Object> obj) {
1253   return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
1254 }
1255
1256
1257 // Implements part of 8.12.9 DefineOwnProperty.
1258 // There are 3 cases that lead here:
1259 // Step 4b - define a new accessor property.
1260 // Steps 9c & 12 - replace an existing data property with an accessor property.
1261 // Step 12 - update an existing accessor property with an accessor or generic
1262 //           descriptor.
1263 RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
1264   HandleScope scope(isolate);
1265   DCHECK(args.length() == 5);
1266   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1267   RUNTIME_ASSERT(!obj->IsNull());
1268   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1269   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
1270   RUNTIME_ASSERT(IsValidAccessor(getter));
1271   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
1272   RUNTIME_ASSERT(IsValidAccessor(setter));
1273   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
1274
1275   RETURN_FAILURE_ON_EXCEPTION(
1276       isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
1277   return isolate->heap()->undefined_value();
1278 }
1279
1280
1281 // Implements part of 8.12.9 DefineOwnProperty.
1282 // There are 3 cases that lead here:
1283 // Step 4a - define a new data property.
1284 // Steps 9b & 12 - replace an existing accessor property with a data property.
1285 // Step 12 - update an existing data property with a data or generic
1286 //           descriptor.
1287 RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
1288   HandleScope scope(isolate);
1289   DCHECK(args.length() == 4);
1290   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1291   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1292   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1293   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1294
1295   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
1296                                                         LookupIterator::OWN);
1297   if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) {
1298     return isolate->heap()->undefined_value();
1299   }
1300
1301   Handle<Object> result;
1302   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1303       isolate, result, JSObject::DefineOwnPropertyIgnoreAttributes(
1304                            &it, value, attrs, JSObject::DONT_FORCE_FIELD));
1305
1306   return *result;
1307 }
1308
1309
1310 // Return property without being observable by accessors or interceptors.
1311 RUNTIME_FUNCTION(Runtime_GetDataProperty) {
1312   HandleScope scope(isolate);
1313   DCHECK(args.length() == 2);
1314   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
1315   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1316   return *JSReceiver::GetDataProperty(object, name);
1317 }
1318
1319
1320 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
1321   SealHandleScope shs(isolate);
1322   DCHECK(args.length() == 1);
1323   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
1324   return isolate->heap()->ToBoolean(
1325       IsFastPackedElementsKind(obj->map()->elements_kind()));
1326 }
1327
1328
1329 RUNTIME_FUNCTION(Runtime_ValueOf) {
1330   SealHandleScope shs(isolate);
1331   DCHECK(args.length() == 1);
1332   CONVERT_ARG_CHECKED(Object, obj, 0);
1333   if (!obj->IsJSValue()) return obj;
1334   return JSValue::cast(obj)->value();
1335 }
1336
1337
1338 RUNTIME_FUNCTION(Runtime_SetValueOf) {
1339   SealHandleScope shs(isolate);
1340   DCHECK(args.length() == 2);
1341   CONVERT_ARG_CHECKED(Object, obj, 0);
1342   CONVERT_ARG_CHECKED(Object, value, 1);
1343   if (!obj->IsJSValue()) return value;
1344   JSValue::cast(obj)->set_value(value);
1345   return value;
1346 }
1347
1348
1349 RUNTIME_FUNCTION(Runtime_JSValueGetValue) {
1350   SealHandleScope shs(isolate);
1351   DCHECK(args.length() == 1);
1352   CONVERT_ARG_CHECKED(JSValue, obj, 0);
1353   return JSValue::cast(obj)->value();
1354 }
1355
1356
1357 RUNTIME_FUNCTION(Runtime_HeapObjectGetMap) {
1358   SealHandleScope shs(isolate);
1359   DCHECK(args.length() == 1);
1360   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
1361   return obj->map();
1362 }
1363
1364
1365 RUNTIME_FUNCTION(Runtime_MapGetInstanceType) {
1366   SealHandleScope shs(isolate);
1367   DCHECK(args.length() == 1);
1368   CONVERT_ARG_CHECKED(Map, map, 0);
1369   return Smi::FromInt(map->instance_type());
1370 }
1371
1372
1373 RUNTIME_FUNCTION(Runtime_ObjectEquals) {
1374   SealHandleScope shs(isolate);
1375   DCHECK(args.length() == 2);
1376   CONVERT_ARG_CHECKED(Object, obj1, 0);
1377   CONVERT_ARG_CHECKED(Object, obj2, 1);
1378   return isolate->heap()->ToBoolean(obj1 == obj2);
1379 }
1380
1381
1382 RUNTIME_FUNCTION(Runtime_IsObject) {
1383   SealHandleScope shs(isolate);
1384   DCHECK(args.length() == 1);
1385   CONVERT_ARG_CHECKED(Object, obj, 0);
1386   if (!obj->IsHeapObject()) return isolate->heap()->false_value();
1387   if (obj->IsNull()) return isolate->heap()->true_value();
1388   if (obj->IsUndetectableObject()) return isolate->heap()->false_value();
1389   Map* map = HeapObject::cast(obj)->map();
1390   bool is_non_callable_spec_object =
1391       map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
1392       map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE;
1393   return isolate->heap()->ToBoolean(is_non_callable_spec_object);
1394 }
1395
1396
1397 RUNTIME_FUNCTION(Runtime_IsUndetectableObject) {
1398   SealHandleScope shs(isolate);
1399   DCHECK(args.length() == 1);
1400   CONVERT_ARG_CHECKED(Object, obj, 0);
1401   return isolate->heap()->ToBoolean(obj->IsUndetectableObject());
1402 }
1403
1404
1405 RUNTIME_FUNCTION(Runtime_IsSpecObject) {
1406   SealHandleScope shs(isolate);
1407   DCHECK(args.length() == 1);
1408   CONVERT_ARG_CHECKED(Object, obj, 0);
1409   return isolate->heap()->ToBoolean(obj->IsSpecObject());
1410 }
1411
1412
1413 RUNTIME_FUNCTION(Runtime_IsStrong) {
1414   SealHandleScope shs(isolate);
1415   DCHECK(args.length() == 1);
1416   CONVERT_ARG_CHECKED(Object, obj, 0);
1417   return isolate->heap()->ToBoolean(obj->IsJSReceiver() &&
1418                                     JSReceiver::cast(obj)->map()->is_strong());
1419 }
1420
1421
1422 RUNTIME_FUNCTION(Runtime_ClassOf) {
1423   SealHandleScope shs(isolate);
1424   DCHECK(args.length() == 1);
1425   CONVERT_ARG_CHECKED(Object, obj, 0);
1426   if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
1427   return JSReceiver::cast(obj)->class_name();
1428 }
1429
1430
1431 RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
1432   HandleScope scope(isolate);
1433   DCHECK(args.length() == 4);
1434   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1435   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1436   CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
1437   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1438
1439   RETURN_FAILURE_ON_EXCEPTION(
1440       isolate,
1441       JSObject::DefineAccessor(object, name, getter,
1442                                isolate->factory()->null_value(), attrs));
1443   return isolate->heap()->undefined_value();
1444 }
1445
1446
1447 RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
1448   HandleScope scope(isolate);
1449   DCHECK(args.length() == 4);
1450   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1451   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1452   CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
1453   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1454
1455   RETURN_FAILURE_ON_EXCEPTION(
1456       isolate,
1457       JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1458                                setter, attrs));
1459   return isolate->heap()->undefined_value();
1460 }
1461 }  // namespace internal
1462 }  // namespace v8