[stubs] Also handle properties of the JSBuiltinsObject in the fast case.
[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(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 RUNTIME_FUNCTION(Runtime_GetPropertyNames) {
798   HandleScope scope(isolate);
799   DCHECK(args.length() == 1);
800   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
801   Handle<JSArray> result;
802
803   isolate->counters()->for_in()->Increment();
804   Handle<FixedArray> elements;
805   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
806       isolate, elements,
807       JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
808   return *isolate->factory()->NewJSArrayWithElements(elements);
809 }
810
811
812 // Returns either a FixedArray as Runtime_GetPropertyNames,
813 // or, if the given object has an enum cache that contains
814 // all enumerable properties of the object and its prototypes
815 // have none, the map of the object. This is used to speed up
816 // the check for deletions during a for-in.
817 RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
818   SealHandleScope shs(isolate);
819   DCHECK(args.length() == 1);
820
821   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
822
823   if (raw_object->IsSimpleEnum()) return raw_object->map();
824
825   HandleScope scope(isolate);
826   Handle<JSReceiver> object(raw_object);
827   Handle<FixedArray> content;
828   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
829       isolate, content,
830       JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
831
832   // Test again, since cache may have been built by preceding call.
833   if (object->IsSimpleEnum()) return object->map();
834
835   return *content;
836 }
837
838
839 // Return the names of the own named properties.
840 // args[0]: object
841 // args[1]: PropertyAttributes as int
842 RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
843   HandleScope scope(isolate);
844   DCHECK(args.length() == 2);
845   if (!args[0]->IsJSObject()) {
846     return isolate->heap()->undefined_value();
847   }
848   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
849   CONVERT_SMI_ARG_CHECKED(filter_value, 1);
850   PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
851
852   // Find the number of own properties for each of the objects.
853   int total_property_count = 0;
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     total_property_count += jsproto->NumberOfOwnProperties(filter);
860   }
861
862   // Allocate an array with storage for all the property names.
863   Handle<FixedArray> names =
864       isolate->factory()->NewFixedArray(total_property_count);
865
866   // Get the property names.
867   int next_copy_index = 0;
868   int hidden_strings = 0;
869   Handle<Object> hidden_string = isolate->factory()->hidden_string();
870   for (PrototypeIterator iter(isolate, object,
871                               PrototypeIterator::START_AT_RECEIVER);
872        !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
873     Handle<JSObject> jsproto =
874         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
875     int own = jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
876     // Names from hidden prototypes may already have been added
877     // for inherited function template instances. Count the duplicates
878     // and stub them out; the final copy pass at the end ignores holes.
879     for (int j = next_copy_index; j < next_copy_index + own; j++) {
880       Object* name_from_hidden_proto = names->get(j);
881       if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) {
882         hidden_strings++;
883       } else {
884         for (int k = 0; k < next_copy_index; k++) {
885           Object* name = names->get(k);
886           if (name_from_hidden_proto == name) {
887             names->set(j, *hidden_string);
888             hidden_strings++;
889             break;
890           }
891         }
892       }
893     }
894     next_copy_index += own;
895   }
896
897   CHECK_EQ(total_property_count, next_copy_index);
898
899   if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
900     for (int i = 0; i < total_property_count; i++) {
901       Handle<Name> name(Name::cast(names->get(i)));
902       if (name.is_identical_to(hidden_string)) continue;
903       LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
904       if (!JSObject::AllCanRead(&it)) {
905         names->set(i, *hidden_string);
906         hidden_strings++;
907       }
908     }
909   }
910
911   // Filter out name of hidden properties object and
912   // hidden prototype duplicates.
913   if (hidden_strings > 0) {
914     if (hidden_strings == total_property_count) {
915       names = isolate->factory()->empty_fixed_array();
916     } else {
917       int i;
918       for (i = 0; i < total_property_count; i++) {
919         Object* name = names->get(i);
920         if (name == *hidden_string) break;
921       }
922       int dest_pos = i;
923       for (; i < total_property_count; i++) {
924         Object* name = names->get(i);
925         if (name == *hidden_string) continue;
926         names->set(dest_pos++, name);
927       }
928
929       isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
930           *names, hidden_strings);
931     }
932   }
933
934   return *isolate->factory()->NewJSArrayWithElements(names);
935 }
936
937
938 // Return the names of the own indexed properties.
939 // args[0]: object
940 RUNTIME_FUNCTION(Runtime_GetOwnElementNames) {
941   HandleScope scope(isolate);
942   DCHECK(args.length() == 1);
943   if (!args[0]->IsJSObject()) {
944     return isolate->heap()->undefined_value();
945   }
946   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
947
948   int n = obj->NumberOfOwnElements(NONE);
949   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
950   obj->GetOwnElementKeys(*names, NONE);
951   return *isolate->factory()->NewJSArrayWithElements(names);
952 }
953
954
955 // Return information on whether an object has a named or indexed interceptor.
956 // args[0]: object
957 RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
958   HandleScope scope(isolate);
959   DCHECK(args.length() == 1);
960   if (!args[0]->IsJSObject()) {
961     return Smi::FromInt(0);
962   }
963   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
964
965   int result = 0;
966   if (obj->HasNamedInterceptor()) result |= 2;
967   if (obj->HasIndexedInterceptor()) result |= 1;
968
969   return Smi::FromInt(result);
970 }
971
972
973 // Return property names from named interceptor.
974 // args[0]: object
975 RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames) {
976   HandleScope scope(isolate);
977   DCHECK(args.length() == 1);
978   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
979
980   if (obj->HasNamedInterceptor()) {
981     Handle<JSObject> result;
982     if (JSObject::GetKeysForNamedInterceptor(obj, obj).ToHandle(&result)) {
983       return *result;
984     }
985   }
986   return isolate->heap()->undefined_value();
987 }
988
989
990 // Return element names from indexed interceptor.
991 // args[0]: object
992 RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames) {
993   HandleScope scope(isolate);
994   DCHECK(args.length() == 1);
995   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
996
997   if (obj->HasIndexedInterceptor()) {
998     Handle<JSObject> result;
999     if (JSObject::GetKeysForIndexedInterceptor(obj, obj).ToHandle(&result)) {
1000       return *result;
1001     }
1002   }
1003   return isolate->heap()->undefined_value();
1004 }
1005
1006
1007 RUNTIME_FUNCTION(Runtime_OwnKeys) {
1008   HandleScope scope(isolate);
1009   DCHECK(args.length() == 1);
1010   CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
1011   Handle<JSObject> object(raw_object);
1012
1013   Handle<FixedArray> contents;
1014   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1015       isolate, contents, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY));
1016
1017   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
1018   // property array and since the result is mutable we have to create
1019   // a fresh clone on each invocation.
1020   int length = contents->length();
1021   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
1022   for (int i = 0; i < length; i++) {
1023     Object* entry = contents->get(i);
1024     if (entry->IsString()) {
1025       copy->set(i, entry);
1026     } else {
1027       DCHECK(entry->IsNumber());
1028       HandleScope scope(isolate);
1029       Handle<Object> entry_handle(entry, isolate);
1030       Handle<Object> entry_str =
1031           isolate->factory()->NumberToString(entry_handle);
1032       copy->set(i, *entry_str);
1033     }
1034   }
1035   return *isolate->factory()->NewJSArrayWithElements(copy);
1036 }
1037
1038
1039 RUNTIME_FUNCTION(Runtime_ToFastProperties) {
1040   HandleScope scope(isolate);
1041   DCHECK(args.length() == 1);
1042   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1043   if (object->IsJSObject() && !object->IsGlobalObject()) {
1044     JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
1045                                 "RuntimeToFastProperties");
1046   }
1047   return *object;
1048 }
1049
1050
1051 RUNTIME_FUNCTION(Runtime_ToBool) {
1052   SealHandleScope shs(isolate);
1053   DCHECK(args.length() == 1);
1054   CONVERT_ARG_CHECKED(Object, object, 0);
1055
1056   return isolate->heap()->ToBoolean(object->BooleanValue());
1057 }
1058
1059
1060 RUNTIME_FUNCTION(Runtime_NewStringWrapper) {
1061   HandleScope scope(isolate);
1062   DCHECK(args.length() == 1);
1063   CONVERT_ARG_HANDLE_CHECKED(String, value, 0);
1064   return *Object::ToObject(isolate, value).ToHandleChecked();
1065 }
1066
1067
1068 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
1069   HandleScope scope(isolate);
1070   DCHECK(args.length() == 0);
1071   return *isolate->factory()->NewHeapNumber(0);
1072 }
1073
1074
1075 static Object* Runtime_NewObjectHelper(Isolate* isolate,
1076                                        Handle<Object> constructor,
1077                                        Handle<Object> original_constructor,
1078                                        Handle<AllocationSite> site) {
1079   // If the constructor isn't a proper function we throw a type error.
1080   if (!constructor->IsJSFunction()) {
1081     THROW_NEW_ERROR_RETURN_FAILURE(
1082         isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor));
1083   }
1084
1085   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
1086
1087   CHECK(original_constructor->IsJSFunction());
1088   Handle<JSFunction> original_function =
1089       Handle<JSFunction>::cast(original_constructor);
1090
1091
1092   // If function should not have prototype, construction is not allowed. In this
1093   // case generated code bailouts here, since function has no initial_map.
1094   if (!function->should_have_prototype() && !function->shared()->bound()) {
1095     THROW_NEW_ERROR_RETURN_FAILURE(
1096         isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor));
1097   }
1098
1099   Debug* debug = isolate->debug();
1100   // Handle stepping into constructors if step into is active.
1101   if (debug->StepInActive()) debug->HandleStepIn(function, true);
1102
1103   if (function->has_initial_map()) {
1104     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
1105       // The 'Function' function ignores the receiver object when
1106       // called using 'new' and creates a new JSFunction object that
1107       // is returned.  The receiver object is only used for error
1108       // reporting if an error occurs when constructing the new
1109       // JSFunction. Factory::NewJSObject() should not be used to
1110       // allocate JSFunctions since it does not properly initialize
1111       // the shared part of the function. Since the receiver is
1112       // ignored anyway, we use the global object as the receiver
1113       // instead of a new JSFunction object. This way, errors are
1114       // reported the same way whether or not 'Function' is called
1115       // using 'new'.
1116       return isolate->global_proxy();
1117     }
1118   }
1119
1120   // The function should be compiled for the optimization hints to be
1121   // available.
1122   Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
1123
1124   Handle<JSObject> result;
1125   if (site.is_null()) {
1126     result = isolate->factory()->NewJSObject(function);
1127   } else {
1128     result = isolate->factory()->NewJSObjectWithMemento(function, site);
1129   }
1130
1131   // Set up the prototoype using original function.
1132   // TODO(dslomov): instead of setting the __proto__,
1133   // use and cache the correct map.
1134   if (*original_function != *function) {
1135     if (original_function->has_instance_prototype()) {
1136       Handle<Object> prototype =
1137           handle(original_function->instance_prototype(), isolate);
1138       RETURN_FAILURE_ON_EXCEPTION(
1139           isolate, JSObject::SetPrototype(result, prototype, false));
1140     }
1141   }
1142
1143   isolate->counters()->constructed_objects()->Increment();
1144   isolate->counters()->constructed_objects_runtime()->Increment();
1145
1146   return *result;
1147 }
1148
1149
1150 RUNTIME_FUNCTION(Runtime_NewObject) {
1151   HandleScope scope(isolate);
1152   DCHECK(args.length() == 2);
1153   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
1154   CONVERT_ARG_HANDLE_CHECKED(Object, original_constructor, 1);
1155   return Runtime_NewObjectHelper(isolate, constructor, original_constructor,
1156                                  Handle<AllocationSite>::null());
1157 }
1158
1159
1160 RUNTIME_FUNCTION(Runtime_NewObjectWithAllocationSite) {
1161   HandleScope scope(isolate);
1162   DCHECK(args.length() == 3);
1163   CONVERT_ARG_HANDLE_CHECKED(Object, original_constructor, 2);
1164   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 1);
1165   CONVERT_ARG_HANDLE_CHECKED(Object, feedback, 0);
1166   Handle<AllocationSite> site;
1167   if (feedback->IsAllocationSite()) {
1168     // The feedback can be an AllocationSite or undefined.
1169     site = Handle<AllocationSite>::cast(feedback);
1170   }
1171   return Runtime_NewObjectHelper(isolate, constructor, original_constructor,
1172                                  site);
1173 }
1174
1175
1176 RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) {
1177   HandleScope scope(isolate);
1178   DCHECK(args.length() == 1);
1179
1180   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1181   function->CompleteInobjectSlackTracking();
1182
1183   return isolate->heap()->undefined_value();
1184 }
1185
1186
1187 RUNTIME_FUNCTION(Runtime_GlobalProxy) {
1188   SealHandleScope shs(isolate);
1189   DCHECK(args.length() == 1);
1190   CONVERT_ARG_CHECKED(JSFunction, function, 0);
1191   return function->context()->global_proxy();
1192 }
1193
1194
1195 RUNTIME_FUNCTION(Runtime_LookupAccessor) {
1196   HandleScope scope(isolate);
1197   DCHECK(args.length() == 3);
1198   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
1199   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1200   CONVERT_SMI_ARG_CHECKED(flag, 2);
1201   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
1202   if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
1203   Handle<Object> result;
1204   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1205       isolate, result,
1206       JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
1207   return *result;
1208 }
1209
1210
1211 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
1212   HandleScope scope(isolate);
1213   DCHECK(args.length() == 2);
1214   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1215   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
1216   RUNTIME_ASSERT((index->value() & 1) == 1);
1217   FieldIndex field_index =
1218       FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
1219   if (field_index.is_inobject()) {
1220     RUNTIME_ASSERT(field_index.property_index() <
1221                    object->map()->inobject_properties());
1222   } else {
1223     RUNTIME_ASSERT(field_index.outobject_array_index() <
1224                    object->properties()->length());
1225   }
1226   return *JSObject::FastPropertyAt(object, Representation::Double(),
1227                                    field_index);
1228 }
1229
1230
1231 RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
1232   HandleScope scope(isolate);
1233   DCHECK(args.length() == 1);
1234   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1235   if (!object->IsJSObject()) return Smi::FromInt(0);
1236   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
1237   if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
1238   // This call must not cause lazy deopts, because it's called from deferred
1239   // code where we can't handle lazy deopts for lack of a suitable bailout
1240   // ID. So we just try migration and signal failure if necessary,
1241   // which will also trigger a deopt.
1242   if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0);
1243   return *object;
1244 }
1245
1246
1247 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
1248   SealHandleScope shs(isolate);
1249   DCHECK(args.length() == 1);
1250   CONVERT_ARG_CHECKED(Object, obj, 0);
1251   return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
1252 }
1253
1254
1255 static bool IsValidAccessor(Handle<Object> obj) {
1256   return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
1257 }
1258
1259
1260 // Implements part of 8.12.9 DefineOwnProperty.
1261 // There are 3 cases that lead here:
1262 // Step 4b - define a new accessor property.
1263 // Steps 9c & 12 - replace an existing data property with an accessor property.
1264 // Step 12 - update an existing accessor property with an accessor or generic
1265 //           descriptor.
1266 RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
1267   HandleScope scope(isolate);
1268   DCHECK(args.length() == 5);
1269   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1270   RUNTIME_ASSERT(!obj->IsNull());
1271   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1272   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
1273   RUNTIME_ASSERT(IsValidAccessor(getter));
1274   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
1275   RUNTIME_ASSERT(IsValidAccessor(setter));
1276   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
1277
1278   RETURN_FAILURE_ON_EXCEPTION(
1279       isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
1280   return isolate->heap()->undefined_value();
1281 }
1282
1283
1284 // Implements part of 8.12.9 DefineOwnProperty.
1285 // There are 3 cases that lead here:
1286 // Step 4a - define a new data property.
1287 // Steps 9b & 12 - replace an existing accessor property with a data property.
1288 // Step 12 - update an existing data property with a data or generic
1289 //           descriptor.
1290 RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
1291   HandleScope scope(isolate);
1292   DCHECK(args.length() == 4);
1293   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1294   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1295   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1296   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1297
1298   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
1299                                                         LookupIterator::OWN);
1300   if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) {
1301     return isolate->heap()->undefined_value();
1302   }
1303
1304   Handle<Object> result;
1305   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1306       isolate, result, JSObject::DefineOwnPropertyIgnoreAttributes(
1307                            &it, value, attrs, JSObject::DONT_FORCE_FIELD));
1308
1309   return *result;
1310 }
1311
1312
1313 // Return property without being observable by accessors or interceptors.
1314 RUNTIME_FUNCTION(Runtime_GetDataProperty) {
1315   HandleScope scope(isolate);
1316   DCHECK(args.length() == 2);
1317   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
1318   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1319   return *JSReceiver::GetDataProperty(object, name);
1320 }
1321
1322
1323 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
1324   SealHandleScope shs(isolate);
1325   DCHECK(args.length() == 1);
1326   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
1327   return isolate->heap()->ToBoolean(
1328       IsFastPackedElementsKind(obj->map()->elements_kind()));
1329 }
1330
1331
1332 RUNTIME_FUNCTION(Runtime_ValueOf) {
1333   SealHandleScope shs(isolate);
1334   DCHECK(args.length() == 1);
1335   CONVERT_ARG_CHECKED(Object, obj, 0);
1336   if (!obj->IsJSValue()) return obj;
1337   return JSValue::cast(obj)->value();
1338 }
1339
1340
1341 RUNTIME_FUNCTION(Runtime_SetValueOf) {
1342   SealHandleScope shs(isolate);
1343   DCHECK(args.length() == 2);
1344   CONVERT_ARG_CHECKED(Object, obj, 0);
1345   CONVERT_ARG_CHECKED(Object, value, 1);
1346   if (!obj->IsJSValue()) return value;
1347   JSValue::cast(obj)->set_value(value);
1348   return value;
1349 }
1350
1351
1352 RUNTIME_FUNCTION(Runtime_JSValueGetValue) {
1353   SealHandleScope shs(isolate);
1354   DCHECK(args.length() == 1);
1355   CONVERT_ARG_CHECKED(JSValue, obj, 0);
1356   return JSValue::cast(obj)->value();
1357 }
1358
1359
1360 RUNTIME_FUNCTION(Runtime_HeapObjectGetMap) {
1361   SealHandleScope shs(isolate);
1362   DCHECK(args.length() == 1);
1363   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
1364   return obj->map();
1365 }
1366
1367
1368 RUNTIME_FUNCTION(Runtime_MapGetInstanceType) {
1369   SealHandleScope shs(isolate);
1370   DCHECK(args.length() == 1);
1371   CONVERT_ARG_CHECKED(Map, map, 0);
1372   return Smi::FromInt(map->instance_type());
1373 }
1374
1375
1376 RUNTIME_FUNCTION(Runtime_ObjectEquals) {
1377   SealHandleScope shs(isolate);
1378   DCHECK(args.length() == 2);
1379   CONVERT_ARG_CHECKED(Object, obj1, 0);
1380   CONVERT_ARG_CHECKED(Object, obj2, 1);
1381   return isolate->heap()->ToBoolean(obj1 == obj2);
1382 }
1383
1384
1385 RUNTIME_FUNCTION(Runtime_IsObject) {
1386   SealHandleScope shs(isolate);
1387   DCHECK(args.length() == 1);
1388   CONVERT_ARG_CHECKED(Object, obj, 0);
1389   if (!obj->IsHeapObject()) return isolate->heap()->false_value();
1390   if (obj->IsNull()) return isolate->heap()->true_value();
1391   if (obj->IsUndetectableObject()) return isolate->heap()->false_value();
1392   Map* map = HeapObject::cast(obj)->map();
1393   bool is_non_callable_spec_object =
1394       map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
1395       map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE;
1396   return isolate->heap()->ToBoolean(is_non_callable_spec_object);
1397 }
1398
1399
1400 RUNTIME_FUNCTION(Runtime_IsUndetectableObject) {
1401   SealHandleScope shs(isolate);
1402   DCHECK(args.length() == 1);
1403   CONVERT_ARG_CHECKED(Object, obj, 0);
1404   return isolate->heap()->ToBoolean(obj->IsUndetectableObject());
1405 }
1406
1407
1408 RUNTIME_FUNCTION(Runtime_IsSpecObject) {
1409   SealHandleScope shs(isolate);
1410   DCHECK(args.length() == 1);
1411   CONVERT_ARG_CHECKED(Object, obj, 0);
1412   return isolate->heap()->ToBoolean(obj->IsSpecObject());
1413 }
1414
1415
1416 RUNTIME_FUNCTION(Runtime_IsStrong) {
1417   SealHandleScope shs(isolate);
1418   DCHECK(args.length() == 1);
1419   CONVERT_ARG_CHECKED(Object, obj, 0);
1420   return isolate->heap()->ToBoolean(obj->IsJSReceiver() &&
1421                                     JSReceiver::cast(obj)->map()->is_strong());
1422 }
1423
1424
1425 RUNTIME_FUNCTION(Runtime_ClassOf) {
1426   SealHandleScope shs(isolate);
1427   DCHECK(args.length() == 1);
1428   CONVERT_ARG_CHECKED(Object, obj, 0);
1429   if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
1430   return JSReceiver::cast(obj)->class_name();
1431 }
1432
1433
1434 RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
1435   HandleScope scope(isolate);
1436   DCHECK(args.length() == 4);
1437   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1438   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1439   CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
1440   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1441
1442   RETURN_FAILURE_ON_EXCEPTION(
1443       isolate,
1444       JSObject::DefineAccessor(object, name, getter,
1445                                isolate->factory()->null_value(), attrs));
1446   return isolate->heap()->undefined_value();
1447 }
1448
1449
1450 RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
1451   HandleScope scope(isolate);
1452   DCHECK(args.length() == 4);
1453   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1454   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1455   CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
1456   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1457
1458   RETURN_FAILURE_ON_EXCEPTION(
1459       isolate,
1460       JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1461                                setter, attrs));
1462   return isolate->heap()->undefined_value();
1463 }
1464 }  // namespace internal
1465 }  // namespace v8