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