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/runtime/runtime-utils.h"
6 :
7 : #include "src/arguments.h"
8 : #include "src/bootstrapper.h"
9 : #include "src/debug/debug.h"
10 : #include "src/isolate-inl.h"
11 : #include "src/messages.h"
12 : #include "src/objects/property-descriptor-object.h"
13 : #include "src/property-descriptor.h"
14 : #include "src/runtime/runtime.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 52019422 : MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
20 : Handle<Object> object,
21 : Handle<Object> key,
22 : bool* is_found_out) {
23 52019422 : if (object->IsNullOrUndefined(isolate)) {
24 28970 : THROW_NEW_ERROR(
25 : isolate,
26 : NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
27 : Object);
28 : }
29 :
30 52004937 : bool success = false;
31 : LookupIterator it =
32 52004937 : LookupIterator::PropertyOrElement(isolate, object, key, &success);
33 52004936 : if (!success) return MaybeHandle<Object>();
34 :
35 52004921 : MaybeHandle<Object> result = Object::GetProperty(&it);
36 52005706 : if (is_found_out) *is_found_out = it.IsFound();
37 52004922 : return result;
38 : }
39 :
40 21102050 : static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate,
41 : Handle<Object> receiver_obj,
42 : Handle<Object> key_obj) {
43 : // Fast cases for getting named properties of the receiver JSObject
44 : // itself.
45 : //
46 : // The global proxy objects has to be excluded since LookupOwn on
47 : // the global proxy object can return a valid result even though the
48 : // global proxy object never has properties. This is the case
49 : // because the global proxy object forwards everything to its hidden
50 : // prototype including own lookups.
51 : //
52 : // Additionally, we need to make sure that we do not cache results
53 : // for objects that require access checks.
54 :
55 : // Convert string-index keys to their number variant to avoid internalization
56 : // below; and speed up subsequent conversion to index.
57 : uint32_t index;
58 22195672 : if (key_obj->IsString() && String::cast(*key_obj)->AsArrayIndex(&index)) {
59 25822 : key_obj = isolate->factory()->NewNumberFromUint(index);
60 : }
61 21102050 : if (receiver_obj->IsJSObject()) {
62 42099222 : if (!receiver_obj->IsJSGlobalProxy() &&
63 42098528 : !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
64 : Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
65 : Handle<Name> key = Handle<Name>::cast(key_obj);
66 1033410 : key_obj = key = isolate->factory()->InternalizeName(key);
67 :
68 : DisallowHeapAllocation no_allocation;
69 1033410 : if (receiver->IsJSGlobalObject()) {
70 : // Attempt dictionary lookup.
71 : GlobalDictionary* dictionary =
72 : JSGlobalObject::cast(*receiver)->global_dictionary();
73 : int entry = dictionary->FindEntry(key);
74 0 : if (entry != GlobalDictionary::kNotFound) {
75 : PropertyCell* cell = dictionary->CellAt(entry);
76 0 : if (cell->property_details().kind() == kData) {
77 : Object* value = cell->value();
78 0 : if (!value->IsTheHole(isolate)) {
79 0 : return Handle<Object>(value, isolate);
80 : }
81 : // If value is the hole (meaning, absent) do the general lookup.
82 : }
83 : }
84 1033410 : } else if (!receiver->HasFastProperties()) {
85 : // Attempt dictionary lookup.
86 : NameDictionary* dictionary = receiver->property_dictionary();
87 : int entry = dictionary->FindEntry(key);
88 1672525 : if ((entry != NameDictionary::kNotFound) &&
89 : (dictionary->DetailsAt(entry).kind() == kData)) {
90 821030 : Object* value = dictionary->ValueAt(entry);
91 821030 : return Handle<Object>(value, isolate);
92 : }
93 : }
94 20031522 : } else if (key_obj->IsSmi()) {
95 : // JSObject without a name key. If the key is a Smi, check for a
96 : // definite out-of-bounds access to elements, which is a strong indicator
97 : // that subsequent accesses will also call the runtime. Proactively
98 : // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
99 : // doubles for those future calls in the case that the elements would
100 : // become PACKED_DOUBLE_ELEMENTS.
101 : Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
102 : ElementsKind elements_kind = js_object->GetElementsKind();
103 19997679 : if (IsDoubleElementsKind(elements_kind)) {
104 80 : if (Smi::ToInt(*key_obj) >= js_object->elements()->length()) {
105 : elements_kind = IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS
106 0 : : PACKED_ELEMENTS;
107 0 : JSObject::TransitionElementsKind(js_object, elements_kind);
108 : }
109 : } else {
110 : DCHECK(IsSmiOrObjectElementsKind(elements_kind) ||
111 : !IsFastElementsKind(elements_kind));
112 : }
113 : }
114 63092 : } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
115 : // Fast case for string indexing using [] with a smi index.
116 : Handle<String> str = Handle<String>::cast(receiver_obj);
117 : int index = Handle<Smi>::cast(key_obj)->value();
118 45010 : if (index >= 0 && index < str->length()) {
119 : Factory* factory = isolate->factory();
120 : return factory->LookupSingleCharacterStringFromCode(
121 39320 : String::Flatten(str)->Get(index));
122 : }
123 : }
124 :
125 : // Fall back to GetObjectProperty.
126 20261360 : return Runtime::GetObjectProperty(isolate, receiver_obj, key_obj);
127 : }
128 :
129 : namespace {
130 :
131 11020511 : bool DeleteObjectPropertyFast(Isolate* isolate, Handle<JSReceiver> receiver,
132 : Handle<Object> raw_key) {
133 : DisallowHeapAllocation no_allocation;
134 : // This implements a special case for fast property deletion: when the
135 : // last property in an object is deleted, then instead of normalizing
136 : // the properties, we can undo the last map transition, with a few
137 : // prerequisites:
138 : // (1) The receiver must be a regular object and the key a unique name.
139 : Map* map = receiver->map();
140 11020511 : if (map->IsSpecialReceiverMap()) return false;
141 11001356 : if (!raw_key->IsUniqueName()) return false;
142 : Handle<Name> key = Handle<Name>::cast(raw_key);
143 : // (2) The property to be deleted must be the last property.
144 : int nof = map->NumberOfOwnDescriptors();
145 10219801 : if (nof == 0) return false;
146 10167034 : int descriptor = nof - 1;
147 : DescriptorArray* descriptors = map->instance_descriptors();
148 10167034 : if (descriptors->GetKey(descriptor) != *key) return false;
149 : // (3) The property to be deleted must be deletable.
150 10047581 : PropertyDetails details = descriptors->GetDetails(descriptor);
151 10047581 : if (!details.IsConfigurable()) return false;
152 : // (4) The map must have a back pointer.
153 10047314 : Object* backpointer = map->GetBackPointer();
154 10047314 : if (!backpointer->IsMap()) return false;
155 : // (5) The last transition must have been caused by adding a property
156 : // (and not any kind of special transition).
157 10021736 : if (Map::cast(backpointer)->NumberOfOwnDescriptors() != nof - 1) return false;
158 :
159 : // Preconditions successful. No more bailouts after this point.
160 :
161 : // Zap the property to avoid keeping objects alive. Zapping is not necessary
162 : // for properties stored in the descriptor array.
163 10021699 : if (details.location() == kField) {
164 : isolate->heap()->NotifyObjectLayoutChange(*receiver, map->instance_size(),
165 10021690 : no_allocation);
166 10021690 : Object* filler = isolate->heap()->one_pointer_filler_map();
167 10021690 : FieldIndex index = FieldIndex::ForPropertyIndex(map, details.field_index());
168 10021690 : JSObject::cast(*receiver)->RawFastPropertyAtPut(index, filler);
169 : // We must clear any recorded slot for the deleted property, because
170 : // subsequent object modifications might put a raw double there.
171 : // Slot clearing is the reason why this entire function cannot currently
172 : // be implemented in the DeleteProperty stub.
173 10021690 : if (index.is_inobject() && !map->IsUnboxedDoubleField(index)) {
174 : isolate->heap()->ClearRecordedSlot(
175 4081 : *receiver, HeapObject::RawField(*receiver, index.offset()));
176 : }
177 : }
178 : // If the map was marked stable before, then there could be optimized code
179 : // that depends on the assumption that no object that reached this map
180 : // transitions away from it without triggering the "deoptimize dependent
181 : // code" mechanism.
182 10021699 : map->NotifyLeafMapLayoutChange();
183 : // Finally, perform the map rollback.
184 10021699 : receiver->synchronized_set_map(Map::cast(backpointer));
185 10021699 : return true;
186 : }
187 :
188 : } // namespace
189 :
190 11020511 : Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate,
191 : Handle<JSReceiver> receiver,
192 : Handle<Object> key,
193 : LanguageMode language_mode) {
194 11020511 : if (DeleteObjectPropertyFast(isolate, receiver, key)) return Just(true);
195 :
196 998812 : bool success = false;
197 : LookupIterator it = LookupIterator::PropertyOrElement(
198 998812 : isolate, receiver, key, &success, LookupIterator::OWN);
199 998812 : if (!success) return Nothing<bool>();
200 :
201 998803 : return JSReceiver::DeleteProperty(&it, language_mode);
202 : }
203 :
204 : // ES #sec-object.keys
205 137082 : RUNTIME_FUNCTION(Runtime_ObjectKeys) {
206 68541 : HandleScope scope(isolate);
207 68541 : Handle<Object> object = args.at(0);
208 :
209 : // Convert the {object} to a proper {receiver}.
210 : Handle<JSReceiver> receiver;
211 137082 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
212 : Object::ToObject(isolate, object));
213 :
214 : // Collect the own keys for the {receiver}.
215 : Handle<FixedArray> keys;
216 137026 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
217 : isolate, keys,
218 : KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
219 : ENUMERABLE_STRINGS,
220 : GetKeysConversion::kConvertToString));
221 68541 : return *keys;
222 : }
223 :
224 : // ES6 19.1.3.2
225 3312 : RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
226 1656 : HandleScope scope(isolate);
227 1656 : Handle<Object> property = args.at(1);
228 :
229 : Handle<Name> key;
230 : uint32_t index;
231 1656 : bool key_is_array_index = property->ToArrayIndex(&index);
232 :
233 1656 : if (!key_is_array_index) {
234 2558 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
235 : Object::ToName(isolate, property));
236 1249 : key_is_array_index = key->AsArrayIndex(&index);
237 : }
238 :
239 1626 : Handle<Object> object = args.at(0);
240 :
241 1626 : if (object->IsJSModuleNamespace()) {
242 0 : if (key.is_null()) {
243 : DCHECK(key_is_array_index);
244 : // Namespace objects can't have indexed properties.
245 0 : return isolate->heap()->false_value();
246 : }
247 :
248 : Maybe<bool> result =
249 0 : JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), key);
250 0 : if (!result.IsJust()) return isolate->heap()->exception();
251 0 : return isolate->heap()->ToBoolean(result.FromJust());
252 :
253 1626 : } else if (object->IsJSObject()) {
254 964 : Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
255 : // Fast case: either the key is a real named property or it is not
256 : // an array index and there are no interceptors or hidden
257 : // prototypes.
258 : // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to
259 : // handle all cases directly (without this custom fast path).
260 : {
261 : LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
262 : LookupIterator it =
263 : key_is_array_index ? LookupIterator(isolate, js_obj, index, js_obj, c)
264 2183 : : LookupIterator(js_obj, key, js_obj, c);
265 964 : Maybe<bool> maybe = JSReceiver::HasProperty(&it);
266 1470 : if (maybe.IsNothing()) return isolate->heap()->exception();
267 : DCHECK(!isolate->has_pending_exception());
268 954 : if (maybe.FromJust()) return isolate->heap()->true_value();
269 : }
270 :
271 458 : Map* map = js_obj->map();
272 1098 : if (!map->has_hidden_prototype() &&
273 160 : (key_is_array_index ? !map->has_indexed_interceptor()
274 160 : : !map->has_named_interceptor())) {
275 261 : return isolate->heap()->false_value();
276 : }
277 :
278 : // Slow case.
279 : LookupIterator::Configuration c = LookupIterator::OWN;
280 : LookupIterator it = key_is_array_index
281 : ? LookupIterator(isolate, js_obj, index, js_obj, c)
282 394 : : LookupIterator(js_obj, key, js_obj, c);
283 :
284 197 : Maybe<bool> maybe = JSReceiver::HasProperty(&it);
285 197 : if (maybe.IsNothing()) return isolate->heap()->exception();
286 : DCHECK(!isolate->has_pending_exception());
287 197 : return isolate->heap()->ToBoolean(maybe.FromJust());
288 :
289 662 : } else if (object->IsJSProxy()) {
290 271 : if (key.is_null()) {
291 : DCHECK(key_is_array_index);
292 82 : key = isolate->factory()->Uint32ToString(index);
293 : }
294 :
295 : Maybe<bool> result =
296 542 : JSReceiver::HasOwnProperty(Handle<JSProxy>::cast(object), key);
297 271 : if (!result.IsJust()) return isolate->heap()->exception();
298 181 : return isolate->heap()->ToBoolean(result.FromJust());
299 :
300 391 : } else if (object->IsString()) {
301 : return isolate->heap()->ToBoolean(
302 : key_is_array_index
303 69 : ? index < static_cast<uint32_t>(String::cast(*object)->length())
304 272 : : key->Equals(isolate->heap()->length_string()));
305 255 : } else if (object->IsNullOrUndefined(isolate)) {
306 438 : THROW_NEW_ERROR_RETURN_FAILURE(
307 : isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
308 : }
309 :
310 36 : return isolate->heap()->false_value();
311 : }
312 :
313 60 : RUNTIME_FUNCTION(Runtime_AddDictionaryProperty) {
314 30 : HandleScope scope(isolate);
315 30 : Handle<JSObject> receiver = args.at<JSObject>(0);
316 30 : Handle<Name> name = args.at<Name>(1);
317 30 : Handle<Object> value = args.at(2);
318 :
319 : DCHECK(name->IsUniqueName());
320 :
321 30 : Handle<NameDictionary> dictionary(receiver->property_dictionary(), isolate);
322 30 : PropertyDetails property_details(kData, NONE, PropertyCellType::kNoCell);
323 30 : dictionary = NameDictionary::Add(dictionary, name, value, property_details);
324 30 : receiver->SetProperties(*dictionary);
325 30 : return *value;
326 : }
327 :
328 : // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
329 : // TODO(verwaest): Support the common cases with precached map directly in
330 : // an Object.create stub.
331 245518 : RUNTIME_FUNCTION(Runtime_ObjectCreate) {
332 122759 : HandleScope scope(isolate);
333 122759 : Handle<Object> prototype = args.at(0);
334 245150 : if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
335 76 : THROW_NEW_ERROR_RETURN_FAILURE(
336 : isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
337 : }
338 :
339 : // Generate the map with the specified {prototype} based on the Object
340 : // function's initial map from the current native context.
341 : // TODO(bmeurer): Use a dedicated cache for Object.create; think about
342 : // slack tracking for Object.create.
343 : Handle<Map> map =
344 122721 : Map::GetObjectCreateMap(Handle<HeapObject>::cast(prototype));
345 :
346 : // Actually allocate the object.
347 : Handle<JSObject> object;
348 122721 : if (map->is_dictionary_map()) {
349 368 : object = isolate->factory()->NewSlowJSObjectFromMap(map);
350 : } else {
351 122353 : object = isolate->factory()->NewJSObjectFromMap(map);
352 : }
353 :
354 : // Define the properties if properties was specified and is not undefined.
355 122721 : Handle<Object> properties = args.at(1);
356 122721 : if (!properties->IsUndefined(isolate)) {
357 1106 : RETURN_FAILURE_ON_EXCEPTION(
358 : isolate, JSReceiver::DefineProperties(isolate, object, properties));
359 : }
360 :
361 122759 : return *object;
362 : }
363 :
364 12983756 : MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
365 : Handle<Object> object,
366 : Handle<Object> key,
367 : Handle<Object> value,
368 : LanguageMode language_mode) {
369 12983756 : if (object->IsNullOrUndefined(isolate)) {
370 20000 : THROW_NEW_ERROR(
371 : isolate,
372 : NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
373 : Object);
374 : }
375 :
376 : // Check if the given key is an array index.
377 12973756 : bool success = false;
378 : LookupIterator it =
379 12973756 : LookupIterator::PropertyOrElement(isolate, object, key, &success);
380 12973756 : if (!success) return MaybeHandle<Object>();
381 :
382 12973747 : MAYBE_RETURN_NULL(Object::SetProperty(&it, value, language_mode,
383 : Object::MAY_BE_STORE_FROM_KEYED));
384 12857108 : return value;
385 : }
386 :
387 :
388 30 : RUNTIME_FUNCTION(Runtime_GetPrototype) {
389 15 : HandleScope scope(isolate);
390 : DCHECK_EQ(1, args.length());
391 30 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
392 45 : RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
393 : }
394 :
395 :
396 10492 : RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
397 5246 : HandleScope scope(isolate);
398 : DCHECK_EQ(2, args.length());
399 10492 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
400 5246 : CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
401 5246 : if (prototype->IsJSFunction()) {
402 586 : Handle<JSFunction> function = Handle<JSFunction>::cast(prototype);
403 586 : if (!function->shared()->has_shared_name()) {
404 0 : Handle<Map> function_map(function->map(), isolate);
405 0 : if (!JSFunction::SetName(function, isolate->factory()->proto_string(),
406 0 : isolate->factory()->empty_string())) {
407 0 : return isolate->heap()->exception();
408 : }
409 0 : CHECK_EQ(*function_map, function->map());
410 : }
411 : }
412 5246 : MAYBE_RETURN(
413 : JSReceiver::SetPrototype(obj, prototype, false, Object::THROW_ON_ERROR),
414 : isolate->heap()->exception());
415 5246 : return *obj;
416 : }
417 :
418 32308 : RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
419 16154 : HandleScope scope(isolate);
420 : DCHECK_EQ(2, args.length());
421 32308 : CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
422 32308 : CONVERT_SMI_ARG_CHECKED(properties, 1);
423 : // Conservative upper limit to prevent fuzz tests from going OOM.
424 16154 : if (properties > 100000) return isolate->ThrowIllegalOperation();
425 24383 : if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
426 : JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
427 8229 : "OptimizeForAdding");
428 : }
429 16154 : return *object;
430 : }
431 :
432 :
433 2936036 : RUNTIME_FUNCTION(Runtime_GetProperty) {
434 1468018 : HandleScope scope(isolate);
435 : DCHECK_EQ(2, args.length());
436 :
437 1468018 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
438 1468018 : CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
439 :
440 2936036 : RETURN_RESULT_OR_FAILURE(isolate,
441 1468018 : Runtime::GetObjectProperty(isolate, object, key));
442 : }
443 :
444 : // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
445 42204100 : RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
446 21102050 : HandleScope scope(isolate);
447 : DCHECK_EQ(2, args.length());
448 :
449 21102050 : CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
450 21102050 : CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
451 :
452 42204100 : RETURN_RESULT_OR_FAILURE(
453 21102050 : isolate, KeyedGetObjectProperty(isolate, receiver_obj, key_obj));
454 : }
455 :
456 328322 : RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
457 164161 : HandleScope scope(isolate);
458 : DCHECK_EQ(4, args.length());
459 :
460 328322 : CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
461 328322 : CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
462 164161 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
463 328322 : CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
464 :
465 : #ifdef DEBUG
466 : uint32_t index = 0;
467 : DCHECK(!name->ToArrayIndex(&index));
468 : LookupIterator it(object, name, object, LookupIterator::OWN_SKIP_INTERCEPTOR);
469 : Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
470 : if (!maybe.IsJust()) return isolate->heap()->exception();
471 : DCHECK(!it.IsFound());
472 : #endif
473 :
474 328322 : RETURN_RESULT_OR_FAILURE(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
475 164161 : object, name, value, attrs));
476 : }
477 :
478 :
479 : // Adds an element to an array.
480 : // This is used to create an indexed data property into an array.
481 0 : RUNTIME_FUNCTION(Runtime_AddElement) {
482 0 : HandleScope scope(isolate);
483 : DCHECK_EQ(3, args.length());
484 :
485 0 : CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
486 0 : CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
487 0 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
488 :
489 0 : uint32_t index = 0;
490 0 : CHECK(key->ToArrayIndex(&index));
491 :
492 : #ifdef DEBUG
493 : LookupIterator it(isolate, object, index, object,
494 : LookupIterator::OWN_SKIP_INTERCEPTOR);
495 : Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
496 : if (!maybe.IsJust()) return isolate->heap()->exception();
497 : DCHECK(!it.IsFound());
498 :
499 : if (object->IsJSArray()) {
500 : Handle<JSArray> array = Handle<JSArray>::cast(object);
501 : DCHECK(!JSArray::WouldChangeReadOnlyLength(array, index));
502 : }
503 : #endif
504 :
505 0 : RETURN_RESULT_OR_FAILURE(isolate, JSObject::SetOwnElementIgnoreAttributes(
506 0 : object, index, value, NONE));
507 : }
508 :
509 :
510 42834 : RUNTIME_FUNCTION(Runtime_AppendElement) {
511 21417 : HandleScope scope(isolate);
512 : DCHECK_EQ(2, args.length());
513 :
514 42834 : CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
515 21417 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
516 21417 : CHECK(!value->IsTheHole(isolate));
517 :
518 : uint32_t index;
519 21417 : CHECK(array->length()->ToArrayIndex(&index));
520 :
521 42834 : RETURN_FAILURE_ON_EXCEPTION(
522 : isolate, JSObject::AddDataElement(array, index, value, NONE));
523 21417 : JSObject::ValidateElements(*array);
524 21417 : return *array;
525 : }
526 :
527 :
528 23537776 : RUNTIME_FUNCTION(Runtime_SetProperty) {
529 11768888 : HandleScope scope(isolate);
530 : DCHECK_EQ(4, args.length());
531 :
532 11768888 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
533 11768888 : CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
534 11768888 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
535 23537776 : CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3);
536 :
537 23537776 : RETURN_RESULT_OR_FAILURE(
538 : isolate,
539 11768888 : Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
540 : }
541 :
542 :
543 : namespace {
544 :
545 : // ES6 section 12.5.4.
546 11012922 : Object* DeleteProperty(Isolate* isolate, Handle<Object> object,
547 : Handle<Object> key, LanguageMode language_mode) {
548 : Handle<JSReceiver> receiver;
549 22025844 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
550 : Object::ToObject(isolate, object));
551 : Maybe<bool> result =
552 11012903 : Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode);
553 11012903 : MAYBE_RETURN(result, isolate->heap()->exception());
554 11011433 : return isolate->heap()->ToBoolean(result.FromJust());
555 : }
556 :
557 : } // namespace
558 :
559 22025844 : RUNTIME_FUNCTION(Runtime_DeleteProperty) {
560 11012922 : HandleScope scope(isolate);
561 : DCHECK_EQ(3, args.length());
562 11012922 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
563 11012922 : CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
564 22025844 : CONVERT_SMI_ARG_CHECKED(language_mode, 2);
565 : return DeleteProperty(isolate, object, key,
566 11012922 : static_cast<LanguageMode>(language_mode));
567 : }
568 :
569 568 : RUNTIME_FUNCTION(Runtime_ShrinkPropertyDictionary) {
570 284 : HandleScope scope(isolate);
571 : DCHECK_EQ(1, args.length());
572 568 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
573 284 : Handle<NameDictionary> dictionary(receiver->property_dictionary(), isolate);
574 284 : Handle<NameDictionary> new_properties = NameDictionary::Shrink(dictionary);
575 284 : receiver->SetProperties(*new_properties);
576 284 : return Smi::kZero;
577 : }
578 :
579 : // ES6 section 12.9.3, operator in.
580 69804 : RUNTIME_FUNCTION(Runtime_HasProperty) {
581 34902 : HandleScope scope(isolate);
582 : DCHECK_EQ(2, args.length());
583 34902 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
584 34902 : CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
585 :
586 : // Check that {object} is actually a receiver.
587 34902 : if (!object->IsJSReceiver()) {
588 528 : THROW_NEW_ERROR_RETURN_FAILURE(
589 : isolate,
590 : NewTypeError(MessageTemplate::kInvalidInOperatorUse, key, object));
591 : }
592 34638 : Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
593 :
594 : // Convert the {key} to a name.
595 : Handle<Name> name;
596 69276 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
597 : Object::ToName(isolate, key));
598 :
599 : // Lookup the {name} on {receiver}.
600 34602 : Maybe<bool> maybe = JSReceiver::HasProperty(receiver, name);
601 34602 : if (!maybe.IsJust()) return isolate->heap()->exception();
602 34578 : return isolate->heap()->ToBoolean(maybe.FromJust());
603 : }
604 :
605 :
606 234 : RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) {
607 117 : HandleScope scope(isolate);
608 : DCHECK_EQ(2, args.length());
609 234 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
610 234 : CONVERT_SMI_ARG_CHECKED(filter_value, 1);
611 117 : PropertyFilter filter = static_cast<PropertyFilter>(filter_value);
612 :
613 : Handle<FixedArray> keys;
614 234 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
615 : isolate, keys,
616 : KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, filter,
617 : GetKeysConversion::kConvertToString));
618 :
619 234 : return *isolate->factory()->NewJSArrayWithElements(keys);
620 : }
621 :
622 :
623 : // Return information on whether an object has a named or indexed interceptor.
624 : // args[0]: object
625 0 : RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
626 0 : HandleScope scope(isolate);
627 : DCHECK_EQ(1, args.length());
628 0 : if (!args[0]->IsJSObject()) {
629 : return Smi::kZero;
630 : }
631 0 : CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
632 :
633 : int result = 0;
634 0 : if (obj->HasNamedInterceptor()) result |= 2;
635 0 : if (obj->HasIndexedInterceptor()) result |= 1;
636 :
637 0 : return Smi::FromInt(result);
638 : }
639 :
640 :
641 186256 : RUNTIME_FUNCTION(Runtime_ToFastProperties) {
642 93128 : HandleScope scope(isolate);
643 : DCHECK_EQ(1, args.length());
644 93128 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
645 186246 : if (object->IsJSObject() && !object->IsJSGlobalObject()) {
646 : JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
647 85266 : "RuntimeToFastProperties");
648 : }
649 93128 : return *object;
650 : }
651 :
652 :
653 56 : RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
654 28 : HandleScope scope(isolate);
655 : DCHECK_EQ(0, args.length());
656 56 : return *isolate->factory()->NewHeapNumber(0);
657 : }
658 :
659 :
660 463600 : RUNTIME_FUNCTION(Runtime_NewObject) {
661 231800 : HandleScope scope(isolate);
662 : DCHECK_EQ(2, args.length());
663 463600 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
664 463600 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1);
665 695400 : RETURN_RESULT_OR_FAILURE(isolate, JSObject::New(target, new_target));
666 : }
667 :
668 :
669 30858 : RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) {
670 15429 : HandleScope scope(isolate);
671 : DCHECK_EQ(1, args.length());
672 :
673 30858 : CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0);
674 15429 : initial_map->CompleteInobjectSlackTracking();
675 :
676 15429 : return isolate->heap()->undefined_value();
677 : }
678 :
679 :
680 0 : RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
681 0 : HandleScope scope(isolate);
682 : DCHECK_EQ(2, args.length());
683 0 : CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
684 0 : CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
685 0 : CHECK_EQ(index->value() & 1, 1);
686 : FieldIndex field_index =
687 0 : FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
688 0 : if (field_index.is_inobject()) {
689 0 : CHECK(field_index.property_index() <
690 : object->map()->GetInObjectProperties());
691 : } else {
692 0 : CHECK(field_index.outobject_array_index() <
693 : object->property_dictionary()->length());
694 : }
695 : return *JSObject::FastPropertyAt(object, Representation::Double(),
696 0 : field_index);
697 : }
698 :
699 :
700 2000036 : RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
701 1000018 : HandleScope scope(isolate);
702 : DCHECK_EQ(1, args.length());
703 1000018 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
704 1000018 : if (!object->IsJSObject()) return Smi::kZero;
705 1000018 : Handle<JSObject> js_object = Handle<JSObject>::cast(object);
706 : // It could have been a DCHECK but we call this function directly from tests.
707 1000018 : if (!js_object->map()->is_deprecated()) return Smi::kZero;
708 : // This call must not cause lazy deopts, because it's called from deferred
709 : // code where we can't handle lazy deopts for lack of a suitable bailout
710 : // ID. So we just try migration and signal failure if necessary,
711 : // which will also trigger a deopt.
712 18 : if (!JSObject::TryMigrateInstance(js_object)) return Smi::kZero;
713 1000018 : return *object;
714 : }
715 :
716 :
717 0 : RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
718 : SealHandleScope shs(isolate);
719 : DCHECK_EQ(1, args.length());
720 0 : CONVERT_ARG_CHECKED(Object, obj, 0);
721 0 : return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
722 : }
723 :
724 200426 : static bool IsValidAccessor(Isolate* isolate, Handle<Object> obj) {
725 301484 : return obj->IsNullOrUndefined(isolate) || obj->IsCallable();
726 : }
727 :
728 :
729 : // Implements part of 8.12.9 DefineOwnProperty.
730 : // There are 3 cases that lead here:
731 : // Step 4b - define a new accessor property.
732 : // Steps 9c & 12 - replace an existing data property with an accessor property.
733 : // Step 12 - update an existing accessor property with an accessor or generic
734 : // descriptor.
735 200426 : RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
736 100213 : HandleScope scope(isolate);
737 : DCHECK_EQ(5, args.length());
738 200426 : CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
739 100213 : CHECK(!obj->IsNull(isolate));
740 200426 : CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
741 100213 : CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
742 100213 : CHECK(IsValidAccessor(isolate, getter));
743 100213 : CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
744 100213 : CHECK(IsValidAccessor(isolate, setter));
745 200426 : CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
746 :
747 100213 : RETURN_FAILURE_ON_EXCEPTION(
748 : isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
749 100208 : return isolate->heap()->undefined_value();
750 : }
751 :
752 :
753 1298614 : RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
754 649307 : HandleScope scope(isolate);
755 : DCHECK_EQ(6, args.length());
756 1298614 : CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
757 1298614 : CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
758 649307 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
759 1298614 : CONVERT_SMI_ARG_CHECKED(flag, 3);
760 1298614 : CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 4);
761 1298614 : CONVERT_SMI_ARG_CHECKED(index, 5);
762 :
763 1298614 : StoreDataPropertyInLiteralICNexus nexus(vector, vector->ToSlot(index));
764 649307 : if (nexus.ic_state() == UNINITIALIZED) {
765 506651 : if (name->IsUniqueName()) {
766 1012888 : nexus.ConfigureMonomorphic(name, handle(object->map()));
767 : } else {
768 207 : nexus.ConfigureMegamorphic(PROPERTY);
769 : }
770 142656 : } else if (nexus.ic_state() == MONOMORPHIC) {
771 394657 : if (nexus.FindFirstMap() != object->map() ||
772 131483 : nexus.GetFeedbackExtra() != *name) {
773 192 : nexus.ConfigureMegamorphic(PROPERTY);
774 : }
775 : }
776 :
777 : DataPropertyInLiteralFlags flags =
778 649307 : static_cast<DataPropertyInLiteralFlag>(flag);
779 :
780 1298614 : PropertyAttributes attrs = (flags & DataPropertyInLiteralFlag::kDontEnum)
781 : ? PropertyAttributes::DONT_ENUM
782 649307 : : PropertyAttributes::NONE;
783 :
784 649307 : if (flags & DataPropertyInLiteralFlag::kSetFunctionName) {
785 : DCHECK(value->IsJSFunction());
786 8294 : Handle<JSFunction> function = Handle<JSFunction>::cast(value);
787 : DCHECK(!function->shared()->has_shared_name());
788 8294 : Handle<Map> function_map(function->map(), isolate);
789 8294 : if (!JSFunction::SetName(function, name,
790 8294 : isolate->factory()->empty_string())) {
791 10 : return isolate->heap()->exception();
792 : }
793 : // Class constructors do not reserve in-object space for name field.
794 16559 : CHECK_IMPLIES(!IsClassConstructor(function->shared()->kind()),
795 : *function_map == function->map());
796 : }
797 :
798 : LookupIterator it = LookupIterator::PropertyOrElement(
799 649297 : isolate, object, name, object, LookupIterator::OWN);
800 : // Cannot fail since this should only be called when
801 : // creating an object literal.
802 649297 : CHECK(JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attrs,
803 : Object::DONT_THROW)
804 : .IsJust());
805 649307 : return *object;
806 : }
807 :
808 570 : RUNTIME_FUNCTION(Runtime_CollectTypeProfile) {
809 285 : HandleScope scope(isolate);
810 : DCHECK_EQ(3, args.length());
811 570 : CONVERT_ARG_HANDLE_CHECKED(Smi, position, 0);
812 285 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
813 570 : CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 2);
814 :
815 285 : Handle<String> type = Object::TypeOf(isolate, value);
816 285 : if (value->IsJSReceiver()) {
817 105 : Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
818 105 : type = JSReceiver::GetConstructorName(object);
819 180 : } else if (value->IsNull(isolate)) {
820 : // typeof(null) is object. But it's more user-friendly to annotate
821 : // null as type "null".
822 70 : type = Handle<String>(isolate->heap()->null_string());
823 : }
824 :
825 : DCHECK(vector->metadata()->HasTypeProfileSlot());
826 570 : CollectTypeProfileNexus nexus(vector, vector->GetTypeProfileSlot());
827 285 : nexus.Collect(type, position->value());
828 :
829 570 : return isolate->heap()->undefined_value();
830 : }
831 :
832 : // Return property without being observable by accessors or interceptors.
833 0 : RUNTIME_FUNCTION(Runtime_GetDataProperty) {
834 0 : HandleScope scope(isolate);
835 : DCHECK_EQ(2, args.length());
836 0 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
837 0 : CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
838 0 : return *JSReceiver::GetDataProperty(object, name);
839 : }
840 :
841 0 : RUNTIME_FUNCTION(Runtime_GetConstructorName) {
842 0 : HandleScope scope(isolate);
843 : DCHECK_EQ(1, args.length());
844 0 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
845 :
846 0 : CHECK(!object->IsNullOrUndefined(isolate));
847 0 : Handle<JSReceiver> recv = Object::ToObject(isolate, object).ToHandleChecked();
848 0 : return *JSReceiver::GetConstructorName(recv);
849 : }
850 :
851 7870 : RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
852 : SealHandleScope shs(isolate);
853 : DCHECK_EQ(1, args.length());
854 7870 : CONVERT_ARG_CHECKED(HeapObject, obj, 0);
855 : return isolate->heap()->ToBoolean(
856 3935 : IsFastPackedElementsKind(obj->map()->elements_kind()));
857 : }
858 :
859 :
860 0 : RUNTIME_FUNCTION(Runtime_ValueOf) {
861 : SealHandleScope shs(isolate);
862 : DCHECK_EQ(1, args.length());
863 0 : CONVERT_ARG_CHECKED(Object, obj, 0);
864 0 : if (!obj->IsJSValue()) return obj;
865 0 : return JSValue::cast(obj)->value();
866 : }
867 :
868 :
869 3096 : RUNTIME_FUNCTION(Runtime_IsJSReceiver) {
870 : SealHandleScope shs(isolate);
871 : DCHECK_EQ(1, args.length());
872 1548 : CONVERT_ARG_CHECKED(Object, obj, 0);
873 1548 : return isolate->heap()->ToBoolean(obj->IsJSReceiver());
874 : }
875 :
876 :
877 20 : RUNTIME_FUNCTION(Runtime_ClassOf) {
878 : SealHandleScope shs(isolate);
879 : DCHECK_EQ(1, args.length());
880 10 : CONVERT_ARG_CHECKED(Object, obj, 0);
881 10 : if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
882 10 : return JSReceiver::cast(obj)->class_name();
883 : }
884 :
885 :
886 14488 : RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
887 7244 : HandleScope scope(isolate);
888 : DCHECK_EQ(4, args.length());
889 14488 : CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
890 14488 : CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
891 14488 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
892 14488 : CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
893 :
894 7244 : if (String::cast(getter->shared()->name())->length() == 0) {
895 2262 : Handle<Map> getter_map(getter->map(), isolate);
896 2262 : if (!JSFunction::SetName(getter, name, isolate->factory()->get_string())) {
897 10 : return isolate->heap()->exception();
898 : }
899 4504 : CHECK_EQ(*getter_map, getter->map());
900 : }
901 :
902 14468 : RETURN_FAILURE_ON_EXCEPTION(
903 : isolate,
904 : JSObject::DefineAccessor(object, name, getter,
905 : isolate->factory()->null_value(), attrs));
906 7234 : return isolate->heap()->undefined_value();
907 : }
908 :
909 720 : RUNTIME_FUNCTION(Runtime_CopyDataProperties) {
910 360 : HandleScope scope(isolate);
911 : DCHECK_EQ(2, args.length());
912 720 : CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
913 360 : CONVERT_ARG_HANDLE_CHECKED(Object, source, 1);
914 :
915 : // 2. If source is undefined or null, let keys be an empty List.
916 711 : if (source->IsUndefined(isolate) || source->IsNull(isolate)) {
917 18 : return isolate->heap()->undefined_value();
918 : }
919 :
920 342 : MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(isolate, target, source,
921 : nullptr, false),
922 : isolate->heap()->exception());
923 306 : return isolate->heap()->undefined_value();
924 : }
925 :
926 558 : RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedProperties) {
927 279 : HandleScope scope(isolate);
928 : DCHECK_LE(1, args.length());
929 279 : CONVERT_ARG_HANDLE_CHECKED(Object, source, 0);
930 :
931 : // 2. If source is undefined or null, let keys be an empty List.
932 558 : if (source->IsUndefined(isolate) || source->IsNull(isolate)) {
933 0 : return isolate->heap()->undefined_value();
934 : }
935 :
936 558 : ScopedVector<Handle<Object>> excluded_properties(args.length() - 1);
937 189 : for (int i = 1; i < args.length(); i++) {
938 189 : Handle<Object> property = args.at(i);
939 : uint32_t property_num;
940 : // We convert string to number if possible, in cases of computed
941 : // properties resolving to numbers, which would've been strings
942 : // instead because of our call to %ToName() in the desugaring for
943 : // computed properties.
944 351 : if (property->IsString() &&
945 162 : String::cast(*property)->AsArrayIndex(&property_num)) {
946 36 : property = isolate->factory()->NewNumberFromUint(property_num);
947 : }
948 :
949 189 : excluded_properties[i - 1] = property;
950 : }
951 :
952 : Handle<JSObject> target =
953 279 : isolate->factory()->NewJSObject(isolate->object_function());
954 279 : MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(isolate, target, source,
955 : &excluded_properties, false),
956 : isolate->heap()->exception());
957 279 : return *target;
958 : }
959 :
960 : namespace {
961 :
962 976 : inline void TrySetNative(Handle<Object> maybe_func) {
963 1952 : if (!maybe_func->IsJSFunction()) return;
964 : JSFunction::cast(*maybe_func)->shared()->set_native(true);
965 : }
966 :
967 2867 : inline void TrySetNativeAndLength(Handle<Object> maybe_func, int length) {
968 5734 : if (!maybe_func->IsJSFunction()) return;
969 : SharedFunctionInfo* shared = JSFunction::cast(*maybe_func)->shared();
970 : shared->set_native(true);
971 2867 : if (length >= 0) {
972 : shared->set_length(length);
973 : }
974 : }
975 :
976 : } // namespace
977 :
978 9516 : RUNTIME_FUNCTION(Runtime_DefineMethodsInternal) {
979 3172 : HandleScope scope(isolate);
980 : DCHECK_EQ(3, args.length());
981 3172 : CHECK(isolate->bootstrapper()->IsActive());
982 6344 : CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
983 6344 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, source_class, 1);
984 6344 : CONVERT_SMI_ARG_CHECKED(length, 2);
985 :
986 : DCHECK(source_class->prototype()->IsJSObject());
987 3172 : Handle<JSObject> source(JSObject::cast(source_class->prototype()), isolate);
988 :
989 : Handle<FixedArray> keys;
990 6344 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
991 : isolate, keys,
992 : KeyAccumulator::GetKeys(source, KeyCollectionMode::kOwnOnly,
993 : ALL_PROPERTIES,
994 : GetKeysConversion::kConvertToString));
995 :
996 16226 : for (int i = 0; i < keys->length(); ++i) {
997 6527 : Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
998 9699 : if (*key == isolate->heap()->constructor_string()) continue;
999 :
1000 3355 : PropertyDescriptor descriptor;
1001 : Maybe<bool> did_get_descriptor =
1002 3355 : JSReceiver::GetOwnPropertyDescriptor(isolate, source, key, &descriptor);
1003 3355 : CHECK(did_get_descriptor.FromJust());
1004 3355 : if (descriptor.has_value()) {
1005 2867 : TrySetNativeAndLength(descriptor.value(), length);
1006 : } else {
1007 488 : if (descriptor.has_get()) TrySetNative(descriptor.get());
1008 488 : if (descriptor.has_set()) TrySetNative(descriptor.set());
1009 : }
1010 :
1011 : Maybe<bool> success = JSReceiver::DefineOwnProperty(
1012 3355 : isolate, target, key, &descriptor, Object::DONT_THROW);
1013 3355 : CHECK(success.FromJust());
1014 : }
1015 3172 : return isolate->heap()->undefined_value();
1016 : }
1017 :
1018 4568 : RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
1019 2284 : HandleScope scope(isolate);
1020 : DCHECK_EQ(4, args.length());
1021 4568 : CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1022 4568 : CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1023 4568 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
1024 4568 : CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1025 :
1026 2284 : if (String::cast(setter->shared()->name())->length() == 0) {
1027 199 : Handle<Map> setter_map(setter->map(), isolate);
1028 199 : if (!JSFunction::SetName(setter, name, isolate->factory()->set_string())) {
1029 10 : return isolate->heap()->exception();
1030 : }
1031 378 : CHECK_EQ(*setter_map, setter->map());
1032 : }
1033 :
1034 4548 : RETURN_FAILURE_ON_EXCEPTION(
1035 : isolate,
1036 : JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1037 : setter, attrs));
1038 2274 : return isolate->heap()->undefined_value();
1039 : }
1040 :
1041 :
1042 0 : RUNTIME_FUNCTION(Runtime_ToObject) {
1043 0 : HandleScope scope(isolate);
1044 : DCHECK_EQ(1, args.length());
1045 0 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1046 0 : RETURN_RESULT_OR_FAILURE(isolate, Object::ToObject(isolate, object));
1047 : }
1048 :
1049 :
1050 234 : RUNTIME_FUNCTION(Runtime_ToPrimitive) {
1051 117 : HandleScope scope(isolate);
1052 : DCHECK_EQ(1, args.length());
1053 117 : CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1054 351 : RETURN_RESULT_OR_FAILURE(isolate, Object::ToPrimitive(input));
1055 : }
1056 :
1057 :
1058 234 : RUNTIME_FUNCTION(Runtime_ToPrimitive_Number) {
1059 117 : HandleScope scope(isolate);
1060 : DCHECK_EQ(1, args.length());
1061 117 : CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1062 234 : RETURN_RESULT_OR_FAILURE(
1063 117 : isolate, Object::ToPrimitive(input, ToPrimitiveHint::kNumber));
1064 : }
1065 :
1066 5332 : RUNTIME_FUNCTION(Runtime_ToNumber) {
1067 2666 : HandleScope scope(isolate);
1068 : DCHECK_EQ(1, args.length());
1069 2666 : CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1070 7998 : RETURN_RESULT_OR_FAILURE(isolate, Object::ToNumber(input));
1071 : }
1072 :
1073 1720 : RUNTIME_FUNCTION(Runtime_ToNumeric) {
1074 860 : HandleScope scope(isolate);
1075 : DCHECK_EQ(1, args.length());
1076 860 : CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1077 2580 : RETURN_RESULT_OR_FAILURE(isolate, Object::ToNumeric(input));
1078 : }
1079 :
1080 0 : RUNTIME_FUNCTION(Runtime_ToInteger) {
1081 0 : HandleScope scope(isolate);
1082 : DCHECK_EQ(1, args.length());
1083 0 : CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1084 0 : RETURN_RESULT_OR_FAILURE(isolate, Object::ToInteger(isolate, input));
1085 : }
1086 :
1087 :
1088 360 : RUNTIME_FUNCTION(Runtime_ToLength) {
1089 180 : HandleScope scope(isolate);
1090 : DCHECK_EQ(1, args.length());
1091 180 : CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1092 540 : RETURN_RESULT_OR_FAILURE(isolate, Object::ToLength(isolate, input));
1093 : }
1094 :
1095 :
1096 7518224 : RUNTIME_FUNCTION(Runtime_ToString) {
1097 3759112 : HandleScope scope(isolate);
1098 : DCHECK_EQ(1, args.length());
1099 3759112 : CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1100 11277336 : RETURN_RESULT_OR_FAILURE(isolate, Object::ToString(isolate, input));
1101 : }
1102 :
1103 :
1104 1032 : RUNTIME_FUNCTION(Runtime_ToName) {
1105 516 : HandleScope scope(isolate);
1106 : DCHECK_EQ(1, args.length());
1107 516 : CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1108 1548 : RETURN_RESULT_OR_FAILURE(isolate, Object::ToName(isolate, input));
1109 : }
1110 :
1111 :
1112 144 : RUNTIME_FUNCTION(Runtime_SameValue) {
1113 : SealHandleScope scope(isolate);
1114 : DCHECK_EQ(2, args.length());
1115 72 : CONVERT_ARG_CHECKED(Object, x, 0);
1116 72 : CONVERT_ARG_CHECKED(Object, y, 1);
1117 72 : return isolate->heap()->ToBoolean(x->SameValue(y));
1118 : }
1119 :
1120 :
1121 1264 : RUNTIME_FUNCTION(Runtime_SameValueZero) {
1122 : SealHandleScope scope(isolate);
1123 : DCHECK_EQ(2, args.length());
1124 632 : CONVERT_ARG_CHECKED(Object, x, 0);
1125 632 : CONVERT_ARG_CHECKED(Object, y, 1);
1126 632 : return isolate->heap()->ToBoolean(x->SameValueZero(y));
1127 : }
1128 :
1129 :
1130 : // TODO(bmeurer): Kill this special wrapper and use TF compatible LessThan,
1131 : // GreaterThan, etc. which return true or false.
1132 0 : RUNTIME_FUNCTION(Runtime_Compare) {
1133 0 : HandleScope scope(isolate);
1134 : DCHECK_EQ(3, args.length());
1135 0 : CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
1136 0 : CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
1137 0 : CONVERT_ARG_HANDLE_CHECKED(Object, ncr, 2);
1138 0 : Maybe<ComparisonResult> result = Object::Compare(x, y);
1139 0 : if (result.IsJust()) {
1140 0 : switch (result.FromJust()) {
1141 : case ComparisonResult::kLessThan:
1142 0 : return Smi::FromInt(LESS);
1143 : case ComparisonResult::kEqual:
1144 0 : return Smi::FromInt(EQUAL);
1145 : case ComparisonResult::kGreaterThan:
1146 0 : return Smi::FromInt(GREATER);
1147 : case ComparisonResult::kUndefined:
1148 : return *ncr;
1149 : }
1150 0 : UNREACHABLE();
1151 : }
1152 0 : return isolate->heap()->exception();
1153 : }
1154 :
1155 1840 : RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
1156 920 : HandleScope scope(isolate);
1157 : DCHECK_EQ(2, args.length());
1158 920 : CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1159 920 : CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1160 920 : if (!object->IsJSReceiver()) return isolate->heap()->false_value();
1161 : Maybe<bool> result = JSReceiver::HasInPrototypeChain(
1162 920 : isolate, Handle<JSReceiver>::cast(object), prototype);
1163 920 : MAYBE_RETURN(result, isolate->heap()->exception());
1164 811 : return isolate->heap()->ToBoolean(result.FromJust());
1165 : }
1166 :
1167 :
1168 : // ES6 section 7.4.7 CreateIterResultObject ( value, done )
1169 36 : RUNTIME_FUNCTION(Runtime_CreateIterResultObject) {
1170 18 : HandleScope scope(isolate);
1171 : DCHECK_EQ(2, args.length());
1172 18 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
1173 18 : CONVERT_ARG_HANDLE_CHECKED(Object, done, 1);
1174 36 : return *isolate->factory()->NewJSIteratorResult(value, done->BooleanValue());
1175 : }
1176 :
1177 2077390 : RUNTIME_FUNCTION(Runtime_CreateDataProperty) {
1178 1038695 : HandleScope scope(isolate);
1179 : DCHECK_EQ(3, args.length());
1180 2077390 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, o, 0);
1181 1038695 : CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1182 1038695 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1183 : bool success;
1184 : LookupIterator it = LookupIterator::PropertyOrElement(
1185 1038695 : isolate, o, key, &success, LookupIterator::OWN);
1186 1038695 : if (!success) return isolate->heap()->exception();
1187 1038695 : MAYBE_RETURN(
1188 : JSReceiver::CreateDataProperty(&it, value, Object::THROW_ON_ERROR),
1189 : isolate->heap()->exception());
1190 1038695 : return *value;
1191 : }
1192 :
1193 : // Checks that 22.2.2.1.1 Runtime Semantics: IterableToList produces exactly the
1194 : // same result as doing nothing.
1195 52384 : RUNTIME_FUNCTION(Runtime_IterableToListCanBeElided) {
1196 26192 : HandleScope scope(isolate);
1197 : DCHECK_EQ(1, args.length());
1198 52384 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
1199 :
1200 26192 : if (!obj->IsJSObject()) return isolate->heap()->ToBoolean(false);
1201 :
1202 : // While iteration alone may not have observable side-effects, calling
1203 : // toNumber on an object will. Make sure the arg is not an array of objects.
1204 26192 : ElementsKind kind = JSObject::cast(*obj)->GetElementsKind();
1205 26192 : if (!IsFastNumberElementsKind(kind)) return isolate->heap()->ToBoolean(false);
1206 :
1207 25453 : return isolate->heap()->ToBoolean(!obj->IterationHasObservableEffects());
1208 : }
1209 :
1210 4327270 : RUNTIME_FUNCTION(Runtime_GetOwnPropertyDescriptor) {
1211 2163635 : HandleScope scope(isolate);
1212 :
1213 : DCHECK_EQ(2, args.length());
1214 4327270 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
1215 4327270 : CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1216 :
1217 2163635 : PropertyDescriptor desc;
1218 : Maybe<bool> found =
1219 2163635 : JSReceiver::GetOwnPropertyDescriptor(isolate, object, name, &desc);
1220 2163635 : MAYBE_RETURN(found, isolate->heap()->exception());
1221 :
1222 2163302 : if (!found.FromJust()) return isolate->heap()->undefined_value();
1223 4325230 : return *desc.ToPropertyDescriptorObject(isolate);
1224 : }
1225 :
1226 : } // namespace internal
1227 : } // namespace v8
|