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