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/ast/prettyprinter.h"
6 #include "src/common/message-template.h"
7 #include "src/debug/debug.h"
8 #include "src/execution/arguments-inl.h"
9 #include "src/execution/isolate-inl.h"
10 #include "src/execution/messages.h"
11 #include "src/handles/maybe-handles.h"
12 #include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop.
13 #include "src/heap/memory-chunk.h"
14 #include "src/init/bootstrapper.h"
15 #include "src/logging/counters.h"
16 #include "src/objects/hash-table-inl.h"
17 #include "src/objects/js-array-inl.h"
18 #include "src/objects/property-descriptor-object.h"
19 #include "src/objects/property-descriptor.h"
20 #include "src/runtime/runtime-utils.h"
21 #include "src/runtime/runtime.h"
22
23 namespace v8 {
24 namespace internal {
25
GetObjectProperty(Isolate * isolate,Handle<Object> holder,Handle<Object> key,Handle<Object> receiver,bool * is_found)26 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
27 Handle<Object> holder,
28 Handle<Object> key,
29 Handle<Object> receiver,
30 bool* is_found) {
31 if (receiver.is_null()) {
32 receiver = holder;
33 }
34 if (holder->IsNullOrUndefined(isolate)) {
35 ErrorUtils::ThrowLoadFromNullOrUndefined(isolate, holder, key);
36 return MaybeHandle<Object>();
37 }
38
39 bool success = false;
40 LookupIterator::Key lookup_key(isolate, key, &success);
41 if (!success) return MaybeHandle<Object>();
42 LookupIterator it = LookupIterator(isolate, receiver, lookup_key, holder);
43
44 MaybeHandle<Object> result = Object::GetProperty(&it);
45 if (is_found) *is_found = it.IsFound();
46
47 if (!it.IsFound() && key->IsSymbol() &&
48 Symbol::cast(*key).is_private_name()) {
49 Handle<Symbol> sym = Handle<Symbol>::cast(key);
50 Handle<Object> name(sym->description(), isolate);
51 DCHECK(name->IsString());
52 Handle<String> name_string = Handle<String>::cast(name);
53 if (sym->IsPrivateBrand()) {
54 Handle<String> class_name = (name_string->length() == 0)
55 ? isolate->factory()->anonymous_string()
56 : name_string;
57 THROW_NEW_ERROR(isolate,
58 NewTypeError(MessageTemplate::kInvalidPrivateBrand,
59 class_name, holder),
60 Object);
61 }
62 THROW_NEW_ERROR(isolate,
63 NewTypeError(MessageTemplate::kInvalidPrivateMemberRead,
64 name_string, holder),
65 Object);
66 }
67 return result;
68 }
69
HasProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key)70 MaybeHandle<Object> Runtime::HasProperty(Isolate* isolate,
71 Handle<Object> object,
72 Handle<Object> key) {
73 // Check that {object} is actually a receiver.
74 if (!object->IsJSReceiver()) {
75 THROW_NEW_ERROR(
76 isolate,
77 NewTypeError(MessageTemplate::kInvalidInOperatorUse, key, object),
78 Object);
79 }
80 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
81
82 // Convert the {key} to a name.
83 Handle<Name> name;
84 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
85 Object);
86
87 // Lookup the {name} on {receiver}.
88 Maybe<bool> maybe = JSReceiver::HasProperty(receiver, name);
89 if (maybe.IsNothing()) return MaybeHandle<Object>();
90 return maybe.FromJust() ? ReadOnlyRoots(isolate).true_value_handle()
91 : ReadOnlyRoots(isolate).false_value_handle();
92 }
93
94 namespace {
95
DeleteObjectPropertyFast(Isolate * isolate,Handle<JSReceiver> receiver,Handle<Object> raw_key)96 bool DeleteObjectPropertyFast(Isolate* isolate, Handle<JSReceiver> receiver,
97 Handle<Object> raw_key) {
98 // This implements a special case for fast property deletion: when the
99 // last property in an object is deleted, then instead of normalizing
100 // the properties, we can undo the last map transition, with a few
101 // prerequisites:
102 // (1) The receiver must be a regular object and the key a unique name.
103 Handle<Map> receiver_map(receiver->map(), isolate);
104 if (receiver_map->IsSpecialReceiverMap()) return false;
105 if (!raw_key->IsUniqueName()) return false;
106 Handle<Name> key = Handle<Name>::cast(raw_key);
107 // (2) The property to be deleted must be the last property.
108 int nof = receiver_map->NumberOfOwnDescriptors();
109 if (nof == 0) return false;
110 InternalIndex descriptor(nof - 1);
111 Handle<DescriptorArray> descriptors(
112 receiver_map->instance_descriptors(kRelaxedLoad), isolate);
113 if (descriptors->GetKey(descriptor) != *key) return false;
114 // (3) The property to be deleted must be deletable.
115 PropertyDetails details = descriptors->GetDetails(descriptor);
116 if (!details.IsConfigurable()) return false;
117 // (4) The map must have a back pointer.
118 Handle<Object> backpointer(receiver_map->GetBackPointer(), isolate);
119 if (!backpointer->IsMap()) return false;
120 Handle<Map> parent_map = Handle<Map>::cast(backpointer);
121 // (5) The last transition must have been caused by adding a property
122 // (and not any kind of special transition).
123 if (parent_map->NumberOfOwnDescriptors() != nof - 1) return false;
124
125 // Preconditions successful. No more bailouts after this point.
126
127 // If the {descriptor} was "const" so far, we need to update the
128 // {receiver_map} here, otherwise we could get the constants wrong, i.e.
129 //
130 // o.x = 1;
131 // delete o.x;
132 // o.x = 2;
133 //
134 // could trick V8 into thinking that `o.x` is still 1 even after the second
135 // assignment.
136 if (details.constness() == PropertyConstness::kConst &&
137 details.location() == kField) {
138 Handle<FieldType> field_type(descriptors->GetFieldType(descriptor),
139 isolate);
140 Map::GeneralizeField(isolate, receiver_map, descriptor,
141 PropertyConstness::kMutable, details.representation(),
142 field_type);
143 DCHECK_EQ(PropertyConstness::kMutable,
144 descriptors->GetDetails(descriptor).constness());
145 }
146
147 // Zap the property to avoid keeping objects alive. Zapping is not necessary
148 // for properties stored in the descriptor array.
149 if (details.location() == kField) {
150 DisallowHeapAllocation no_allocation;
151
152 // Invalidate slots manually later in case we delete an in-object tagged
153 // property. In this case we might later store an untagged value in the
154 // recorded slot.
155 isolate->heap()->NotifyObjectLayoutChange(*receiver, no_allocation,
156 InvalidateRecordedSlots::kNo);
157 FieldIndex index =
158 FieldIndex::ForPropertyIndex(*receiver_map, details.field_index());
159 // Special case deleting the last out-of object property.
160 if (!index.is_inobject() && index.outobject_array_index() == 0) {
161 DCHECK(!parent_map->HasOutOfObjectProperties());
162 // Clear out the properties backing store.
163 receiver->SetProperties(ReadOnlyRoots(isolate).empty_fixed_array());
164 } else {
165 Object filler = ReadOnlyRoots(isolate).one_pointer_filler_map();
166 JSObject::cast(*receiver).RawFastPropertyAtPut(index, filler);
167 // We must clear any recorded slot for the deleted property, because
168 // subsequent object modifications might put a raw double there.
169 // Slot clearing is the reason why this entire function cannot currently
170 // be implemented in the DeleteProperty stub.
171 if (index.is_inobject() && !receiver_map->IsUnboxedDoubleField(index)) {
172 // We need to clear the recorded slot in this case because in-object
173 // slack tracking might not be finished. This ensures that we don't
174 // have recorded slots in free space.
175 isolate->heap()->ClearRecordedSlot(*receiver,
176 receiver->RawField(index.offset()));
177 MemoryChunk* chunk = MemoryChunk::FromHeapObject(*receiver);
178 chunk->InvalidateRecordedSlots(*receiver);
179 }
180 }
181 }
182 // If the {receiver_map} was marked stable before, then there could be
183 // optimized code that depends on the assumption that no object that
184 // reached this {receiver_map} transitions away from it without triggering
185 // the "deoptimize dependent code" mechanism.
186 receiver_map->NotifyLeafMapLayoutChange(isolate);
187 // Finally, perform the map rollback.
188 receiver->synchronized_set_map(*parent_map);
189 #if VERIFY_HEAP
190 receiver->HeapObjectVerify(isolate);
191 receiver->property_array().PropertyArrayVerify(isolate);
192 #endif
193 return true;
194 }
195
196 } // namespace
197
DeleteObjectProperty(Isolate * isolate,Handle<JSReceiver> receiver,Handle<Object> key,LanguageMode language_mode)198 Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate,
199 Handle<JSReceiver> receiver,
200 Handle<Object> key,
201 LanguageMode language_mode) {
202 if (DeleteObjectPropertyFast(isolate, receiver, key)) return Just(true);
203
204 bool success = false;
205 LookupIterator::Key lookup_key(isolate, key, &success);
206 if (!success) return Nothing<bool>();
207 LookupIterator it(isolate, receiver, lookup_key, LookupIterator::OWN);
208
209 return JSReceiver::DeleteProperty(&it, language_mode);
210 }
211
212 // ES #sec-object.keys
RUNTIME_FUNCTION(Runtime_ObjectKeys)213 RUNTIME_FUNCTION(Runtime_ObjectKeys) {
214 HandleScope scope(isolate);
215 Handle<Object> object = args.at(0);
216
217 // Convert the {object} to a proper {receiver}.
218 Handle<JSReceiver> receiver;
219 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
220 Object::ToObject(isolate, object));
221
222 // Collect the own keys for the {receiver}.
223 Handle<FixedArray> keys;
224 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
225 isolate, keys,
226 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
227 ENUMERABLE_STRINGS,
228 GetKeysConversion::kConvertToString));
229 return *keys;
230 }
231
232 // ES #sec-object.getOwnPropertyNames
RUNTIME_FUNCTION(Runtime_ObjectGetOwnPropertyNames)233 RUNTIME_FUNCTION(Runtime_ObjectGetOwnPropertyNames) {
234 HandleScope scope(isolate);
235 Handle<Object> object = args.at(0);
236
237 // Convert the {object} to a proper {receiver}.
238 Handle<JSReceiver> receiver;
239 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
240 Object::ToObject(isolate, object));
241
242 // Collect the own keys for the {receiver}.
243 // TODO(v8:9401): We should extend the fast path of KeyAccumulator::GetKeys to
244 // also use fast path even when filter = SKIP_SYMBOLS.
245 Handle<FixedArray> keys;
246 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
247 isolate, keys,
248 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
249 SKIP_SYMBOLS,
250 GetKeysConversion::kConvertToString));
251 return *keys;
252 }
253
RUNTIME_FUNCTION(Runtime_ObjectGetOwnPropertyNamesTryFast)254 RUNTIME_FUNCTION(Runtime_ObjectGetOwnPropertyNamesTryFast) {
255 HandleScope scope(isolate);
256 Handle<Object> object = args.at(0);
257
258 // Convert the {object} to a proper {receiver}.
259 Handle<JSReceiver> receiver;
260 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
261 Object::ToObject(isolate, object));
262
263 Handle<Map> map(receiver->map(), isolate);
264
265 int nod = map->NumberOfOwnDescriptors();
266 Handle<FixedArray> keys;
267 if (nod != 0 && map->NumberOfEnumerableProperties() == nod) {
268 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
269 isolate, keys,
270 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
271 ENUMERABLE_STRINGS,
272 GetKeysConversion::kConvertToString));
273 } else {
274 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
275 isolate, keys,
276 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
277 SKIP_SYMBOLS,
278 GetKeysConversion::kConvertToString));
279 }
280
281 return *keys;
282 }
283
284 // ES6 19.1.3.2
RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty)285 RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
286 HandleScope scope(isolate);
287 Handle<Object> property = args.at(1);
288
289 // TODO(ishell): To improve performance, consider performing the to-string
290 // conversion of {property} before calling into the runtime.
291 bool success;
292 LookupIterator::Key key(isolate, property, &success);
293 if (!success) return ReadOnlyRoots(isolate).exception();
294
295 Handle<Object> object = args.at(0);
296
297 if (object->IsJSModuleNamespace()) {
298 if (key.is_element()) {
299 // Namespace objects can't have indexed properties.
300 return ReadOnlyRoots(isolate).false_value();
301 }
302 LookupIterator it(isolate, object, key, LookupIterator::OWN);
303 PropertyDescriptor desc;
304 Maybe<bool> result = JSReceiver::GetOwnPropertyDescriptor(&it, &desc);
305 if (!result.IsJust()) return ReadOnlyRoots(isolate).exception();
306 return isolate->heap()->ToBoolean(result.FromJust());
307
308 } else if (object->IsJSObject()) {
309 Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
310 // Fast case: either the key is a real named property or it is not
311 // an array index and there are no interceptors or hidden
312 // prototypes.
313 // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to
314 // handle all cases directly (without this custom fast path).
315 {
316 LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
317 LookupIterator it(isolate, js_obj, key, js_obj, c);
318 Maybe<bool> maybe = JSReceiver::HasProperty(&it);
319 if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
320 DCHECK(!isolate->has_pending_exception());
321 if (maybe.FromJust()) return ReadOnlyRoots(isolate).true_value();
322 }
323
324 Map map = js_obj->map();
325 if (!map.IsJSGlobalProxyMap() &&
326 (key.is_element() && key.index() <= JSArray::kMaxArrayIndex
327 ? !map.has_indexed_interceptor()
328 : !map.has_named_interceptor())) {
329 return ReadOnlyRoots(isolate).false_value();
330 }
331
332 // Slow case.
333 LookupIterator it(isolate, js_obj, key, js_obj, LookupIterator::OWN);
334 Maybe<bool> maybe = JSReceiver::HasProperty(&it);
335 if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
336 DCHECK(!isolate->has_pending_exception());
337 return isolate->heap()->ToBoolean(maybe.FromJust());
338
339 } else if (object->IsJSProxy()) {
340 LookupIterator it(isolate, object, key, Handle<JSProxy>::cast(object),
341 LookupIterator::OWN);
342 Maybe<PropertyAttributes> attributes =
343 JSReceiver::GetPropertyAttributes(&it);
344 if (attributes.IsNothing()) return ReadOnlyRoots(isolate).exception();
345 return isolate->heap()->ToBoolean(attributes.FromJust() != ABSENT);
346
347 } else if (object->IsString()) {
348 return isolate->heap()->ToBoolean(
349 key.is_element()
350 ? key.index() < static_cast<size_t>(String::cast(*object).length())
351 : key.name()->Equals(ReadOnlyRoots(isolate).length_string()));
352 } else if (object->IsNullOrUndefined(isolate)) {
353 THROW_NEW_ERROR_RETURN_FAILURE(
354 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
355 }
356
357 return ReadOnlyRoots(isolate).false_value();
358 }
359
RUNTIME_FUNCTION(Runtime_AddDictionaryProperty)360 RUNTIME_FUNCTION(Runtime_AddDictionaryProperty) {
361 HandleScope scope(isolate);
362 Handle<JSObject> receiver = args.at<JSObject>(0);
363 Handle<Name> name = args.at<Name>(1);
364 Handle<Object> value = args.at(2);
365
366 DCHECK(name->IsUniqueName());
367
368 Handle<NameDictionary> dictionary(receiver->property_dictionary(), isolate);
369 PropertyDetails property_details(kData, NONE, PropertyCellType::kNoCell);
370 dictionary =
371 NameDictionary::Add(isolate, dictionary, name, value, property_details);
372 receiver->SetProperties(*dictionary);
373 return *value;
374 }
375
376 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
377 // TODO(verwaest): Support the common cases with precached map directly in
378 // an Object.create stub.
RUNTIME_FUNCTION(Runtime_ObjectCreate)379 RUNTIME_FUNCTION(Runtime_ObjectCreate) {
380 HandleScope scope(isolate);
381 Handle<Object> prototype = args.at(0);
382 Handle<Object> properties = args.at(1);
383 Handle<JSObject> obj;
384 // 1. If Type(O) is neither Object nor Null, throw a TypeError exception.
385 if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
386 THROW_NEW_ERROR_RETURN_FAILURE(
387 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
388 }
389 // 2. Let obj be ObjectCreate(O).
390 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
391 isolate, obj, JSObject::ObjectCreate(isolate, prototype));
392
393 // 3. If Properties is not undefined, then
394 if (!properties->IsUndefined(isolate)) {
395 // a. Return ? ObjectDefineProperties(obj, Properties).
396 // Define the properties if properties was specified and is not undefined.
397 RETURN_RESULT_OR_FAILURE(
398 isolate, JSReceiver::DefineProperties(isolate, obj, properties));
399 }
400 // 4. Return obj.
401 return *obj;
402 }
403
SetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,StoreOrigin store_origin,Maybe<ShouldThrow> should_throw)404 MaybeHandle<Object> Runtime::SetObjectProperty(
405 Isolate* isolate, Handle<Object> object, Handle<Object> key,
406 Handle<Object> value, StoreOrigin store_origin,
407 Maybe<ShouldThrow> should_throw) {
408 if (object->IsNullOrUndefined(isolate)) {
409 THROW_NEW_ERROR(
410 isolate,
411 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
412 Object);
413 }
414
415 // Check if the given key is an array index.
416 bool success = false;
417 LookupIterator::Key lookup_key(isolate, key, &success);
418 if (!success) return MaybeHandle<Object>();
419 LookupIterator it(isolate, object, lookup_key);
420
421 if (!it.IsFound() && key->IsSymbol() &&
422 Symbol::cast(*key).is_private_name()) {
423 Handle<Object> name_string(Symbol::cast(*key).description(), isolate);
424 DCHECK(name_string->IsString());
425 THROW_NEW_ERROR(isolate,
426 NewTypeError(MessageTemplate::kInvalidPrivateMemberWrite,
427 name_string, object),
428 Object);
429 }
430
431 MAYBE_RETURN_NULL(
432 Object::SetProperty(&it, value, store_origin, should_throw));
433
434 return value;
435 }
436
RUNTIME_FUNCTION(Runtime_InternalSetPrototype)437 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
438 HandleScope scope(isolate);
439 DCHECK_EQ(2, args.length());
440 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
441 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
442 MAYBE_RETURN(JSReceiver::SetPrototype(obj, prototype, false, kThrowOnError),
443 ReadOnlyRoots(isolate).exception());
444 return *obj;
445 }
446
RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties)447 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
448 HandleScope scope(isolate);
449 DCHECK_EQ(2, args.length());
450 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
451 CONVERT_SMI_ARG_CHECKED(properties, 1);
452 // Conservative upper limit to prevent fuzz tests from going OOM.
453 if (properties > 100000) return isolate->ThrowIllegalOperation();
454 if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
455 JSObject::NormalizeProperties(isolate, object, KEEP_INOBJECT_PROPERTIES,
456 properties, "OptimizeForAdding");
457 }
458 return *object;
459 }
460
RUNTIME_FUNCTION(Runtime_ObjectValues)461 RUNTIME_FUNCTION(Runtime_ObjectValues) {
462 HandleScope scope(isolate);
463 DCHECK_EQ(1, args.length());
464
465 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
466
467 Handle<FixedArray> values;
468 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
469 isolate, values,
470 JSReceiver::GetOwnValues(receiver, PropertyFilter::ENUMERABLE_STRINGS,
471 true));
472 return *isolate->factory()->NewJSArrayWithElements(values);
473 }
474
RUNTIME_FUNCTION(Runtime_ObjectValuesSkipFastPath)475 RUNTIME_FUNCTION(Runtime_ObjectValuesSkipFastPath) {
476 HandleScope scope(isolate);
477 DCHECK_EQ(1, args.length());
478
479 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
480
481 Handle<FixedArray> value;
482 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
483 isolate, value,
484 JSReceiver::GetOwnValues(receiver, PropertyFilter::ENUMERABLE_STRINGS,
485 false));
486 return *isolate->factory()->NewJSArrayWithElements(value);
487 }
488
RUNTIME_FUNCTION(Runtime_ObjectEntries)489 RUNTIME_FUNCTION(Runtime_ObjectEntries) {
490 HandleScope scope(isolate);
491 DCHECK_EQ(1, args.length());
492
493 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
494
495 Handle<FixedArray> entries;
496 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
497 isolate, entries,
498 JSReceiver::GetOwnEntries(receiver, PropertyFilter::ENUMERABLE_STRINGS,
499 true));
500 return *isolate->factory()->NewJSArrayWithElements(entries);
501 }
502
RUNTIME_FUNCTION(Runtime_ObjectEntriesSkipFastPath)503 RUNTIME_FUNCTION(Runtime_ObjectEntriesSkipFastPath) {
504 HandleScope scope(isolate);
505 DCHECK_EQ(1, args.length());
506
507 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
508
509 Handle<FixedArray> entries;
510 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
511 isolate, entries,
512 JSReceiver::GetOwnEntries(receiver, PropertyFilter::ENUMERABLE_STRINGS,
513 false));
514 return *isolate->factory()->NewJSArrayWithElements(entries);
515 }
516
RUNTIME_FUNCTION(Runtime_ObjectIsExtensible)517 RUNTIME_FUNCTION(Runtime_ObjectIsExtensible) {
518 HandleScope scope(isolate);
519 DCHECK_EQ(1, args.length());
520 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
521
522 Maybe<bool> result =
523 object->IsJSReceiver()
524 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
525 : Just(false);
526 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
527 return isolate->heap()->ToBoolean(result.FromJust());
528 }
529
RUNTIME_FUNCTION(Runtime_JSReceiverPreventExtensionsThrow)530 RUNTIME_FUNCTION(Runtime_JSReceiverPreventExtensionsThrow) {
531 HandleScope scope(isolate);
532 DCHECK_EQ(1, args.length());
533 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
534
535 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
536 kThrowOnError),
537 ReadOnlyRoots(isolate).exception());
538 return *object;
539 }
540
RUNTIME_FUNCTION(Runtime_JSReceiverPreventExtensionsDontThrow)541 RUNTIME_FUNCTION(Runtime_JSReceiverPreventExtensionsDontThrow) {
542 HandleScope scope(isolate);
543 DCHECK_EQ(1, args.length());
544 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
545
546 Maybe<bool> result = JSReceiver::PreventExtensions(
547 Handle<JSReceiver>::cast(object), kDontThrow);
548 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
549 return *isolate->factory()->ToBoolean(result.FromJust());
550 }
551
RUNTIME_FUNCTION(Runtime_JSReceiverGetPrototypeOf)552 RUNTIME_FUNCTION(Runtime_JSReceiverGetPrototypeOf) {
553 HandleScope scope(isolate);
554 DCHECK_EQ(1, args.length());
555 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
556
557 RETURN_RESULT_OR_FAILURE(isolate,
558 JSReceiver::GetPrototype(isolate, receiver));
559 }
560
RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfThrow)561 RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfThrow) {
562 HandleScope scope(isolate);
563
564 DCHECK_EQ(2, args.length());
565 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
566 CONVERT_ARG_HANDLE_CHECKED(Object, proto, 1);
567
568 MAYBE_RETURN(JSReceiver::SetPrototype(object, proto, true, kThrowOnError),
569 ReadOnlyRoots(isolate).exception());
570
571 return *object;
572 }
573
RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfDontThrow)574 RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfDontThrow) {
575 HandleScope scope(isolate);
576
577 DCHECK_EQ(2, args.length());
578 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
579 CONVERT_ARG_HANDLE_CHECKED(Object, proto, 1);
580
581 Maybe<bool> result =
582 JSReceiver::SetPrototype(object, proto, true, kDontThrow);
583 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
584 return *isolate->factory()->ToBoolean(result.FromJust());
585 }
586
RUNTIME_FUNCTION(Runtime_GetProperty)587 RUNTIME_FUNCTION(Runtime_GetProperty) {
588 HandleScope scope(isolate);
589 DCHECK(args.length() == 3 || args.length() == 2);
590 CONVERT_ARG_HANDLE_CHECKED(Object, holder_obj, 0);
591 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
592 Handle<Object> receiver_obj = holder_obj;
593 if (args.length() == 3) {
594 CHECK(args[2].IsObject());
595 receiver_obj = args.at<Object>(2);
596 }
597
598 // Fast cases for getting named properties of the holder JSObject
599 // itself.
600 //
601 // The global proxy objects has to be excluded since LookupOwn on
602 // the global proxy object can return a valid result even though the
603 // global proxy object never has properties. This is the case
604 // because the global proxy object forwards everything to its hidden
605 // prototype including own lookups.
606 //
607 // Additionally, we need to make sure that we do not cache results
608 // for objects that require access checks.
609
610 // Convert string-index keys to their number variant to avoid internalization
611 // below; and speed up subsequent conversion to index.
612 uint32_t index;
613 if (key_obj->IsString() && String::cast(*key_obj).AsArrayIndex(&index)) {
614 key_obj = isolate->factory()->NewNumberFromUint(index);
615 }
616 if (holder_obj->IsJSObject()) {
617 if (!holder_obj->IsJSGlobalProxy() && !holder_obj->IsAccessCheckNeeded() &&
618 key_obj->IsName()) {
619 Handle<JSObject> holder = Handle<JSObject>::cast(holder_obj);
620 Handle<Name> key = Handle<Name>::cast(key_obj);
621 key_obj = key = isolate->factory()->InternalizeName(key);
622
623 DisallowHeapAllocation no_allocation;
624 if (holder->IsJSGlobalObject()) {
625 // Attempt dictionary lookup.
626 GlobalDictionary dictionary =
627 JSGlobalObject::cast(*holder).global_dictionary();
628 InternalIndex entry = dictionary.FindEntry(isolate, key);
629 if (entry.is_found()) {
630 PropertyCell cell = dictionary.CellAt(entry);
631 if (cell.property_details().kind() == kData) {
632 Object value = cell.value();
633 if (!value.IsTheHole(isolate)) return value;
634 // If value is the hole (meaning, absent) do the general lookup.
635 }
636 }
637 } else if (!holder->HasFastProperties()) {
638 // Attempt dictionary lookup.
639 NameDictionary dictionary = holder->property_dictionary();
640 InternalIndex entry = dictionary.FindEntry(isolate, key);
641 if ((entry.is_found()) &&
642 (dictionary.DetailsAt(entry).kind() == kData)) {
643 return dictionary.ValueAt(entry);
644 }
645 }
646 } else if (key_obj->IsSmi()) {
647 // JSObject without a name key. If the key is a Smi, check for a
648 // definite out-of-bounds access to elements, which is a strong indicator
649 // that subsequent accesses will also call the runtime. Proactively
650 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
651 // doubles for those future calls in the case that the elements would
652 // become PACKED_DOUBLE_ELEMENTS.
653 Handle<JSObject> js_object = Handle<JSObject>::cast(holder_obj);
654 ElementsKind elements_kind = js_object->GetElementsKind();
655 if (IsDoubleElementsKind(elements_kind)) {
656 if (Smi::ToInt(*key_obj) >= js_object->elements().length()) {
657 elements_kind = IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS
658 : PACKED_ELEMENTS;
659 JSObject::TransitionElementsKind(js_object, elements_kind);
660 }
661 } else {
662 DCHECK(IsSmiOrObjectElementsKind(elements_kind) ||
663 !IsFastElementsKind(elements_kind));
664 }
665 }
666 } else if (holder_obj->IsString() && key_obj->IsSmi()) {
667 // Fast case for string indexing using [] with a smi index.
668 Handle<String> str = Handle<String>::cast(holder_obj);
669 int index = Handle<Smi>::cast(key_obj)->value();
670 if (index >= 0 && index < str->length()) {
671 Factory* factory = isolate->factory();
672 return *factory->LookupSingleCharacterStringFromCode(
673 String::Flatten(isolate, str)->Get(index));
674 }
675 }
676
677 // Fall back to GetObjectProperty.
678 RETURN_RESULT_OR_FAILURE(
679 isolate,
680 Runtime::GetObjectProperty(isolate, holder_obj, key_obj, receiver_obj));
681 }
682
RUNTIME_FUNCTION(Runtime_SetKeyedProperty)683 RUNTIME_FUNCTION(Runtime_SetKeyedProperty) {
684 HandleScope scope(isolate);
685 DCHECK_EQ(3, args.length());
686
687 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
688 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
689 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
690
691 RETURN_RESULT_OR_FAILURE(
692 isolate, Runtime::SetObjectProperty(isolate, object, key, value,
693 StoreOrigin::kMaybeKeyed));
694 }
695
RUNTIME_FUNCTION(Runtime_SetNamedProperty)696 RUNTIME_FUNCTION(Runtime_SetNamedProperty) {
697 HandleScope scope(isolate);
698 DCHECK_EQ(3, args.length());
699
700 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
701 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
702 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
703
704 RETURN_RESULT_OR_FAILURE(
705 isolate, Runtime::SetObjectProperty(isolate, object, key, value,
706 StoreOrigin::kNamed));
707 }
708
709 // Similar to DefineDataPropertyInLiteral, but does not update feedback, and
710 // and does not have a flags parameter for performing SetFunctionName().
711 //
712 // Currently, this is used for ObjectLiteral spread properties.
RUNTIME_FUNCTION(Runtime_StoreDataPropertyInLiteral)713 RUNTIME_FUNCTION(Runtime_StoreDataPropertyInLiteral) {
714 HandleScope scope(isolate);
715 DCHECK_EQ(3, args.length());
716
717 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
718 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
719 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
720
721 LookupIterator::Key lookup_key(isolate, key);
722 LookupIterator it(isolate, object, lookup_key, LookupIterator::OWN);
723
724 Maybe<bool> result = JSObject::DefineOwnPropertyIgnoreAttributes(
725 &it, value, NONE, Just(kDontThrow));
726 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
727 DCHECK(result.IsJust());
728 USE(result);
729
730 return *value;
731 }
732
733 namespace {
734
735 // ES6 section 12.5.4.
DeleteProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,LanguageMode language_mode)736 Object DeleteProperty(Isolate* isolate, Handle<Object> object,
737 Handle<Object> key, LanguageMode language_mode) {
738 Handle<JSReceiver> receiver;
739 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
740 Object::ToObject(isolate, object));
741 Maybe<bool> result =
742 Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode);
743 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
744 return isolate->heap()->ToBoolean(result.FromJust());
745 }
746
747 } // namespace
748
RUNTIME_FUNCTION(Runtime_DeleteProperty)749 RUNTIME_FUNCTION(Runtime_DeleteProperty) {
750 HandleScope scope(isolate);
751 DCHECK_EQ(3, args.length());
752 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
753 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
754 CONVERT_SMI_ARG_CHECKED(language_mode, 2);
755 return DeleteProperty(isolate, object, key,
756 static_cast<LanguageMode>(language_mode));
757 }
758
RUNTIME_FUNCTION(Runtime_ShrinkPropertyDictionary)759 RUNTIME_FUNCTION(Runtime_ShrinkPropertyDictionary) {
760 HandleScope scope(isolate);
761 DCHECK_EQ(1, args.length());
762 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
763 Handle<NameDictionary> dictionary(receiver->property_dictionary(), isolate);
764 Handle<NameDictionary> new_properties =
765 NameDictionary::Shrink(isolate, dictionary);
766 receiver->SetProperties(*new_properties);
767 return Smi::zero();
768 }
769
770 // ES6 section 12.9.3, operator in.
RUNTIME_FUNCTION(Runtime_HasProperty)771 RUNTIME_FUNCTION(Runtime_HasProperty) {
772 HandleScope scope(isolate);
773 DCHECK_EQ(2, args.length());
774 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
775 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
776
777 // Check that {object} is actually a receiver.
778 if (!object->IsJSReceiver()) {
779 THROW_NEW_ERROR_RETURN_FAILURE(
780 isolate,
781 NewTypeError(MessageTemplate::kInvalidInOperatorUse, key, object));
782 }
783 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
784
785 // Convert the {key} to a name.
786 Handle<Name> name;
787 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
788 Object::ToName(isolate, key));
789
790 // Lookup the {name} on {receiver}.
791 Maybe<bool> maybe = JSReceiver::HasProperty(receiver, name);
792 if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
793 return isolate->heap()->ToBoolean(maybe.FromJust());
794 }
795
RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys)796 RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) {
797 HandleScope scope(isolate);
798 DCHECK_EQ(2, args.length());
799 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
800 CONVERT_SMI_ARG_CHECKED(filter_value, 1);
801 PropertyFilter filter = static_cast<PropertyFilter>(filter_value);
802
803 Handle<FixedArray> keys;
804 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
805 isolate, keys,
806 KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, filter,
807 GetKeysConversion::kConvertToString));
808
809 return *isolate->factory()->NewJSArrayWithElements(keys);
810 }
811
RUNTIME_FUNCTION(Runtime_ToFastProperties)812 RUNTIME_FUNCTION(Runtime_ToFastProperties) {
813 HandleScope scope(isolate);
814 DCHECK_EQ(1, args.length());
815 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
816 if (object->IsJSObject() && !object->IsJSGlobalObject()) {
817 JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
818 "RuntimeToFastProperties");
819 }
820 return *object;
821 }
822
RUNTIME_FUNCTION(Runtime_AllocateHeapNumber)823 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
824 HandleScope scope(isolate);
825 DCHECK_EQ(0, args.length());
826 return *isolate->factory()->NewHeapNumber(0);
827 }
828
RUNTIME_FUNCTION(Runtime_NewObject)829 RUNTIME_FUNCTION(Runtime_NewObject) {
830 HandleScope scope(isolate);
831 DCHECK_EQ(2, args.length());
832 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
833 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1);
834 RETURN_RESULT_OR_FAILURE(
835 isolate,
836 JSObject::New(target, new_target, Handle<AllocationSite>::null()));
837 }
838
RUNTIME_FUNCTION(Runtime_GetDerivedMap)839 RUNTIME_FUNCTION(Runtime_GetDerivedMap) {
840 HandleScope scope(isolate);
841 DCHECK_EQ(2, args.length());
842 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
843 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1);
844 RETURN_RESULT_OR_FAILURE(
845 isolate, JSFunction::GetDerivedMap(isolate, target, new_target));
846 }
847
RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTrackingForMap)848 RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTrackingForMap) {
849 DisallowHeapAllocation no_gc;
850 HandleScope scope(isolate);
851 DCHECK_EQ(1, args.length());
852
853 CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0);
854 initial_map->CompleteInobjectSlackTracking(isolate);
855
856 return ReadOnlyRoots(isolate).undefined_value();
857 }
858
RUNTIME_FUNCTION(Runtime_TryMigrateInstance)859 RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
860 HandleScope scope(isolate);
861 DCHECK_EQ(1, args.length());
862 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
863 // It could have been a DCHECK but we call this function directly from tests.
864 if (!js_object->map().is_deprecated()) return Smi::zero();
865 // This call must not cause lazy deopts, because it's called from deferred
866 // code where we can't handle lazy deopts for lack of a suitable bailout
867 // ID. So we just try migration and signal failure if necessary,
868 // which will also trigger a deopt.
869 if (!JSObject::TryMigrateInstance(isolate, js_object)) return Smi::zero();
870 return *js_object;
871 }
872
IsValidAccessor(Isolate * isolate,Handle<Object> obj)873 static bool IsValidAccessor(Isolate* isolate, Handle<Object> obj) {
874 return obj->IsNullOrUndefined(isolate) || obj->IsCallable();
875 }
876
877 // Implements part of 8.12.9 DefineOwnProperty.
878 // There are 3 cases that lead here:
879 // Step 4b - define a new accessor property.
880 // Steps 9c & 12 - replace an existing data property with an accessor property.
881 // Step 12 - update an existing accessor property with an accessor or generic
882 // descriptor.
RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked)883 RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
884 HandleScope scope(isolate);
885 DCHECK_EQ(5, args.length());
886 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
887 CHECK(!obj->IsNull(isolate));
888 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
889 CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
890 CHECK(IsValidAccessor(isolate, getter));
891 CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
892 CHECK(IsValidAccessor(isolate, setter));
893 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
894
895 RETURN_FAILURE_ON_EXCEPTION(
896 isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
897 return ReadOnlyRoots(isolate).undefined_value();
898 }
899
RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral)900 RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
901 HandleScope scope(isolate);
902 DCHECK_EQ(6, args.length());
903 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
904 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
905 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
906 CONVERT_SMI_ARG_CHECKED(flag, 3);
907 CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 4);
908 CONVERT_TAGGED_INDEX_ARG_CHECKED(index, 5);
909
910 if (!maybe_vector->IsUndefined()) {
911 DCHECK(maybe_vector->IsFeedbackVector());
912 Handle<FeedbackVector> vector = Handle<FeedbackVector>::cast(maybe_vector);
913 FeedbackNexus nexus(vector, FeedbackVector::ToSlot(index));
914 if (nexus.ic_state() == UNINITIALIZED) {
915 if (name->IsUniqueName()) {
916 nexus.ConfigureMonomorphic(name, handle(object->map(), isolate),
917 MaybeObjectHandle());
918 } else {
919 nexus.ConfigureMegamorphic(PROPERTY);
920 }
921 } else if (nexus.ic_state() == MONOMORPHIC) {
922 if (nexus.GetFirstMap() != object->map() || nexus.GetName() != *name) {
923 nexus.ConfigureMegamorphic(PROPERTY);
924 }
925 }
926 }
927
928 DataPropertyInLiteralFlags flags(flag);
929 PropertyAttributes attrs = (flags & DataPropertyInLiteralFlag::kDontEnum)
930 ? PropertyAttributes::DONT_ENUM
931 : PropertyAttributes::NONE;
932
933 if (flags & DataPropertyInLiteralFlag::kSetFunctionName) {
934 DCHECK(value->IsJSFunction());
935 Handle<JSFunction> function = Handle<JSFunction>::cast(value);
936 DCHECK(!function->shared().HasSharedName());
937 Handle<Map> function_map(function->map(), isolate);
938 if (!JSFunction::SetName(function, name,
939 isolate->factory()->empty_string())) {
940 return ReadOnlyRoots(isolate).exception();
941 }
942 // Class constructors do not reserve in-object space for name field.
943 CHECK_IMPLIES(!IsClassConstructor(function->shared().kind()),
944 *function_map == function->map());
945 }
946
947 LookupIterator::Key key(isolate, name);
948 LookupIterator it(isolate, object, key, object, LookupIterator::OWN);
949 // Cannot fail since this should only be called when
950 // creating an object literal.
951 CHECK(JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attrs,
952 Just(kDontThrow))
953 .IsJust());
954 return *object;
955 }
956
RUNTIME_FUNCTION(Runtime_CollectTypeProfile)957 RUNTIME_FUNCTION(Runtime_CollectTypeProfile) {
958 HandleScope scope(isolate);
959 DCHECK_EQ(3, args.length());
960 CONVERT_ARG_HANDLE_CHECKED(Smi, position, 0);
961 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
962 CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 2);
963
964 if (maybe_vector->IsUndefined()) {
965 return ReadOnlyRoots(isolate).undefined_value();
966 }
967 CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 2);
968
969 Handle<String> type = Object::TypeOf(isolate, value);
970 if (value->IsJSReceiver()) {
971 Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
972 type = JSReceiver::GetConstructorName(object);
973 } else if (value->IsNull(isolate)) {
974 // typeof(null) is object. But it's more user-friendly to annotate
975 // null as type "null".
976 type = Handle<String>(ReadOnlyRoots(isolate).null_string(), isolate);
977 }
978
979 DCHECK(vector->metadata().HasTypeProfileSlot());
980 FeedbackNexus nexus(vector, vector->GetTypeProfileSlot());
981 nexus.Collect(type, position->value());
982
983 return ReadOnlyRoots(isolate).undefined_value();
984 }
985
RUNTIME_FUNCTION(Runtime_HasFastPackedElements)986 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
987 SealHandleScope shs(isolate);
988 DCHECK_EQ(1, args.length());
989 CONVERT_ARG_CHECKED(HeapObject, obj, 0);
990 return isolate->heap()->ToBoolean(
991 IsFastPackedElementsKind(obj.map().elements_kind()));
992 }
993
RUNTIME_FUNCTION(Runtime_IsJSReceiver)994 RUNTIME_FUNCTION(Runtime_IsJSReceiver) {
995 SealHandleScope shs(isolate);
996 DCHECK_EQ(1, args.length());
997 CONVERT_ARG_CHECKED(Object, obj, 0);
998 return isolate->heap()->ToBoolean(obj.IsJSReceiver());
999 }
1000
RUNTIME_FUNCTION(Runtime_GetFunctionName)1001 RUNTIME_FUNCTION(Runtime_GetFunctionName) {
1002 HandleScope scope(isolate);
1003 DCHECK_EQ(1, args.length());
1004 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1005 return *JSFunction::GetName(isolate, function);
1006 }
1007
RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked)1008 RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
1009 HandleScope scope(isolate);
1010 DCHECK_EQ(4, args.length());
1011 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1012 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1013 CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
1014 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1015
1016 if (String::cast(getter->shared().Name()).length() == 0) {
1017 Handle<Map> getter_map(getter->map(), isolate);
1018 if (!JSFunction::SetName(getter, name, isolate->factory()->get_string())) {
1019 return ReadOnlyRoots(isolate).exception();
1020 }
1021 CHECK_EQ(*getter_map, getter->map());
1022 }
1023
1024 RETURN_FAILURE_ON_EXCEPTION(
1025 isolate,
1026 JSObject::DefineAccessor(object, name, getter,
1027 isolate->factory()->null_value(), attrs));
1028 return ReadOnlyRoots(isolate).undefined_value();
1029 }
1030
RUNTIME_FUNCTION(Runtime_SetDataProperties)1031 RUNTIME_FUNCTION(Runtime_SetDataProperties) {
1032 HandleScope scope(isolate);
1033 DCHECK_EQ(2, args.length());
1034 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0);
1035 CONVERT_ARG_HANDLE_CHECKED(Object, source, 1);
1036
1037 // 2. If source is undefined or null, let keys be an empty List.
1038 if (source->IsUndefined(isolate) || source->IsNull(isolate)) {
1039 return ReadOnlyRoots(isolate).undefined_value();
1040 }
1041
1042 MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(isolate, target, source),
1043 ReadOnlyRoots(isolate).exception());
1044 return ReadOnlyRoots(isolate).undefined_value();
1045 }
1046
RUNTIME_FUNCTION(Runtime_CopyDataProperties)1047 RUNTIME_FUNCTION(Runtime_CopyDataProperties) {
1048 HandleScope scope(isolate);
1049 DCHECK_EQ(2, args.length());
1050 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
1051 CONVERT_ARG_HANDLE_CHECKED(Object, source, 1);
1052
1053 // 2. If source is undefined or null, let keys be an empty List.
1054 if (source->IsUndefined(isolate) || source->IsNull(isolate)) {
1055 return ReadOnlyRoots(isolate).undefined_value();
1056 }
1057
1058 MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(isolate, target, source,
1059 nullptr, false),
1060 ReadOnlyRoots(isolate).exception());
1061 return ReadOnlyRoots(isolate).undefined_value();
1062 }
1063
RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedProperties)1064 RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedProperties) {
1065 HandleScope scope(isolate);
1066 DCHECK_LE(1, args.length());
1067 CONVERT_ARG_HANDLE_CHECKED(Object, source, 0);
1068
1069 // If source is undefined or null, throw a non-coercible error.
1070 if (source->IsNullOrUndefined(isolate)) {
1071 return ErrorUtils::ThrowLoadFromNullOrUndefined(isolate, source,
1072 MaybeHandle<Object>());
1073 }
1074
1075 ScopedVector<Handle<Object>> excluded_properties(args.length() - 1);
1076 for (int i = 1; i < args.length(); i++) {
1077 Handle<Object> property = args.at(i);
1078 uint32_t property_num;
1079 // We convert string to number if possible, in cases of computed
1080 // properties resolving to numbers, which would've been strings
1081 // instead because of our call to %ToName() in the desugaring for
1082 // computed properties.
1083 if (property->IsString() &&
1084 String::cast(*property).AsArrayIndex(&property_num)) {
1085 property = isolate->factory()->NewNumberFromUint(property_num);
1086 }
1087
1088 excluded_properties[i - 1] = property;
1089 }
1090
1091 Handle<JSObject> target =
1092 isolate->factory()->NewJSObject(isolate->object_function());
1093 MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(isolate, target, source,
1094 &excluded_properties, false),
1095 ReadOnlyRoots(isolate).exception());
1096 return *target;
1097 }
1098
RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked)1099 RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
1100 HandleScope scope(isolate);
1101 DCHECK_EQ(4, args.length());
1102 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1103 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1104 CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
1105 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1106
1107 if (String::cast(setter->shared().Name()).length() == 0) {
1108 Handle<Map> setter_map(setter->map(), isolate);
1109 if (!JSFunction::SetName(setter, name, isolate->factory()->set_string())) {
1110 return ReadOnlyRoots(isolate).exception();
1111 }
1112 CHECK_EQ(*setter_map, setter->map());
1113 }
1114
1115 RETURN_FAILURE_ON_EXCEPTION(
1116 isolate,
1117 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1118 setter, attrs));
1119 return ReadOnlyRoots(isolate).undefined_value();
1120 }
1121
RUNTIME_FUNCTION(Runtime_ToObject)1122 RUNTIME_FUNCTION(Runtime_ToObject) {
1123 // Runtime call is implemented in InterpreterIntrinsics and lowered in
1124 // JSIntrinsicLowering.
1125 UNREACHABLE();
1126 }
1127
RUNTIME_FUNCTION(Runtime_ToNumber)1128 RUNTIME_FUNCTION(Runtime_ToNumber) {
1129 HandleScope scope(isolate);
1130 DCHECK_EQ(1, args.length());
1131 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1132 RETURN_RESULT_OR_FAILURE(isolate, Object::ToNumber(isolate, input));
1133 }
1134
RUNTIME_FUNCTION(Runtime_ToNumeric)1135 RUNTIME_FUNCTION(Runtime_ToNumeric) {
1136 HandleScope scope(isolate);
1137 DCHECK_EQ(1, args.length());
1138 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1139 RETURN_RESULT_OR_FAILURE(isolate, Object::ToNumeric(isolate, input));
1140 }
1141
RUNTIME_FUNCTION(Runtime_ToLength)1142 RUNTIME_FUNCTION(Runtime_ToLength) {
1143 HandleScope scope(isolate);
1144 DCHECK_EQ(1, args.length());
1145 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1146 RETURN_RESULT_OR_FAILURE(isolate, Object::ToLength(isolate, input));
1147 }
1148
RUNTIME_FUNCTION(Runtime_ToString)1149 RUNTIME_FUNCTION(Runtime_ToString) {
1150 HandleScope scope(isolate);
1151 DCHECK_EQ(1, args.length());
1152 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1153 RETURN_RESULT_OR_FAILURE(isolate, Object::ToString(isolate, input));
1154 }
1155
RUNTIME_FUNCTION(Runtime_ToName)1156 RUNTIME_FUNCTION(Runtime_ToName) {
1157 HandleScope scope(isolate);
1158 DCHECK_EQ(1, args.length());
1159 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1160 RETURN_RESULT_OR_FAILURE(isolate, Object::ToName(isolate, input));
1161 }
1162
RUNTIME_FUNCTION(Runtime_HasInPrototypeChain)1163 RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
1164 HandleScope scope(isolate);
1165 DCHECK_EQ(2, args.length());
1166 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1167 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1168 if (!object->IsJSReceiver()) return ReadOnlyRoots(isolate).false_value();
1169 Maybe<bool> result = JSReceiver::HasInPrototypeChain(
1170 isolate, Handle<JSReceiver>::cast(object), prototype);
1171 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
1172 return isolate->heap()->ToBoolean(result.FromJust());
1173 }
1174
1175 // ES6 section 7.4.7 CreateIterResultObject ( value, done )
RUNTIME_FUNCTION(Runtime_CreateIterResultObject)1176 RUNTIME_FUNCTION(Runtime_CreateIterResultObject) {
1177 HandleScope scope(isolate);
1178 DCHECK_EQ(2, args.length());
1179 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
1180 CONVERT_ARG_HANDLE_CHECKED(Object, done, 1);
1181 return *isolate->factory()->NewJSIteratorResult(value,
1182 done->BooleanValue(isolate));
1183 }
1184
RUNTIME_FUNCTION(Runtime_CreateDataProperty)1185 RUNTIME_FUNCTION(Runtime_CreateDataProperty) {
1186 HandleScope scope(isolate);
1187 DCHECK_EQ(3, args.length());
1188 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, o, 0);
1189 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1190 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1191 bool success;
1192 LookupIterator::Key lookup_key(isolate, key, &success);
1193 if (!success) return ReadOnlyRoots(isolate).exception();
1194 LookupIterator it(isolate, o, lookup_key, LookupIterator::OWN);
1195 MAYBE_RETURN(JSReceiver::CreateDataProperty(&it, value, Just(kThrowOnError)),
1196 ReadOnlyRoots(isolate).exception());
1197 return *value;
1198 }
1199
RUNTIME_FUNCTION(Runtime_SetOwnPropertyIgnoreAttributes)1200 RUNTIME_FUNCTION(Runtime_SetOwnPropertyIgnoreAttributes) {
1201 HandleScope scope(isolate);
1202 DCHECK_EQ(4, args.length());
1203 CONVERT_ARG_HANDLE_CHECKED(JSObject, o, 0);
1204 CONVERT_ARG_HANDLE_CHECKED(String, key, 1);
1205 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1206 CONVERT_ARG_HANDLE_CHECKED(Smi, attributes, 3);
1207
1208 RETURN_RESULT_OR_FAILURE(
1209 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
1210 o, key, value, PropertyAttributes(attributes->value())));
1211 }
1212
RUNTIME_FUNCTION(Runtime_GetOwnPropertyDescriptor)1213 RUNTIME_FUNCTION(Runtime_GetOwnPropertyDescriptor) {
1214 HandleScope scope(isolate);
1215
1216 DCHECK_EQ(2, args.length());
1217 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
1218 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1219
1220 PropertyDescriptor desc;
1221 Maybe<bool> found =
1222 JSReceiver::GetOwnPropertyDescriptor(isolate, object, name, &desc);
1223 MAYBE_RETURN(found, ReadOnlyRoots(isolate).exception());
1224
1225 if (!found.FromJust()) return ReadOnlyRoots(isolate).undefined_value();
1226 return *desc.ToPropertyDescriptorObject(isolate);
1227 }
1228
RUNTIME_FUNCTION(Runtime_LoadPrivateSetter)1229 RUNTIME_FUNCTION(Runtime_LoadPrivateSetter) {
1230 HandleScope scope(isolate);
1231 DCHECK_EQ(args.length(), 1);
1232 CONVERT_ARG_HANDLE_CHECKED(AccessorPair, pair, 0);
1233 DCHECK(pair->setter().IsJSFunction());
1234 return pair->setter();
1235 }
1236
RUNTIME_FUNCTION(Runtime_LoadPrivateGetter)1237 RUNTIME_FUNCTION(Runtime_LoadPrivateGetter) {
1238 HandleScope scope(isolate);
1239 DCHECK_EQ(args.length(), 1);
1240 CONVERT_ARG_HANDLE_CHECKED(AccessorPair, pair, 0);
1241 DCHECK(pair->getter().IsJSFunction());
1242 return pair->getter();
1243 }
1244
RUNTIME_FUNCTION(Runtime_CreatePrivateAccessors)1245 RUNTIME_FUNCTION(Runtime_CreatePrivateAccessors) {
1246 HandleScope scope(isolate);
1247 DCHECK_EQ(args.length(), 2);
1248 DCHECK(args[0].IsNull() || args[0].IsJSFunction());
1249 DCHECK(args[1].IsNull() || args[1].IsJSFunction());
1250 Handle<AccessorPair> pair = isolate->factory()->NewAccessorPair();
1251 pair->SetComponents(args[0], args[1]);
1252 return *pair;
1253 }
1254
RUNTIME_FUNCTION(Runtime_AddPrivateBrand)1255 RUNTIME_FUNCTION(Runtime_AddPrivateBrand) {
1256 HandleScope scope(isolate);
1257 DCHECK_EQ(args.length(), 3);
1258 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
1259 CONVERT_ARG_HANDLE_CHECKED(Symbol, brand, 1);
1260 CONVERT_ARG_HANDLE_CHECKED(Context, context, 2);
1261 DCHECK(brand->is_private_name());
1262
1263 LookupIterator it(isolate, receiver, brand, LookupIterator::OWN);
1264
1265 if (it.IsFound()) {
1266 THROW_NEW_ERROR_RETURN_FAILURE(
1267 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, brand));
1268 }
1269
1270 PropertyAttributes attributes =
1271 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
1272 CHECK(Object::AddDataProperty(&it, context, attributes, Just(kDontThrow),
1273 StoreOrigin::kMaybeKeyed)
1274 .FromJust());
1275 return *receiver;
1276 }
1277
RUNTIME_FUNCTION(Runtime_AddPrivateField)1278 RUNTIME_FUNCTION(Runtime_AddPrivateField) {
1279 HandleScope scope(isolate);
1280 DCHECK_EQ(3, args.length());
1281 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, o, 0);
1282 CONVERT_ARG_HANDLE_CHECKED(Symbol, key, 1);
1283 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1284 DCHECK(key->is_private_name());
1285
1286 LookupIterator it(isolate, o, key, LookupIterator::OWN);
1287
1288 if (it.IsFound()) {
1289 THROW_NEW_ERROR_RETURN_FAILURE(
1290 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, key));
1291 }
1292
1293 CHECK(Object::AddDataProperty(&it, value, NONE, Just(kDontThrow),
1294 StoreOrigin::kMaybeKeyed)
1295 .FromJust());
1296 return ReadOnlyRoots(isolate).undefined_value();
1297 }
1298
1299 } // namespace internal
1300 } // namespace v8
1301