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/base/macros.h"
7 #include "src/builtins/builtins.h"
8 #include "src/common/globals.h"
9 #include "src/common/message-template.h"
10 #include "src/debug/debug.h"
11 #include "src/execution/arguments-inl.h"
12 #include "src/execution/frames.h"
13 #include "src/execution/isolate-inl.h"
14 #include "src/execution/messages.h"
15 #include "src/handles/maybe-handles.h"
16 #include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop.
17 #include "src/heap/memory-chunk.h"
18 #include "src/init/bootstrapper.h"
19 #include "src/logging/counters.h"
20 #include "src/objects/hash-table-inl.h"
21 #include "src/objects/js-array-inl.h"
22 #include "src/objects/map-updater.h"
23 #include "src/objects/property-descriptor-object.h"
24 #include "src/objects/property-descriptor.h"
25 #include "src/objects/property-details.h"
26 #include "src/objects/swiss-name-dictionary-inl.h"
27 #include "src/runtime/runtime-utils.h"
28 #include "src/runtime/runtime.h"
29
30 namespace v8 {
31 namespace internal {
32
GetObjectProperty(Isolate * isolate,Handle<Object> lookup_start_object,Handle<Object> key,Handle<Object> receiver,bool * is_found)33 MaybeHandle<Object> Runtime::GetObjectProperty(
34 Isolate* isolate, Handle<Object> lookup_start_object, Handle<Object> key,
35 Handle<Object> receiver, bool* is_found) {
36 if (receiver.is_null()) {
37 receiver = lookup_start_object;
38 }
39 if (lookup_start_object->IsNullOrUndefined(isolate)) {
40 ErrorUtils::ThrowLoadFromNullOrUndefined(isolate, lookup_start_object, key);
41 return MaybeHandle<Object>();
42 }
43
44 bool success = false;
45 PropertyKey lookup_key(isolate, key, &success);
46 if (!success) return MaybeHandle<Object>();
47 LookupIterator it =
48 LookupIterator(isolate, receiver, lookup_key, lookup_start_object);
49
50 MaybeHandle<Object> result = Object::GetProperty(&it);
51 if (result.is_null()) {
52 return result;
53 }
54 if (is_found) *is_found = it.IsFound();
55
56 if (!it.IsFound() && key->IsSymbol() &&
57 Symbol::cast(*key).is_private_name()) {
58 MessageTemplate message =
59 Symbol::cast(*key).IsPrivateBrand()
60 ? MessageTemplate::kInvalidPrivateBrandInstance
61 : MessageTemplate::kInvalidPrivateMemberRead;
62 THROW_NEW_ERROR(isolate, NewTypeError(message, key, lookup_start_object),
63 Object);
64 }
65 return result;
66 }
67
HasProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key)68 MaybeHandle<Object> Runtime::HasProperty(Isolate* isolate,
69 Handle<Object> object,
70 Handle<Object> key) {
71 // Check that {object} is actually a receiver.
72 if (!object->IsJSReceiver()) {
73 THROW_NEW_ERROR(
74 isolate,
75 NewTypeError(MessageTemplate::kInvalidInOperatorUse, key, object),
76 Object);
77 }
78 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
79
80 // Convert the {key} to a name.
81 Handle<Name> name;
82 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
83 Object);
84
85 // Lookup the {name} on {receiver}.
86 Maybe<bool> maybe = JSReceiver::HasProperty(isolate, receiver, name);
87 if (maybe.IsNothing()) return MaybeHandle<Object>();
88 return maybe.FromJust() ? ReadOnlyRoots(isolate).true_value_handle()
89 : ReadOnlyRoots(isolate).false_value_handle();
90 }
91
92 namespace {
93
94 // This function sets the sentinel value in a deleted field. Thes sentinel has
95 // to look like a proper standalone object because the slack tracking may
96 // complete at any time. For this reason we use the filler map word.
97 // If V8_MAP_PACKING is enabled, then the filler map word is a packed filler
98 // map. Otherwise, the filler map word is the same as the filler map.
ClearField(Isolate * isolate,JSObject object,FieldIndex index)99 inline void ClearField(Isolate* isolate, JSObject object, FieldIndex index) {
100 if (index.is_inobject()) {
101 MapWord filler_map_word =
102 ReadOnlyRoots(isolate).one_pointer_filler_map_word();
103 #ifndef V8_MAP_PACKING
104 DCHECK_EQ(filler_map_word.ToMap(),
105 ReadOnlyRoots(isolate).one_pointer_filler_map());
106 #endif
107 int offset = index.offset();
108 TaggedField<MapWord>::Release_Store(object, offset, filler_map_word);
109 } else {
110 object.property_array().set(
111 index.outobject_array_index(),
112 ReadOnlyRoots(isolate).one_pointer_filler_map());
113 }
114 }
115
GeneralizeAllTransitionsToFieldAsMutable(Isolate * isolate,Handle<Map> map,Handle<Name> name)116 void GeneralizeAllTransitionsToFieldAsMutable(Isolate* isolate, Handle<Map> map,
117 Handle<Name> name) {
118 InternalIndex descriptor(map->NumberOfOwnDescriptors());
119
120 Handle<Map> target_maps[kPropertyAttributesCombinationsCount];
121 int target_maps_count = 0;
122
123 // Collect all outgoing field transitions.
124 {
125 DisallowGarbageCollection no_gc;
126 TransitionsAccessor transitions(isolate, *map);
127 transitions.ForEachTransitionTo(
128 *name,
129 [&](Map target) {
130 DCHECK_EQ(descriptor, target.LastAdded());
131 DCHECK_EQ(*name, target.GetLastDescriptorName(isolate));
132 PropertyDetails details = target.GetLastDescriptorDetails(isolate);
133 // Currently, we track constness only for fields.
134 if (details.kind() == PropertyKind::kData &&
135 details.constness() == PropertyConstness::kConst) {
136 target_maps[target_maps_count++] = handle(target, isolate);
137 }
138 DCHECK_IMPLIES(details.kind() == PropertyKind::kAccessor,
139 details.constness() == PropertyConstness::kConst);
140 },
141 &no_gc);
142 CHECK_LE(target_maps_count, kPropertyAttributesCombinationsCount);
143 }
144
145 for (int i = 0; i < target_maps_count; i++) {
146 Handle<Map> target = target_maps[i];
147 PropertyDetails details =
148 target->instance_descriptors(isolate).GetDetails(descriptor);
149 Handle<FieldType> field_type(
150 target->instance_descriptors(isolate).GetFieldType(descriptor),
151 isolate);
152 MapUpdater::GeneralizeField(isolate, target, descriptor,
153 PropertyConstness::kMutable,
154 details.representation(), field_type);
155 DCHECK_EQ(PropertyConstness::kMutable, target->instance_descriptors(isolate)
156 .GetDetails(descriptor)
157 .constness());
158 }
159 }
160
DeleteObjectPropertyFast(Isolate * isolate,Handle<JSReceiver> receiver,Handle<Object> raw_key)161 bool DeleteObjectPropertyFast(Isolate* isolate, Handle<JSReceiver> receiver,
162 Handle<Object> raw_key) {
163 // This implements a special case for fast property deletion: when the
164 // last property in an object is deleted, then instead of normalizing
165 // the properties, we can undo the last map transition, with a few
166 // prerequisites:
167 // (1) The receiver must be a regular object and the key a unique name.
168 Handle<Map> receiver_map(receiver->map(), isolate);
169 if (receiver_map->IsSpecialReceiverMap()) return false;
170 DCHECK(receiver_map->IsJSObjectMap());
171
172 if (!raw_key->IsUniqueName()) return false;
173 Handle<Name> key = Handle<Name>::cast(raw_key);
174 // (2) The property to be deleted must be the last property.
175 int nof = receiver_map->NumberOfOwnDescriptors();
176 if (nof == 0) return false;
177 InternalIndex descriptor(nof - 1);
178 Handle<DescriptorArray> descriptors(
179 receiver_map->instance_descriptors(isolate), isolate);
180 if (descriptors->GetKey(descriptor) != *key) return false;
181 // (3) The property to be deleted must be deletable.
182 PropertyDetails details = descriptors->GetDetails(descriptor);
183 if (!details.IsConfigurable()) return false;
184 // (4) The map must have a back pointer.
185 Handle<Object> backpointer(receiver_map->GetBackPointer(), isolate);
186 if (!backpointer->IsMap()) return false;
187 Handle<Map> parent_map = Handle<Map>::cast(backpointer);
188 // (5) The last transition must have been caused by adding a property
189 // (and not any kind of special transition).
190 if (parent_map->NumberOfOwnDescriptors() != nof - 1) return false;
191
192 // Preconditions successful. No more bailouts after this point.
193
194 // Zap the property to avoid keeping objects alive. Zapping is not necessary
195 // for properties stored in the descriptor array.
196 if (details.location() == PropertyLocation::kField) {
197 DisallowGarbageCollection no_gc;
198
199 // Invalidate slots manually later in case we delete an in-object tagged
200 // property. In this case we might later store an untagged value in the
201 // recorded slot.
202 isolate->heap()->NotifyObjectLayoutChange(*receiver, no_gc,
203 InvalidateRecordedSlots::kNo);
204 FieldIndex index =
205 FieldIndex::ForPropertyIndex(*receiver_map, details.field_index());
206 // Special case deleting the last out-of object property.
207 if (!index.is_inobject() && index.outobject_array_index() == 0) {
208 DCHECK(!parent_map->HasOutOfObjectProperties());
209 // Clear out the properties backing store.
210 receiver->SetProperties(ReadOnlyRoots(isolate).empty_fixed_array());
211 } else {
212 ClearField(isolate, JSObject::cast(*receiver), index);
213 // We must clear any recorded slot for the deleted property, because
214 // subsequent object modifications might put a raw double there.
215 // Slot clearing is the reason why this entire function cannot currently
216 // be implemented in the DeleteProperty stub.
217 if (index.is_inobject()) {
218 // We need to clear the recorded slot in this case because in-object
219 // slack tracking might not be finished. This ensures that we don't
220 // have recorded slots in free space.
221 isolate->heap()->ClearRecordedSlot(*receiver,
222 receiver->RawField(index.offset()));
223 if (!FLAG_enable_third_party_heap) {
224 MemoryChunk* chunk = MemoryChunk::FromHeapObject(*receiver);
225 chunk->InvalidateRecordedSlots(*receiver);
226 }
227 }
228 }
229 }
230 // If the {receiver_map} was marked stable before, then there could be
231 // optimized code that depends on the assumption that no object that
232 // reached this {receiver_map} transitions away from it without triggering
233 // the "deoptimize dependent code" mechanism.
234 receiver_map->NotifyLeafMapLayoutChange(isolate);
235 // Finally, perform the map rollback.
236 receiver->set_map(*parent_map, kReleaseStore);
237 #if VERIFY_HEAP
238 receiver->HeapObjectVerify(isolate);
239 receiver->property_array().PropertyArrayVerify(isolate);
240 #endif
241
242 // If the {descriptor} was "const" so far, we need to update the
243 // {receiver_map} here, otherwise we could get the constants wrong, i.e.
244 //
245 // o.x = 1;
246 // [change o.x's attributes or reconfigure property kind]
247 // delete o.x;
248 // o.x = 2;
249 //
250 // could trick V8 into thinking that `o.x` is still 1 even after the second
251 // assignment.
252
253 // Step 1: Migrate object to an up-to-date shape.
254 if (parent_map->is_deprecated()) {
255 JSObject::MigrateInstance(isolate, Handle<JSObject>::cast(receiver));
256 parent_map = handle(receiver->map(), isolate);
257 }
258
259 // Step 2: Mark outgoing transitions from the up-to-date version of the
260 // parent_map to same property name of any kind or attributes as mutable.
261 // Also migrate object to the up-to-date map to make the object shapes
262 // converge sooner.
263 GeneralizeAllTransitionsToFieldAsMutable(isolate, parent_map, key);
264
265 return true;
266 }
267
268 } // namespace
269
DeleteObjectProperty(Isolate * isolate,Handle<JSReceiver> receiver,Handle<Object> key,LanguageMode language_mode)270 Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate,
271 Handle<JSReceiver> receiver,
272 Handle<Object> key,
273 LanguageMode language_mode) {
274 if (DeleteObjectPropertyFast(isolate, receiver, key)) return Just(true);
275
276 bool success = false;
277 PropertyKey lookup_key(isolate, key, &success);
278 if (!success) return Nothing<bool>();
279 LookupIterator it(isolate, receiver, lookup_key, LookupIterator::OWN);
280
281 return JSReceiver::DeleteProperty(&it, language_mode);
282 }
283
284 // ES #sec-object.keys
RUNTIME_FUNCTION(Runtime_ObjectKeys)285 RUNTIME_FUNCTION(Runtime_ObjectKeys) {
286 HandleScope scope(isolate);
287 Handle<Object> object = args.at(0);
288
289 // Convert the {object} to a proper {receiver}.
290 Handle<JSReceiver> receiver;
291 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
292 Object::ToObject(isolate, object));
293
294 // Collect the own keys for the {receiver}.
295 Handle<FixedArray> keys;
296 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
297 isolate, keys,
298 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
299 ENUMERABLE_STRINGS,
300 GetKeysConversion::kConvertToString));
301 return *keys;
302 }
303
304 // ES #sec-object.getOwnPropertyNames
RUNTIME_FUNCTION(Runtime_ObjectGetOwnPropertyNames)305 RUNTIME_FUNCTION(Runtime_ObjectGetOwnPropertyNames) {
306 HandleScope scope(isolate);
307 Handle<Object> object = args.at(0);
308
309 // Convert the {object} to a proper {receiver}.
310 Handle<JSReceiver> receiver;
311 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
312 Object::ToObject(isolate, object));
313
314 // Collect the own keys for the {receiver}.
315 // TODO(v8:9401): We should extend the fast path of KeyAccumulator::GetKeys to
316 // also use fast path even when filter = SKIP_SYMBOLS.
317 Handle<FixedArray> keys;
318 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
319 isolate, keys,
320 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
321 SKIP_SYMBOLS,
322 GetKeysConversion::kConvertToString));
323 return *keys;
324 }
325
RUNTIME_FUNCTION(Runtime_ObjectGetOwnPropertyNamesTryFast)326 RUNTIME_FUNCTION(Runtime_ObjectGetOwnPropertyNamesTryFast) {
327 HandleScope scope(isolate);
328 Handle<Object> object = args.at(0);
329
330 // Convert the {object} to a proper {receiver}.
331 Handle<JSReceiver> receiver;
332 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
333 Object::ToObject(isolate, object));
334
335 Handle<Map> map(receiver->map(), isolate);
336
337 int nod = map->NumberOfOwnDescriptors();
338 Handle<FixedArray> keys;
339 if (nod != 0 && map->NumberOfEnumerableProperties() == nod) {
340 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
341 isolate, keys,
342 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
343 ENUMERABLE_STRINGS,
344 GetKeysConversion::kConvertToString));
345 } else {
346 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
347 isolate, keys,
348 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
349 SKIP_SYMBOLS,
350 GetKeysConversion::kConvertToString));
351 }
352
353 return *keys;
354 }
355
356 // ES6 19.1.3.2
RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty)357 RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
358 HandleScope scope(isolate);
359 Handle<Object> property = args.at(1);
360
361 // TODO(ishell): To improve performance, consider performing the to-string
362 // conversion of {property} before calling into the runtime.
363 bool success;
364 PropertyKey key(isolate, property, &success);
365 if (!success) return ReadOnlyRoots(isolate).exception();
366
367 Handle<Object> object = args.at(0);
368
369 if (object->IsJSModuleNamespace()) {
370 LookupIterator it(isolate, object, key, LookupIterator::OWN);
371 PropertyDescriptor desc;
372 Maybe<bool> result = JSReceiver::GetOwnPropertyDescriptor(&it, &desc);
373 if (!result.IsJust()) return ReadOnlyRoots(isolate).exception();
374 return isolate->heap()->ToBoolean(result.FromJust());
375
376 } else if (object->IsJSObject()) {
377 Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
378 // Fast case: either the key is a real named property or it is not
379 // an array index and there are no interceptors or hidden
380 // prototypes.
381 // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to
382 // handle all cases directly (without this custom fast path).
383 {
384 LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
385 LookupIterator it(isolate, js_obj, key, js_obj, c);
386 Maybe<bool> maybe = JSReceiver::HasProperty(&it);
387 if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
388 DCHECK(!isolate->has_pending_exception());
389 if (maybe.FromJust()) return ReadOnlyRoots(isolate).true_value();
390 }
391
392 Map map = js_obj->map();
393 if (!map.IsJSGlobalProxyMap() &&
394 (key.is_element() && key.index() <= JSObject::kMaxElementIndex
395 ? !map.has_indexed_interceptor()
396 : !map.has_named_interceptor())) {
397 return ReadOnlyRoots(isolate).false_value();
398 }
399
400 // Slow case.
401 LookupIterator it(isolate, js_obj, key, js_obj, LookupIterator::OWN);
402 Maybe<bool> maybe = JSReceiver::HasProperty(&it);
403 if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
404 DCHECK(!isolate->has_pending_exception());
405 return isolate->heap()->ToBoolean(maybe.FromJust());
406
407 } else if (object->IsJSProxy()) {
408 LookupIterator it(isolate, object, key, Handle<JSProxy>::cast(object),
409 LookupIterator::OWN);
410 Maybe<PropertyAttributes> attributes =
411 JSReceiver::GetPropertyAttributes(&it);
412 if (attributes.IsNothing()) return ReadOnlyRoots(isolate).exception();
413 return isolate->heap()->ToBoolean(attributes.FromJust() != ABSENT);
414
415 } else if (object->IsString()) {
416 return isolate->heap()->ToBoolean(
417 key.is_element()
418 ? key.index() < static_cast<size_t>(String::cast(*object).length())
419 : key.name()->Equals(ReadOnlyRoots(isolate).length_string()));
420 } else if (object->IsNullOrUndefined(isolate)) {
421 THROW_NEW_ERROR_RETURN_FAILURE(
422 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
423 }
424
425 return ReadOnlyRoots(isolate).false_value();
426 }
427
RUNTIME_FUNCTION(Runtime_HasOwnConstDataProperty)428 RUNTIME_FUNCTION(Runtime_HasOwnConstDataProperty) {
429 HandleScope scope(isolate);
430 DCHECK_EQ(2, args.length());
431 Handle<Object> object = args.at(0);
432 Handle<Object> property = args.at(1);
433
434 bool success;
435 PropertyKey key(isolate, property, &success);
436 if (!success) return ReadOnlyRoots(isolate).undefined_value();
437
438 if (object->IsJSObject()) {
439 Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
440 LookupIterator it(isolate, js_obj, key, js_obj, LookupIterator::OWN);
441
442 switch (it.state()) {
443 case LookupIterator::NOT_FOUND:
444 return isolate->heap()->ToBoolean(false);
445 case LookupIterator::DATA:
446 return isolate->heap()->ToBoolean(it.constness() ==
447 PropertyConstness::kConst);
448 default:
449 return ReadOnlyRoots(isolate).undefined_value();
450 }
451 }
452
453 return ReadOnlyRoots(isolate).undefined_value();
454 }
455
RUNTIME_FUNCTION(Runtime_IsDictPropertyConstTrackingEnabled)456 RUNTIME_FUNCTION(Runtime_IsDictPropertyConstTrackingEnabled) {
457 return isolate->heap()->ToBoolean(V8_DICT_PROPERTY_CONST_TRACKING_BOOL);
458 }
459
RUNTIME_FUNCTION(Runtime_AddDictionaryProperty)460 RUNTIME_FUNCTION(Runtime_AddDictionaryProperty) {
461 HandleScope scope(isolate);
462 Handle<JSObject> receiver = args.at<JSObject>(0);
463 Handle<Name> name = args.at<Name>(1);
464 Handle<Object> value = args.at(2);
465
466 DCHECK(name->IsUniqueName());
467
468 PropertyDetails property_details(
469 PropertyKind::kData, NONE,
470 PropertyDetails::kConstIfDictConstnessTracking);
471 if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
472 Handle<SwissNameDictionary> dictionary(
473 receiver->property_dictionary_swiss(), isolate);
474 dictionary = SwissNameDictionary::Add(isolate, dictionary, name, value,
475 property_details);
476 receiver->SetProperties(*dictionary);
477 } else {
478 Handle<NameDictionary> dictionary(receiver->property_dictionary(), isolate);
479 dictionary =
480 NameDictionary::Add(isolate, dictionary, name, value, property_details);
481 receiver->SetProperties(*dictionary);
482 }
483
484 return *value;
485 }
486
RUNTIME_FUNCTION(Runtime_AddPrivateBrand)487 RUNTIME_FUNCTION(Runtime_AddPrivateBrand) {
488 HandleScope scope(isolate);
489 DCHECK_EQ(args.length(), 4);
490 Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
491 Handle<Symbol> brand = args.at<Symbol>(1);
492 Handle<Context> context = args.at<Context>(2);
493 int depth = args.smi_value_at(3);
494 DCHECK(brand->is_private_name());
495
496 LookupIterator it(isolate, receiver, brand, LookupIterator::OWN);
497
498 if (it.IsFound()) {
499 THROW_NEW_ERROR_RETURN_FAILURE(
500 isolate,
501 NewTypeError(MessageTemplate::kInvalidPrivateBrandReinitialization,
502 brand));
503 }
504
505 PropertyAttributes attributes =
506 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
507
508 // Look for the context in |depth| in the context chain to store it
509 // in the instance with the brand variable as key, which is needed by
510 // the debugger for retrieving names of private methods.
511 DCHECK_GE(depth, 0);
512 for (; depth > 0; depth--) {
513 context =
514 handle(Context::cast(context->get(Context::PREVIOUS_INDEX)), isolate);
515 }
516 DCHECK_EQ(context->scope_info().scope_type(), ScopeType::CLASS_SCOPE);
517 CHECK(Object::AddDataProperty(&it, context, attributes, Just(kDontThrow),
518 StoreOrigin::kMaybeKeyed)
519 .FromJust());
520 return *receiver;
521 }
522
523 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
524 // TODO(verwaest): Support the common cases with precached map directly in
525 // an Object.create stub.
RUNTIME_FUNCTION(Runtime_ObjectCreate)526 RUNTIME_FUNCTION(Runtime_ObjectCreate) {
527 HandleScope scope(isolate);
528 Handle<Object> prototype = args.at(0);
529 Handle<Object> properties = args.at(1);
530 Handle<JSObject> obj;
531 // 1. If Type(O) is neither Object nor Null, throw a TypeError exception.
532 if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
533 THROW_NEW_ERROR_RETURN_FAILURE(
534 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
535 }
536 // 2. Let obj be ObjectCreate(O).
537 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
538 isolate, obj, JSObject::ObjectCreate(isolate, prototype));
539
540 // 3. If Properties is not undefined, then
541 if (!properties->IsUndefined(isolate)) {
542 // a. Return ? ObjectDefineProperties(obj, Properties).
543 // Define the properties if properties was specified and is not undefined.
544 RETURN_RESULT_OR_FAILURE(
545 isolate, JSReceiver::DefineProperties(isolate, obj, properties));
546 }
547 // 4. Return obj.
548 return *obj;
549 }
550
SetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,StoreOrigin store_origin,Maybe<ShouldThrow> should_throw)551 MaybeHandle<Object> Runtime::SetObjectProperty(
552 Isolate* isolate, Handle<Object> object, Handle<Object> key,
553 Handle<Object> value, StoreOrigin store_origin,
554 Maybe<ShouldThrow> should_throw) {
555 if (object->IsNullOrUndefined(isolate)) {
556 MaybeHandle<String> maybe_property =
557 Object::NoSideEffectsToMaybeString(isolate, key);
558 Handle<String> property_name;
559 if (maybe_property.ToHandle(&property_name)) {
560 THROW_NEW_ERROR(
561 isolate,
562 NewTypeError(MessageTemplate::kNonObjectPropertyStoreWithProperty,
563 object, property_name),
564 Object);
565 } else {
566 THROW_NEW_ERROR(
567 isolate,
568 NewTypeError(MessageTemplate::kNonObjectPropertyStore, object),
569 Object);
570 }
571 }
572
573 // Check if the given key is an array index.
574 bool success = false;
575 PropertyKey lookup_key(isolate, key, &success);
576 if (!success) return MaybeHandle<Object>();
577 LookupIterator it(isolate, object, lookup_key);
578 if (key->IsSymbol() && Symbol::cast(*key).is_private_name() &&
579 !JSReceiver::CheckPrivateNameStore(&it, false)) {
580 return MaybeHandle<Object>();
581 }
582
583 MAYBE_RETURN_NULL(
584 Object::SetProperty(&it, value, store_origin, should_throw));
585
586 return value;
587 }
588
DefineObjectOwnProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,StoreOrigin store_origin)589 MaybeHandle<Object> Runtime::DefineObjectOwnProperty(Isolate* isolate,
590 Handle<Object> object,
591 Handle<Object> key,
592 Handle<Object> value,
593 StoreOrigin store_origin) {
594 if (object->IsNullOrUndefined(isolate)) {
595 THROW_NEW_ERROR(
596 isolate,
597 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
598 Object);
599 }
600
601 // Check if the given key is an array index.
602 bool success = false;
603 PropertyKey lookup_key(isolate, key, &success);
604 if (!success) return MaybeHandle<Object>();
605 LookupIterator it(isolate, object, lookup_key, LookupIterator::OWN);
606
607 if (key->IsSymbol() && Symbol::cast(*key).is_private_name()) {
608 if (!JSReceiver::CheckPrivateNameStore(&it, true)) {
609 return MaybeHandle<Object>();
610 }
611 DCHECK(!it.IsFound());
612 MAYBE_RETURN_NULL(
613 JSReceiver::AddPrivateField(&it, value, Nothing<ShouldThrow>()));
614 } else {
615 MAYBE_RETURN_NULL(
616 JSReceiver::CreateDataProperty(&it, value, Nothing<ShouldThrow>()));
617 }
618
619 return value;
620 }
621
RUNTIME_FUNCTION(Runtime_InternalSetPrototype)622 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
623 HandleScope scope(isolate);
624 DCHECK_EQ(2, args.length());
625 Handle<JSReceiver> obj = args.at<JSReceiver>(0);
626 Handle<Object> prototype = args.at(1);
627 MAYBE_RETURN(
628 JSReceiver::SetPrototype(isolate, obj, prototype, false, kThrowOnError),
629 ReadOnlyRoots(isolate).exception());
630 return *obj;
631 }
632
RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties)633 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
634 HandleScope scope(isolate);
635 DCHECK_EQ(2, args.length());
636 Handle<JSObject> object = args.at<JSObject>(0);
637 int properties = args.smi_value_at(1);
638 // Conservative upper limit to prevent fuzz tests from going OOM.
639 if (properties > 100000) return isolate->ThrowIllegalOperation();
640 if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
641 JSObject::NormalizeProperties(isolate, object, KEEP_INOBJECT_PROPERTIES,
642 properties, "OptimizeForAdding");
643 }
644 return *object;
645 }
646
RUNTIME_FUNCTION(Runtime_ObjectValues)647 RUNTIME_FUNCTION(Runtime_ObjectValues) {
648 HandleScope scope(isolate);
649 DCHECK_EQ(1, args.length());
650
651 Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
652
653 Handle<FixedArray> values;
654 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
655 isolate, values,
656 JSReceiver::GetOwnValues(receiver, PropertyFilter::ENUMERABLE_STRINGS,
657 true));
658 return *isolate->factory()->NewJSArrayWithElements(values);
659 }
660
RUNTIME_FUNCTION(Runtime_ObjectValuesSkipFastPath)661 RUNTIME_FUNCTION(Runtime_ObjectValuesSkipFastPath) {
662 HandleScope scope(isolate);
663 DCHECK_EQ(1, args.length());
664
665 Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
666
667 Handle<FixedArray> value;
668 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
669 isolate, value,
670 JSReceiver::GetOwnValues(receiver, PropertyFilter::ENUMERABLE_STRINGS,
671 false));
672 return *isolate->factory()->NewJSArrayWithElements(value);
673 }
674
RUNTIME_FUNCTION(Runtime_ObjectEntries)675 RUNTIME_FUNCTION(Runtime_ObjectEntries) {
676 HandleScope scope(isolate);
677 DCHECK_EQ(1, args.length());
678
679 Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
680
681 Handle<FixedArray> entries;
682 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
683 isolate, entries,
684 JSReceiver::GetOwnEntries(receiver, PropertyFilter::ENUMERABLE_STRINGS,
685 true));
686 return *isolate->factory()->NewJSArrayWithElements(entries);
687 }
688
RUNTIME_FUNCTION(Runtime_ObjectEntriesSkipFastPath)689 RUNTIME_FUNCTION(Runtime_ObjectEntriesSkipFastPath) {
690 HandleScope scope(isolate);
691 DCHECK_EQ(1, args.length());
692
693 Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
694
695 Handle<FixedArray> entries;
696 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
697 isolate, entries,
698 JSReceiver::GetOwnEntries(receiver, PropertyFilter::ENUMERABLE_STRINGS,
699 false));
700 return *isolate->factory()->NewJSArrayWithElements(entries);
701 }
702
RUNTIME_FUNCTION(Runtime_ObjectIsExtensible)703 RUNTIME_FUNCTION(Runtime_ObjectIsExtensible) {
704 HandleScope scope(isolate);
705 DCHECK_EQ(1, args.length());
706 Handle<Object> object = args.at(0);
707
708 Maybe<bool> result =
709 object->IsJSReceiver()
710 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
711 : Just(false);
712 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
713 return isolate->heap()->ToBoolean(result.FromJust());
714 }
715
RUNTIME_FUNCTION(Runtime_JSReceiverPreventExtensionsThrow)716 RUNTIME_FUNCTION(Runtime_JSReceiverPreventExtensionsThrow) {
717 HandleScope scope(isolate);
718 DCHECK_EQ(1, args.length());
719 Handle<JSReceiver> object = args.at<JSReceiver>(0);
720
721 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
722 kThrowOnError),
723 ReadOnlyRoots(isolate).exception());
724 return *object;
725 }
726
RUNTIME_FUNCTION(Runtime_JSReceiverPreventExtensionsDontThrow)727 RUNTIME_FUNCTION(Runtime_JSReceiverPreventExtensionsDontThrow) {
728 HandleScope scope(isolate);
729 DCHECK_EQ(1, args.length());
730 Handle<JSReceiver> object = args.at<JSReceiver>(0);
731
732 Maybe<bool> result = JSReceiver::PreventExtensions(
733 Handle<JSReceiver>::cast(object), kDontThrow);
734 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
735 return *isolate->factory()->ToBoolean(result.FromJust());
736 }
737
RUNTIME_FUNCTION(Runtime_JSReceiverGetPrototypeOf)738 RUNTIME_FUNCTION(Runtime_JSReceiverGetPrototypeOf) {
739 HandleScope scope(isolate);
740 DCHECK_EQ(1, args.length());
741 Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
742
743 RETURN_RESULT_OR_FAILURE(isolate,
744 JSReceiver::GetPrototype(isolate, receiver));
745 }
746
RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfThrow)747 RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfThrow) {
748 HandleScope scope(isolate);
749
750 DCHECK_EQ(2, args.length());
751 Handle<JSReceiver> object = args.at<JSReceiver>(0);
752 Handle<Object> proto = args.at(1);
753
754 MAYBE_RETURN(
755 JSReceiver::SetPrototype(isolate, object, proto, true, kThrowOnError),
756 ReadOnlyRoots(isolate).exception());
757
758 return *object;
759 }
760
RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfDontThrow)761 RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfDontThrow) {
762 HandleScope scope(isolate);
763
764 DCHECK_EQ(2, args.length());
765 Handle<JSReceiver> object = args.at<JSReceiver>(0);
766 Handle<Object> proto = args.at(1);
767
768 Maybe<bool> result =
769 JSReceiver::SetPrototype(isolate, object, proto, true, kDontThrow);
770 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
771 return *isolate->factory()->ToBoolean(result.FromJust());
772 }
773
RUNTIME_FUNCTION(Runtime_GetProperty)774 RUNTIME_FUNCTION(Runtime_GetProperty) {
775 HandleScope scope(isolate);
776 DCHECK(args.length() == 3 || args.length() == 2);
777 Handle<Object> lookup_start_obj = args.at(0);
778 Handle<Object> key_obj = args.at(1);
779 Handle<Object> receiver_obj = lookup_start_obj;
780 if (args.length() == 3) {
781 receiver_obj = args.at<Object>(2);
782 }
783
784 // Fast cases for getting named properties of the lookup_start_obj JSObject
785 // itself.
786 //
787 // The global proxy objects has to be excluded since LookupOwn on
788 // the global proxy object can return a valid result even though the
789 // global proxy object never has properties. This is the case
790 // because the global proxy object forwards everything to its hidden
791 // prototype including own lookups.
792 //
793 // Additionally, we need to make sure that we do not cache results
794 // for objects that require access checks.
795
796 // Convert string-index keys to their number variant to avoid internalization
797 // below; and speed up subsequent conversion to index.
798 uint32_t index;
799 if (key_obj->IsString() && String::cast(*key_obj).AsArrayIndex(&index)) {
800 key_obj = isolate->factory()->NewNumberFromUint(index);
801 }
802 if (lookup_start_obj->IsJSObject()) {
803 Handle<JSObject> lookup_start_object =
804 Handle<JSObject>::cast(lookup_start_obj);
805 if (!lookup_start_object->IsJSGlobalProxy() &&
806 !lookup_start_object->IsAccessCheckNeeded() && key_obj->IsName()) {
807 Handle<Name> key = Handle<Name>::cast(key_obj);
808 key_obj = key = isolate->factory()->InternalizeName(key);
809
810 DisallowGarbageCollection no_gc;
811 if (lookup_start_object->IsJSGlobalObject()) {
812 // Attempt dictionary lookup.
813 GlobalDictionary dictionary = JSGlobalObject::cast(*lookup_start_object)
814 .global_dictionary(kAcquireLoad);
815 InternalIndex entry = dictionary.FindEntry(isolate, key);
816 if (entry.is_found()) {
817 PropertyCell cell = dictionary.CellAt(entry);
818 if (cell.property_details().kind() == PropertyKind::kData) {
819 Object value = cell.value();
820 if (!value.IsTheHole(isolate)) return value;
821 // If value is the hole (meaning, absent) do the general lookup.
822 }
823 }
824 } else if (!lookup_start_object->HasFastProperties()) {
825 // Attempt dictionary lookup.
826 if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
827 SwissNameDictionary dictionary =
828 lookup_start_object->property_dictionary_swiss();
829 InternalIndex entry = dictionary.FindEntry(isolate, *key);
830 if (entry.is_found() &&
831 (dictionary.DetailsAt(entry).kind() == PropertyKind::kData)) {
832 return dictionary.ValueAt(entry);
833 }
834 } else {
835 NameDictionary dictionary =
836 lookup_start_object->property_dictionary();
837 InternalIndex entry = dictionary.FindEntry(isolate, key);
838 if ((entry.is_found()) &&
839 (dictionary.DetailsAt(entry).kind() == PropertyKind::kData)) {
840 return dictionary.ValueAt(entry);
841 }
842 }
843 }
844 } else if (key_obj->IsSmi()) {
845 // JSObject without a name key. If the key is a Smi, check for a
846 // definite out-of-bounds access to elements, which is a strong indicator
847 // that subsequent accesses will also call the runtime. Proactively
848 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
849 // doubles for those future calls in the case that the elements would
850 // become PACKED_DOUBLE_ELEMENTS.
851 ElementsKind elements_kind = lookup_start_object->GetElementsKind();
852 if (IsDoubleElementsKind(elements_kind)) {
853 if (Smi::ToInt(*key_obj) >= lookup_start_object->elements().length()) {
854 elements_kind = IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS
855 : PACKED_ELEMENTS;
856 JSObject::TransitionElementsKind(lookup_start_object, elements_kind);
857 }
858 } else {
859 DCHECK(IsSmiOrObjectElementsKind(elements_kind) ||
860 !IsFastElementsKind(elements_kind));
861 }
862 }
863 } else if (lookup_start_obj->IsString() && key_obj->IsSmi()) {
864 // Fast case for string indexing using [] with a smi index.
865 Handle<String> str = Handle<String>::cast(lookup_start_obj);
866 int smi_index = Handle<Smi>::cast(key_obj)->value();
867 if (smi_index >= 0 && smi_index < str->length()) {
868 Factory* factory = isolate->factory();
869 return *factory->LookupSingleCharacterStringFromCode(
870 String::Flatten(isolate, str)->Get(smi_index));
871 }
872 }
873
874 // Fall back to GetObjectProperty.
875 RETURN_RESULT_OR_FAILURE(
876 isolate, Runtime::GetObjectProperty(isolate, lookup_start_obj, key_obj,
877 receiver_obj));
878 }
879
RUNTIME_FUNCTION(Runtime_SetKeyedProperty)880 RUNTIME_FUNCTION(Runtime_SetKeyedProperty) {
881 HandleScope scope(isolate);
882 DCHECK_EQ(3, args.length());
883
884 Handle<Object> object = args.at(0);
885 Handle<Object> key = args.at(1);
886 Handle<Object> value = args.at(2);
887
888 RETURN_RESULT_OR_FAILURE(
889 isolate, Runtime::SetObjectProperty(isolate, object, key, value,
890 StoreOrigin::kMaybeKeyed));
891 }
892
RUNTIME_FUNCTION(Runtime_DefineObjectOwnProperty)893 RUNTIME_FUNCTION(Runtime_DefineObjectOwnProperty) {
894 HandleScope scope(isolate);
895 DCHECK_EQ(3, args.length());
896
897 Handle<Object> object = args.at(0);
898 Handle<Object> key = args.at(1);
899 Handle<Object> value = args.at(2);
900
901 RETURN_RESULT_OR_FAILURE(
902 isolate, Runtime::DefineObjectOwnProperty(isolate, object, key, value,
903 StoreOrigin::kMaybeKeyed));
904 }
905
RUNTIME_FUNCTION(Runtime_SetNamedProperty)906 RUNTIME_FUNCTION(Runtime_SetNamedProperty) {
907 HandleScope scope(isolate);
908 DCHECK_EQ(3, args.length());
909
910 Handle<Object> object = args.at(0);
911 Handle<Object> key = args.at(1);
912 Handle<Object> value = args.at(2);
913
914 RETURN_RESULT_OR_FAILURE(
915 isolate, Runtime::SetObjectProperty(isolate, object, key, value,
916 StoreOrigin::kNamed));
917 }
918
919 // Similar to DefineKeyedOwnPropertyInLiteral, but does not update feedback, and
920 // and does not have a flags parameter for performing SetFunctionName().
921 //
922 // Currently, this is used for ObjectLiteral spread properties in CloneObjectIC
923 // and for array literal creations in StoreInArrayLiteralIC.
924 // TODO(v8:12548): merge this into DefineKeyedOwnPropertyInLiteral.
RUNTIME_FUNCTION(Runtime_DefineKeyedOwnPropertyInLiteral_Simple)925 RUNTIME_FUNCTION(Runtime_DefineKeyedOwnPropertyInLiteral_Simple) {
926 HandleScope scope(isolate);
927 DCHECK_EQ(3, args.length());
928
929 Handle<JSReceiver> object = args.at<JSReceiver>(0);
930 Handle<Object> key = args.at(1);
931 Handle<Object> value = args.at(2);
932
933 PropertyKey lookup_key(isolate, key);
934 LookupIterator it(isolate, object, lookup_key, LookupIterator::OWN);
935
936 Maybe<bool> result = JSObject::DefineOwnPropertyIgnoreAttributes(
937 &it, value, NONE, Just(kDontThrow));
938 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
939 DCHECK(result.IsJust());
940 USE(result);
941
942 return *value;
943 }
944
945 namespace {
946
947 // ES6 section 12.5.4.
DeleteProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,LanguageMode language_mode)948 Object DeleteProperty(Isolate* isolate, Handle<Object> object,
949 Handle<Object> key, LanguageMode language_mode) {
950 Handle<JSReceiver> receiver;
951 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
952 Object::ToObject(isolate, object));
953 Maybe<bool> result =
954 Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode);
955 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
956 return isolate->heap()->ToBoolean(result.FromJust());
957 }
958
959 } // namespace
960
RUNTIME_FUNCTION(Runtime_DeleteProperty)961 RUNTIME_FUNCTION(Runtime_DeleteProperty) {
962 HandleScope scope(isolate);
963 DCHECK_EQ(3, args.length());
964 Handle<Object> object = args.at(0);
965 Handle<Object> key = args.at(1);
966 int language_mode = args.smi_value_at(2);
967 return DeleteProperty(isolate, object, key,
968 static_cast<LanguageMode>(language_mode));
969 }
970
RUNTIME_FUNCTION(Runtime_ShrinkNameDictionary)971 RUNTIME_FUNCTION(Runtime_ShrinkNameDictionary) {
972 HandleScope scope(isolate);
973 DCHECK_EQ(1, args.length());
974 Handle<NameDictionary> dictionary = args.at<NameDictionary>(0);
975
976 return *NameDictionary::Shrink(isolate, dictionary);
977 }
978
RUNTIME_FUNCTION(Runtime_ShrinkSwissNameDictionary)979 RUNTIME_FUNCTION(Runtime_ShrinkSwissNameDictionary) {
980 HandleScope scope(isolate);
981 DCHECK_EQ(1, args.length());
982 Handle<SwissNameDictionary> dictionary = args.at<SwissNameDictionary>(0);
983
984 return *SwissNameDictionary::Shrink(isolate, dictionary);
985 }
986
987 // ES6 section 12.9.3, operator in.
RUNTIME_FUNCTION(Runtime_HasProperty)988 RUNTIME_FUNCTION(Runtime_HasProperty) {
989 HandleScope scope(isolate);
990 DCHECK_EQ(2, args.length());
991 Handle<Object> object = args.at(0);
992 Handle<Object> key = args.at(1);
993
994 // Check that {object} is actually a receiver.
995 if (!object->IsJSReceiver()) {
996 THROW_NEW_ERROR_RETURN_FAILURE(
997 isolate,
998 NewTypeError(MessageTemplate::kInvalidInOperatorUse, key, object));
999 }
1000 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
1001
1002 // Convert the {key} to a name.
1003 Handle<Name> name;
1004 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1005 Object::ToName(isolate, key));
1006
1007 // Lookup the {name} on {receiver}.
1008 Maybe<bool> maybe = JSReceiver::HasProperty(isolate, receiver, name);
1009 if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
1010 return isolate->heap()->ToBoolean(maybe.FromJust());
1011 }
1012
RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys)1013 RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) {
1014 HandleScope scope(isolate);
1015 DCHECK_EQ(2, args.length());
1016 Handle<JSReceiver> object = args.at<JSReceiver>(0);
1017 int filter_value = args.smi_value_at(1);
1018 PropertyFilter filter = static_cast<PropertyFilter>(filter_value);
1019
1020 Handle<FixedArray> keys;
1021 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1022 isolate, keys,
1023 KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, filter,
1024 GetKeysConversion::kConvertToString));
1025
1026 return *isolate->factory()->NewJSArrayWithElements(keys);
1027 }
1028
RUNTIME_FUNCTION(Runtime_ToFastProperties)1029 RUNTIME_FUNCTION(Runtime_ToFastProperties) {
1030 HandleScope scope(isolate);
1031 DCHECK_EQ(1, args.length());
1032 Handle<Object> object = args.at(0);
1033 if (object->IsJSObject() && !object->IsJSGlobalObject()) {
1034 JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
1035 "RuntimeToFastProperties");
1036 }
1037 return *object;
1038 }
1039
RUNTIME_FUNCTION(Runtime_AllocateHeapNumber)1040 RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
1041 HandleScope scope(isolate);
1042 DCHECK_EQ(0, args.length());
1043 return *isolate->factory()->NewHeapNumber(0);
1044 }
1045
RUNTIME_FUNCTION(Runtime_NewObject)1046 RUNTIME_FUNCTION(Runtime_NewObject) {
1047 HandleScope scope(isolate);
1048 DCHECK_EQ(2, args.length());
1049 Handle<JSFunction> target = args.at<JSFunction>(0);
1050 Handle<JSReceiver> new_target = args.at<JSReceiver>(1);
1051 RETURN_RESULT_OR_FAILURE(
1052 isolate,
1053 JSObject::New(target, new_target, Handle<AllocationSite>::null()));
1054 }
1055
RUNTIME_FUNCTION(Runtime_GetDerivedMap)1056 RUNTIME_FUNCTION(Runtime_GetDerivedMap) {
1057 HandleScope scope(isolate);
1058 DCHECK_EQ(3, args.length());
1059 Handle<JSFunction> target = args.at<JSFunction>(0);
1060 Handle<JSReceiver> new_target = args.at<JSReceiver>(1);
1061 Handle<Object> rab_gsab = args.at(2);
1062 if (rab_gsab->IsTrue()) {
1063 return *JSFunction::GetDerivedRabGsabMap(isolate, target, new_target);
1064 } else {
1065 RETURN_RESULT_OR_FAILURE(
1066 isolate, JSFunction::GetDerivedMap(isolate, target, new_target));
1067 }
1068 }
1069
RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTrackingForMap)1070 RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTrackingForMap) {
1071 DisallowGarbageCollection no_gc;
1072 HandleScope scope(isolate);
1073 DCHECK_EQ(1, args.length());
1074
1075 Handle<Map> initial_map = args.at<Map>(0);
1076 MapUpdater::CompleteInobjectSlackTracking(isolate, *initial_map);
1077
1078 return ReadOnlyRoots(isolate).undefined_value();
1079 }
1080
RUNTIME_FUNCTION(Runtime_TryMigrateInstance)1081 RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
1082 HandleScope scope(isolate);
1083 DCHECK_EQ(1, args.length());
1084 Handle<JSObject> js_object = args.at<JSObject>(0);
1085 // It could have been a DCHECK but we call this function directly from tests.
1086 if (!js_object->map().is_deprecated()) return Smi::zero();
1087 // This call must not cause lazy deopts, because it's called from deferred
1088 // code where we can't handle lazy deopts for lack of a suitable bailout
1089 // ID. So we just try migration and signal failure if necessary,
1090 // which will also trigger a deopt.
1091 if (!JSObject::TryMigrateInstance(isolate, js_object)) return Smi::zero();
1092 return *js_object;
1093 }
1094
IsValidAccessor(Isolate * isolate,Handle<Object> obj)1095 static bool IsValidAccessor(Isolate* isolate, Handle<Object> obj) {
1096 return obj->IsNullOrUndefined(isolate) || obj->IsCallable();
1097 }
1098
1099 // Implements part of 8.12.9 DefineOwnProperty.
1100 // There are 3 cases that lead here:
1101 // Step 4b - define a new accessor property.
1102 // Steps 9c & 12 - replace an existing data property with an accessor property.
1103 // Step 12 - update an existing accessor property with an accessor or generic
1104 // descriptor.
RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked)1105 RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
1106 HandleScope scope(isolate);
1107 DCHECK_EQ(5, args.length());
1108 Handle<JSObject> obj = args.at<JSObject>(0);
1109 CHECK(!obj->IsNull(isolate));
1110 Handle<Name> name = args.at<Name>(1);
1111 Handle<Object> getter = args.at(2);
1112 CHECK(IsValidAccessor(isolate, getter));
1113 Handle<Object> setter = args.at(3);
1114 CHECK(IsValidAccessor(isolate, setter));
1115 auto attrs = PropertyAttributesFromInt(args.smi_value_at(4));
1116
1117 RETURN_FAILURE_ON_EXCEPTION(
1118 isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
1119 return ReadOnlyRoots(isolate).undefined_value();
1120 }
1121
RUNTIME_FUNCTION(Runtime_DefineKeyedOwnPropertyInLiteral)1122 RUNTIME_FUNCTION(Runtime_DefineKeyedOwnPropertyInLiteral) {
1123 HandleScope scope(isolate);
1124 DCHECK_EQ(6, args.length());
1125 Handle<JSObject> object = args.at<JSObject>(0);
1126 Handle<Name> name = args.at<Name>(1);
1127 Handle<Object> value = args.at(2);
1128 int flag = args.smi_value_at(3);
1129 Handle<HeapObject> maybe_vector = args.at<HeapObject>(4);
1130 int index = args.tagged_index_value_at(5);
1131
1132 if (!maybe_vector->IsUndefined()) {
1133 DCHECK(maybe_vector->IsFeedbackVector());
1134 Handle<FeedbackVector> vector = Handle<FeedbackVector>::cast(maybe_vector);
1135 FeedbackNexus nexus(vector, FeedbackVector::ToSlot(index));
1136 if (nexus.ic_state() == InlineCacheState::UNINITIALIZED) {
1137 if (name->IsUniqueName()) {
1138 nexus.ConfigureMonomorphic(name, handle(object->map(), isolate),
1139 MaybeObjectHandle());
1140 } else {
1141 nexus.ConfigureMegamorphic(IcCheckType::kProperty);
1142 }
1143 } else if (nexus.ic_state() == InlineCacheState::MONOMORPHIC) {
1144 if (nexus.GetFirstMap() != object->map() || nexus.GetName() != *name) {
1145 nexus.ConfigureMegamorphic(IcCheckType::kProperty);
1146 }
1147 }
1148 }
1149
1150 DefineKeyedOwnPropertyInLiteralFlags flags(flag);
1151 PropertyAttributes attrs =
1152 (flags & DefineKeyedOwnPropertyInLiteralFlag::kDontEnum)
1153 ? PropertyAttributes::DONT_ENUM
1154 : PropertyAttributes::NONE;
1155
1156 if (flags & DefineKeyedOwnPropertyInLiteralFlag::kSetFunctionName) {
1157 DCHECK(value->IsJSFunction());
1158 Handle<JSFunction> function = Handle<JSFunction>::cast(value);
1159 DCHECK(!function->shared().HasSharedName());
1160 Handle<Map> function_map(function->map(), isolate);
1161 if (!JSFunction::SetName(function, name,
1162 isolate->factory()->empty_string())) {
1163 return ReadOnlyRoots(isolate).exception();
1164 }
1165 // Class constructors do not reserve in-object space for name field.
1166 CHECK_IMPLIES(!IsClassConstructor(function->shared().kind()),
1167 *function_map == function->map());
1168 }
1169
1170 PropertyKey key(isolate, name);
1171 LookupIterator it(isolate, object, key, object, LookupIterator::OWN);
1172 // Cannot fail since this should only be called when
1173 // creating an object literal.
1174 CHECK(JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attrs,
1175 Just(kDontThrow))
1176 .IsJust());
1177
1178 // Return the value so that
1179 // BaselineCompiler::VisitDefineKeyedOwnPropertyInLiteral doesn't have to
1180 // save the accumulator.
1181 return *value;
1182 }
1183
RUNTIME_FUNCTION(Runtime_CollectTypeProfile)1184 RUNTIME_FUNCTION(Runtime_CollectTypeProfile) {
1185 HandleScope scope(isolate);
1186 DCHECK_EQ(3, args.length());
1187 int position = args.smi_value_at(0);
1188 Handle<Object> value = args.at(1);
1189 Handle<HeapObject> maybe_vector = args.at<HeapObject>(2);
1190
1191 if (maybe_vector->IsUndefined()) {
1192 return ReadOnlyRoots(isolate).undefined_value();
1193 }
1194 Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
1195
1196 Handle<String> type = Object::TypeOf(isolate, value);
1197 if (value->IsJSReceiver()) {
1198 Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
1199 type = JSReceiver::GetConstructorName(isolate, object);
1200 } else if (value->IsNull(isolate)) {
1201 // typeof(null) is object. But it's more user-friendly to annotate
1202 // null as type "null".
1203 type = Handle<String>(ReadOnlyRoots(isolate).null_string(), isolate);
1204 }
1205
1206 DCHECK(vector->metadata().HasTypeProfileSlot());
1207 FeedbackNexus nexus(vector, vector->GetTypeProfileSlot());
1208 nexus.Collect(type, position);
1209
1210 return ReadOnlyRoots(isolate).undefined_value();
1211 }
1212
RUNTIME_FUNCTION(Runtime_HasFastPackedElements)1213 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
1214 SealHandleScope shs(isolate);
1215 DCHECK_EQ(1, args.length());
1216 auto obj = HeapObject::cast(args[0]);
1217 return isolate->heap()->ToBoolean(
1218 IsFastPackedElementsKind(obj.map().elements_kind()));
1219 }
1220
RUNTIME_FUNCTION(Runtime_IsJSReceiver)1221 RUNTIME_FUNCTION(Runtime_IsJSReceiver) {
1222 SealHandleScope shs(isolate);
1223 DCHECK_EQ(1, args.length());
1224 Object obj = args[0];
1225 return isolate->heap()->ToBoolean(obj.IsJSReceiver());
1226 }
1227
RUNTIME_FUNCTION(Runtime_GetFunctionName)1228 RUNTIME_FUNCTION(Runtime_GetFunctionName) {
1229 HandleScope scope(isolate);
1230 DCHECK_EQ(1, args.length());
1231 Handle<JSFunction> function = args.at<JSFunction>(0);
1232 return *JSFunction::GetName(isolate, function);
1233 }
1234
RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked)1235 RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
1236 HandleScope scope(isolate);
1237 DCHECK_EQ(4, args.length());
1238 Handle<JSObject> object = args.at<JSObject>(0);
1239 Handle<Name> name = args.at<Name>(1);
1240 Handle<JSFunction> getter = args.at<JSFunction>(2);
1241 auto attrs = PropertyAttributesFromInt(args.smi_value_at(3));
1242
1243 if (String::cast(getter->shared().Name()).length() == 0) {
1244 Handle<Map> getter_map(getter->map(), isolate);
1245 if (!JSFunction::SetName(getter, name, isolate->factory()->get_string())) {
1246 return ReadOnlyRoots(isolate).exception();
1247 }
1248 CHECK_EQ(*getter_map, getter->map());
1249 }
1250
1251 RETURN_FAILURE_ON_EXCEPTION(
1252 isolate,
1253 JSObject::DefineAccessor(object, name, getter,
1254 isolate->factory()->null_value(), attrs));
1255 return ReadOnlyRoots(isolate).undefined_value();
1256 }
1257
RUNTIME_FUNCTION(Runtime_SetDataProperties)1258 RUNTIME_FUNCTION(Runtime_SetDataProperties) {
1259 HandleScope scope(isolate);
1260 DCHECK_EQ(2, args.length());
1261 Handle<JSReceiver> target = args.at<JSReceiver>(0);
1262 Handle<Object> source = args.at(1);
1263
1264 // 2. If source is undefined or null, let keys be an empty List.
1265 if (source->IsUndefined(isolate) || source->IsNull(isolate)) {
1266 return ReadOnlyRoots(isolate).undefined_value();
1267 }
1268
1269 MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(
1270 isolate, target, source,
1271 PropertiesEnumerationMode::kEnumerationOrder),
1272 ReadOnlyRoots(isolate).exception());
1273 return ReadOnlyRoots(isolate).undefined_value();
1274 }
1275
RUNTIME_FUNCTION(Runtime_CopyDataProperties)1276 RUNTIME_FUNCTION(Runtime_CopyDataProperties) {
1277 HandleScope scope(isolate);
1278 DCHECK_EQ(2, args.length());
1279 Handle<JSObject> target = args.at<JSObject>(0);
1280 Handle<Object> source = args.at(1);
1281
1282 // 2. If source is undefined or null, let keys be an empty List.
1283 if (source->IsUndefined(isolate) || source->IsNull(isolate)) {
1284 return ReadOnlyRoots(isolate).undefined_value();
1285 }
1286
1287 MAYBE_RETURN(
1288 JSReceiver::SetOrCopyDataProperties(
1289 isolate, target, source,
1290 PropertiesEnumerationMode::kPropertyAdditionOrder, nullptr, false),
1291 ReadOnlyRoots(isolate).exception());
1292 return ReadOnlyRoots(isolate).undefined_value();
1293 }
1294
1295 namespace {
1296
1297 // Check that the excluded properties are within the stack range of the top of
1298 // the stack, and the start of the JS frame.
CheckExcludedPropertiesAreOnCallerStack(Isolate * isolate,Address base,int count)1299 void CheckExcludedPropertiesAreOnCallerStack(Isolate* isolate, Address base,
1300 int count) {
1301 #ifdef DEBUG
1302 StackFrameIterator it(isolate);
1303
1304 // Don't need to check when there's no excluded properties.
1305 if (count == 0) return;
1306
1307 DCHECK(!it.done());
1308
1309 // Properties are pass in order on the stack, which means that their addresses
1310 // are in reverse order in memory (because stacks grow backwards). So, we
1311 // need to check if the _last_ property address is before the stack end...
1312 Address last_property = base - (count - 1) * kSystemPointerSize;
1313 DCHECK_GE(last_property, it.frame()->sp());
1314
1315 // ... and for the first JS frame, make sure the _first_ property address is
1316 // after that stack frame's start.
1317 for (; !it.done(); it.Advance()) {
1318 if (it.frame()->is_java_script()) {
1319 DCHECK_LT(base, it.frame()->fp());
1320 return;
1321 }
1322 }
1323
1324 // We should always find a JS frame.
1325 UNREACHABLE();
1326 #endif
1327 }
1328
1329 } // namespace
1330
RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedPropertiesOnStack)1331 RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedPropertiesOnStack) {
1332 HandleScope scope(isolate);
1333 DCHECK_EQ(3, args.length());
1334 Handle<Object> source = args.at(0);
1335 int excluded_property_count = args.smi_value_at(1);
1336 // The excluded_property_base is passed as a raw stack pointer. This is safe
1337 // because the stack pointer is aligned, so it looks like a Smi to the GC.
1338 Address* excluded_property_base = reinterpret_cast<Address*>(args[2].ptr());
1339 DCHECK(HAS_SMI_TAG(reinterpret_cast<intptr_t>(excluded_property_base)));
1340 // Also make sure that the given base pointer points to to on-stack values.
1341 CheckExcludedPropertiesAreOnCallerStack(
1342 isolate, reinterpret_cast<Address>(excluded_property_base),
1343 excluded_property_count);
1344
1345 // If source is undefined or null, throw a non-coercible error.
1346 if (source->IsNullOrUndefined(isolate)) {
1347 return ErrorUtils::ThrowLoadFromNullOrUndefined(isolate, source,
1348 MaybeHandle<Object>());
1349 }
1350
1351 base::ScopedVector<Handle<Object>> excluded_properties(
1352 excluded_property_count);
1353 for (int i = 0; i < excluded_property_count; i++) {
1354 // Because the excluded properties on stack is from high address
1355 // to low address, so we need to use sub
1356 Handle<Object> property(excluded_property_base - i);
1357 uint32_t property_num;
1358 // We convert string to number if possible, in cases of computed
1359 // properties resolving to numbers, which would've been strings
1360 // instead because of our call to %ToName() in the desugaring for
1361 // computed properties.
1362 if (property->IsString() &&
1363 String::cast(*property).AsArrayIndex(&property_num)) {
1364 property = isolate->factory()->NewNumberFromUint(property_num);
1365 }
1366
1367 excluded_properties[i] = property;
1368 }
1369
1370 Handle<JSObject> target =
1371 isolate->factory()->NewJSObject(isolate->object_function());
1372 MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(
1373 isolate, target, source,
1374 PropertiesEnumerationMode::kPropertyAdditionOrder,
1375 &excluded_properties, false),
1376 ReadOnlyRoots(isolate).exception());
1377 return *target;
1378 }
1379
RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked)1380 RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
1381 HandleScope scope(isolate);
1382 DCHECK_EQ(4, args.length());
1383 Handle<JSObject> object = args.at<JSObject>(0);
1384 Handle<Name> name = args.at<Name>(1);
1385 Handle<JSFunction> setter = args.at<JSFunction>(2);
1386 auto attrs = PropertyAttributesFromInt(args.smi_value_at(3));
1387
1388 if (String::cast(setter->shared().Name()).length() == 0) {
1389 Handle<Map> setter_map(setter->map(), isolate);
1390 if (!JSFunction::SetName(setter, name, isolate->factory()->set_string())) {
1391 return ReadOnlyRoots(isolate).exception();
1392 }
1393 CHECK_EQ(*setter_map, setter->map());
1394 }
1395
1396 RETURN_FAILURE_ON_EXCEPTION(
1397 isolate,
1398 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1399 setter, attrs));
1400 return ReadOnlyRoots(isolate).undefined_value();
1401 }
1402
RUNTIME_FUNCTION(Runtime_ToObject)1403 RUNTIME_FUNCTION(Runtime_ToObject) {
1404 // Runtime call is implemented in InterpreterIntrinsics and lowered in
1405 // JSIntrinsicLowering.
1406 UNREACHABLE();
1407 }
1408
RUNTIME_FUNCTION(Runtime_ToNumber)1409 RUNTIME_FUNCTION(Runtime_ToNumber) {
1410 HandleScope scope(isolate);
1411 DCHECK_EQ(1, args.length());
1412 Handle<Object> input = args.at(0);
1413 RETURN_RESULT_OR_FAILURE(isolate, Object::ToNumber(isolate, input));
1414 }
1415
RUNTIME_FUNCTION(Runtime_ToNumeric)1416 RUNTIME_FUNCTION(Runtime_ToNumeric) {
1417 HandleScope scope(isolate);
1418 DCHECK_EQ(1, args.length());
1419 Handle<Object> input = args.at(0);
1420 RETURN_RESULT_OR_FAILURE(isolate, Object::ToNumeric(isolate, input));
1421 }
1422
RUNTIME_FUNCTION(Runtime_ToLength)1423 RUNTIME_FUNCTION(Runtime_ToLength) {
1424 HandleScope scope(isolate);
1425 DCHECK_EQ(1, args.length());
1426 Handle<Object> input = args.at(0);
1427 RETURN_RESULT_OR_FAILURE(isolate, Object::ToLength(isolate, input));
1428 }
1429
RUNTIME_FUNCTION(Runtime_ToString)1430 RUNTIME_FUNCTION(Runtime_ToString) {
1431 HandleScope scope(isolate);
1432 DCHECK_EQ(1, args.length());
1433 Handle<Object> input = args.at(0);
1434 RETURN_RESULT_OR_FAILURE(isolate, Object::ToString(isolate, input));
1435 }
1436
RUNTIME_FUNCTION(Runtime_ToName)1437 RUNTIME_FUNCTION(Runtime_ToName) {
1438 HandleScope scope(isolate);
1439 DCHECK_EQ(1, args.length());
1440 Handle<Object> input = args.at(0);
1441 RETURN_RESULT_OR_FAILURE(isolate, Object::ToName(isolate, input));
1442 }
1443
RUNTIME_FUNCTION(Runtime_HasInPrototypeChain)1444 RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
1445 HandleScope scope(isolate);
1446 DCHECK_EQ(2, args.length());
1447 Handle<Object> object = args.at(0);
1448 Handle<Object> prototype = args.at(1);
1449 if (!object->IsJSReceiver()) return ReadOnlyRoots(isolate).false_value();
1450 Maybe<bool> result = JSReceiver::HasInPrototypeChain(
1451 isolate, Handle<JSReceiver>::cast(object), prototype);
1452 MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
1453 return isolate->heap()->ToBoolean(result.FromJust());
1454 }
1455
1456 // ES6 section 7.4.7 CreateIterResultObject ( value, done )
RUNTIME_FUNCTION(Runtime_CreateIterResultObject)1457 RUNTIME_FUNCTION(Runtime_CreateIterResultObject) {
1458 HandleScope scope(isolate);
1459 DCHECK_EQ(2, args.length());
1460 Handle<Object> value = args.at(0);
1461 Handle<Object> done = args.at(1);
1462 return *isolate->factory()->NewJSIteratorResult(value,
1463 done->BooleanValue(isolate));
1464 }
1465
RUNTIME_FUNCTION(Runtime_CreateDataProperty)1466 RUNTIME_FUNCTION(Runtime_CreateDataProperty) {
1467 HandleScope scope(isolate);
1468 DCHECK_EQ(3, args.length());
1469 Handle<JSReceiver> o = args.at<JSReceiver>(0);
1470 Handle<Object> key = args.at(1);
1471 Handle<Object> value = args.at(2);
1472 bool success;
1473 PropertyKey lookup_key(isolate, key, &success);
1474 if (!success) return ReadOnlyRoots(isolate).exception();
1475 LookupIterator it(isolate, o, lookup_key, LookupIterator::OWN);
1476 MAYBE_RETURN(JSReceiver::CreateDataProperty(&it, value, Just(kThrowOnError)),
1477 ReadOnlyRoots(isolate).exception());
1478 return *value;
1479 }
1480
RUNTIME_FUNCTION(Runtime_SetOwnPropertyIgnoreAttributes)1481 RUNTIME_FUNCTION(Runtime_SetOwnPropertyIgnoreAttributes) {
1482 HandleScope scope(isolate);
1483 DCHECK_EQ(4, args.length());
1484 Handle<JSObject> o = args.at<JSObject>(0);
1485 Handle<String> key = args.at<String>(1);
1486 Handle<Object> value = args.at(2);
1487 int attributes = args.smi_value_at(3);
1488
1489 RETURN_RESULT_OR_FAILURE(isolate,
1490 JSObject::SetOwnPropertyIgnoreAttributes(
1491 o, key, value, PropertyAttributes(attributes)));
1492 }
1493
RUNTIME_FUNCTION(Runtime_GetOwnPropertyDescriptor)1494 RUNTIME_FUNCTION(Runtime_GetOwnPropertyDescriptor) {
1495 HandleScope scope(isolate);
1496
1497 DCHECK_EQ(2, args.length());
1498 Handle<JSReceiver> object = args.at<JSReceiver>(0);
1499 Handle<Name> name = args.at<Name>(1);
1500
1501 PropertyDescriptor desc;
1502 Maybe<bool> found =
1503 JSReceiver::GetOwnPropertyDescriptor(isolate, object, name, &desc);
1504 MAYBE_RETURN(found, ReadOnlyRoots(isolate).exception());
1505
1506 if (!found.FromJust()) return ReadOnlyRoots(isolate).undefined_value();
1507 return *desc.ToPropertyDescriptorObject(isolate);
1508 }
1509
RUNTIME_FUNCTION(Runtime_LoadPrivateSetter)1510 RUNTIME_FUNCTION(Runtime_LoadPrivateSetter) {
1511 HandleScope scope(isolate);
1512 DCHECK_EQ(args.length(), 1);
1513 Handle<AccessorPair> pair = args.at<AccessorPair>(0);
1514 DCHECK(pair->setter().IsJSFunction());
1515 return pair->setter();
1516 }
1517
RUNTIME_FUNCTION(Runtime_LoadPrivateGetter)1518 RUNTIME_FUNCTION(Runtime_LoadPrivateGetter) {
1519 HandleScope scope(isolate);
1520 DCHECK_EQ(args.length(), 1);
1521 Handle<AccessorPair> pair = args.at<AccessorPair>(0);
1522 DCHECK(pair->getter().IsJSFunction());
1523 return pair->getter();
1524 }
1525
RUNTIME_FUNCTION(Runtime_CreatePrivateAccessors)1526 RUNTIME_FUNCTION(Runtime_CreatePrivateAccessors) {
1527 HandleScope scope(isolate);
1528 DCHECK_EQ(args.length(), 2);
1529 DCHECK(args[0].IsNull() || args[0].IsJSFunction());
1530 DCHECK(args[1].IsNull() || args[1].IsJSFunction());
1531 Handle<AccessorPair> pair = isolate->factory()->NewAccessorPair();
1532 pair->SetComponents(args[0], args[1]);
1533 return *pair;
1534 }
1535
1536 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1537 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableAllocate)1538 RUNTIME_FUNCTION(Runtime_SwissTableAllocate) {
1539 HandleScope scope(isolate);
1540 int at_least_space_for = args.smi_value_at(0);
1541
1542 return *isolate->factory()->NewSwissNameDictionary(at_least_space_for,
1543 AllocationType::kYoung);
1544 }
1545
1546 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1547 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableAdd)1548 RUNTIME_FUNCTION(Runtime_SwissTableAdd) {
1549 HandleScope scope(isolate);
1550 Handle<SwissNameDictionary> table = args.at<SwissNameDictionary>(0);
1551 Handle<Name> key = args.at<Name>(1);
1552 Handle<Object> value = args.at(2);
1553 PropertyDetails details(Smi::cast(args[3]));
1554
1555 DCHECK(key->IsUniqueName());
1556
1557 return *SwissNameDictionary::Add(isolate, table, key, value, details);
1558 }
1559
1560 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1561 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableFindEntry)1562 RUNTIME_FUNCTION(Runtime_SwissTableFindEntry) {
1563 HandleScope scope(isolate);
1564 DisallowGarbageCollection no_gc;
1565 auto table = SwissNameDictionary::cast(args[0]);
1566 Name key = Name::cast(args[1]);
1567 InternalIndex index = table.FindEntry(isolate, key);
1568 return Smi::FromInt(index.is_found()
1569 ? index.as_int()
1570 : SwissNameDictionary::kNotFoundSentinel);
1571 }
1572
1573 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1574 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableUpdate)1575 RUNTIME_FUNCTION(Runtime_SwissTableUpdate) {
1576 HandleScope scope(isolate);
1577 DisallowGarbageCollection no_gc;
1578 auto table = SwissNameDictionary::cast(args[0]);
1579 InternalIndex index(args.smi_value_at(1));
1580 Object value = args[2];
1581 table.ValueAtPut(index, value);
1582
1583 PropertyDetails details(Smi::cast(args[3]));
1584 table.DetailsAtPut(index, details);
1585
1586 return ReadOnlyRoots(isolate).undefined_value();
1587 }
1588
1589 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1590 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableDelete)1591 RUNTIME_FUNCTION(Runtime_SwissTableDelete) {
1592 HandleScope scope(isolate);
1593 Handle<SwissNameDictionary> table = args.at<SwissNameDictionary>(0);
1594 InternalIndex index(args.smi_value_at(1));
1595
1596 return *SwissNameDictionary::DeleteEntry(isolate, table, index);
1597 }
1598
1599 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1600 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableEquals)1601 RUNTIME_FUNCTION(Runtime_SwissTableEquals) {
1602 HandleScope scope(isolate);
1603 DisallowGarbageCollection no_gc;
1604 auto table = SwissNameDictionary::cast(args[0]);
1605 auto other = SwissNameDictionary::cast(args[0]);
1606 return Smi::FromInt(table.EqualsForTesting(other));
1607 }
1608
1609 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1610 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableElementsCount)1611 RUNTIME_FUNCTION(Runtime_SwissTableElementsCount) {
1612 HandleScope scope(isolate);
1613 DisallowGarbageCollection no_gc;
1614 auto table = SwissNameDictionary::cast(args[0]);
1615 return Smi::FromInt(table.NumberOfElements());
1616 }
1617
1618 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1619 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableKeyAt)1620 RUNTIME_FUNCTION(Runtime_SwissTableKeyAt) {
1621 HandleScope scope(isolate);
1622 DisallowGarbageCollection no_gc;
1623 auto table = SwissNameDictionary::cast(args[0]);
1624 InternalIndex index(args.smi_value_at(1));
1625 return table.KeyAt(index);
1626 }
1627
1628 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1629 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableValueAt)1630 RUNTIME_FUNCTION(Runtime_SwissTableValueAt) {
1631 HandleScope scope(isolate);
1632 DisallowGarbageCollection no_gc;
1633 auto table = SwissNameDictionary::cast(args[0]);
1634 InternalIndex index(args.smi_value_at(1));
1635 return table.ValueAt(index);
1636 }
1637
1638 // TODO(v8:11330) This is only here while the CSA/Torque implementaton of
1639 // SwissNameDictionary is work in progress.
RUNTIME_FUNCTION(Runtime_SwissTableDetailsAt)1640 RUNTIME_FUNCTION(Runtime_SwissTableDetailsAt) {
1641 HandleScope scope(isolate);
1642 DisallowGarbageCollection no_gc;
1643 auto table = SwissNameDictionary::cast(args[0]);
1644 InternalIndex index(args.smi_value_at(1));
1645 PropertyDetails d = table.DetailsAt(index);
1646 return d.AsSmi();
1647 }
1648
1649 } // namespace internal
1650 } // namespace v8
1651