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