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