5 #include "src/builtins/builtins-object-gen.h" 7 #include "src/builtins/builtins-utils-gen.h" 8 #include "src/builtins/builtins.h" 9 #include "src/code-stub-assembler.h" 10 #include "src/heap/factory-inl.h" 11 #include "src/ic/accessor-assembler.h" 12 #include "src/ic/keyed-store-generic.h" 13 #include "src/objects/js-generator.h" 14 #include "src/objects/property-descriptor-object.h" 15 #include "src/objects/shared-function-info.h" 16 #include "src/property-details.h" 24 typedef compiler::Node Node;
26 using TNode = CodeStubAssembler::TNode<T>;
34 void ReturnToStringFormat(
Node* context,
Node*
string);
43 Node* enumerable,
Node* configurable);
45 Node* enumerable,
Node* configurable);
46 Node* GetAccessorOrUndefined(
Node* accessor,
Label* if_bailout);
63 enum CollectType { kEntries, kValues };
74 return DecodeWord32<PropertyDetails::KindField>(details);
78 CollectType collect_type);
84 Label* if_call_runtime_with_fast_path,
Label* if_no_properties,
85 CollectType collect_type);
92 void ObjectBuiltinsAssembler::ReturnToStringFormat(
Node* context,
94 Node* lhs = StringConstant(
"[object ");
95 Node* rhs = StringConstant(
"]");
97 Callable callable = CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE);
99 Return(CallStub(callable, context, CallStub(callable, context, lhs,
string),
103 Node* ObjectBuiltinsAssembler::ConstructAccessorDescriptor(Node* context,
107 Node* configurable) {
108 Node* native_context = LoadNativeContext(context);
109 Node* map = LoadContextElement(
110 native_context, Context::ACCESSOR_PROPERTY_DESCRIPTOR_MAP_INDEX);
111 Node* js_desc = AllocateJSObjectFromMap(map);
113 StoreObjectFieldNoWriteBarrier(
114 js_desc, JSAccessorPropertyDescriptor::kGetOffset, getter);
115 StoreObjectFieldNoWriteBarrier(
116 js_desc, JSAccessorPropertyDescriptor::kSetOffset, setter);
117 StoreObjectFieldNoWriteBarrier(
118 js_desc, JSAccessorPropertyDescriptor::kEnumerableOffset,
119 SelectBooleanConstant(enumerable));
120 StoreObjectFieldNoWriteBarrier(
121 js_desc, JSAccessorPropertyDescriptor::kConfigurableOffset,
122 SelectBooleanConstant(configurable));
127 Node* ObjectBuiltinsAssembler::ConstructDataDescriptor(Node* context,
131 Node* configurable) {
132 Node* native_context = LoadNativeContext(context);
133 Node* map = LoadContextElement(native_context,
134 Context::DATA_PROPERTY_DESCRIPTOR_MAP_INDEX);
135 Node* js_desc = AllocateJSObjectFromMap(map);
137 StoreObjectFieldNoWriteBarrier(js_desc,
138 JSDataPropertyDescriptor::kValueOffset, value);
139 StoreObjectFieldNoWriteBarrier(js_desc,
140 JSDataPropertyDescriptor::kWritableOffset,
141 SelectBooleanConstant(writable));
142 StoreObjectFieldNoWriteBarrier(js_desc,
143 JSDataPropertyDescriptor::kEnumerableOffset,
144 SelectBooleanConstant(enumerable));
145 StoreObjectFieldNoWriteBarrier(js_desc,
146 JSDataPropertyDescriptor::kConfigurableOffset,
147 SelectBooleanConstant(configurable));
152 Node* ObjectBuiltinsAssembler::IsSpecialReceiverMap(SloppyTNode<Map> map) {
153 CSA_SLOW_ASSERT(
this, IsMap(map));
154 TNode<BoolT> is_special =
155 IsSpecialReceiverInstanceType(LoadMapInstanceType(map));
157 Map::HasNamedInterceptorBit::kMask | Map::IsAccessCheckNeededBit::kMask;
161 SelectConstant<BoolT>(IsSetWord32(LoadMapBitField(map), mask),
162 is_special, Int32TrueConstant()));
166 TNode<Word32T> ObjectBuiltinsAssembler::IsStringWrapperElementsKind(
168 Node* kind = LoadMapElementsKind(map);
170 Word32Equal(kind, Int32Constant(FAST_STRING_WRAPPER_ELEMENTS)),
171 Word32Equal(kind, Int32Constant(SLOW_STRING_WRAPPER_ELEMENTS)));
174 TNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyEnumerable(
175 TNode<Uint32T> details) {
176 TNode<Uint32T> attributes =
177 DecodeWord32<PropertyDetails::AttributesField>(details);
178 return IsNotSetWord32(attributes, PropertyAttributes::DONT_ENUM);
181 TNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyKindAccessor(
182 TNode<Uint32T> kind) {
183 return Word32Equal(kind, Int32Constant(PropertyKind::kAccessor));
186 TNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyKindData(
187 TNode<Uint32T> kind) {
188 return Word32Equal(kind, Int32Constant(PropertyKind::kData));
191 TNode<Uint32T> ObjectEntriesValuesBuiltinsAssembler::HasHiddenPrototype(
193 TNode<Uint32T> bit_field3 = LoadMapBitField3(map);
194 return DecodeWord32<Map::HasHiddenPrototypeBit>(bit_field3);
197 void ObjectEntriesValuesBuiltinsAssembler::GetOwnValuesOrEntries(
198 TNode<Context> context, TNode<Object> maybe_object,
199 CollectType collect_type) {
200 TNode<JSReceiver> receiver = ToObject_Inline(context, maybe_object);
202 Label if_call_runtime_with_fast_path(
this, Label::kDeferred),
203 if_call_runtime(
this, Label::kDeferred),
204 if_no_properties(
this, Label::kDeferred);
206 TNode<Map> map = LoadMap(receiver);
207 GotoIfNot(IsJSObjectMap(map), &if_call_runtime);
208 GotoIfMapHasSlowProperties(map, &if_call_runtime);
210 TNode<JSObject>
object = CAST(receiver);
211 TNode<FixedArrayBase> elements = LoadElements(
object);
214 GotoIfNot(IsEmptyFixedArray(elements), &if_call_runtime_with_fast_path);
216 TNode<JSArray> result = FastGetOwnValuesOrEntries(
217 context,
object, &if_call_runtime_with_fast_path, &if_no_properties,
221 BIND(&if_no_properties);
223 Node* native_context = LoadNativeContext(context);
224 TNode<Map> array_map =
225 LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
226 TNode<JSArray> empty_array = AllocateJSArray(
227 PACKED_ELEMENTS, array_map, IntPtrConstant(0), SmiConstant(0));
231 BIND(&if_call_runtime_with_fast_path);
234 if (collect_type == CollectType::kEntries) {
235 Return(CallRuntime(Runtime::kObjectEntries, context,
object));
237 DCHECK(collect_type == CollectType::kValues);
238 Return(CallRuntime(Runtime::kObjectValues, context,
object));
242 BIND(&if_call_runtime);
245 if (collect_type == CollectType::kEntries) {
247 CallRuntime(Runtime::kObjectEntriesSkipFastPath, context, receiver));
249 DCHECK(collect_type == CollectType::kValues);
251 CallRuntime(Runtime::kObjectValuesSkipFastPath, context, receiver));
256 void ObjectEntriesValuesBuiltinsAssembler::GotoIfMapHasSlowProperties(
257 TNode<Map> map, Label* if_slow) {
258 GotoIf(IsStringWrapperElementsKind(map), if_slow);
259 GotoIf(IsSpecialReceiverMap(map), if_slow);
260 GotoIf(HasHiddenPrototype(map), if_slow);
261 GotoIf(IsDictionaryMap(map), if_slow);
264 TNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries(
265 TNode<Context> context, TNode<JSObject>
object,
266 Label* if_call_runtime_with_fast_path, Label* if_no_properties,
267 CollectType collect_type) {
268 TNode<Context> native_context = LoadNativeContext(context);
269 TNode<Map> array_map =
270 LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
271 TNode<Map> map = LoadMap(
object);
272 TNode<Uint32T> bit_field3 = LoadMapBitField3(map);
274 Label if_has_enum_cache(
this), if_not_has_enum_cache(
this),
275 collect_entries(
this);
276 TNode<IntPtrT> object_enum_length =
277 Signed(DecodeWordFromWord32<Map::EnumLengthBits>(bit_field3));
278 TNode<BoolT> has_enum_cache = WordNotEqual(
279 object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel));
289 Branch(has_enum_cache, &if_has_enum_cache, if_call_runtime_with_fast_path);
291 BIND(&if_has_enum_cache);
293 GotoIf(WordEqual(object_enum_length, IntPtrConstant(0)), if_no_properties);
294 TNode<FixedArray> values_or_entries = CAST(AllocateFixedArray(
295 PACKED_ELEMENTS, object_enum_length, kAllowLargeObjectAllocation));
303 FillFixedArrayWithValue(PACKED_ELEMENTS, values_or_entries,
304 IntPtrConstant(0), object_enum_length,
305 RootIndex::kTheHoleValue);
307 TVARIABLE(IntPtrT, var_result_index, IntPtrConstant(0));
308 TVARIABLE(IntPtrT, var_descriptor_number, IntPtrConstant(0));
309 Variable* vars[] = {&var_descriptor_number, &var_result_index};
311 TNode<DescriptorArray> descriptors = LoadMapDescriptors(map);
312 Label loop(
this, 2, vars), after_loop(
this), next_descriptor(
this);
313 Branch(IntPtrEqual(var_descriptor_number.value(), object_enum_length),
323 CSA_ASSERT(
this, WordEqual(map, LoadMap(
object)));
324 TNode<IntPtrT> descriptor_entry = var_descriptor_number.value();
325 Node* next_key = LoadKeyByDescriptorEntry(descriptors, descriptor_entry);
328 GotoIf(IsSymbol(next_key), &next_descriptor);
330 TNode<Uint32T> details =
331 LoadDetailsByDescriptorEntry(descriptors, descriptor_entry);
333 TNode<Uint32T> kind = LoadPropertyKind(details);
336 GotoIf(IsPropertyKindAccessor(kind), if_call_runtime_with_fast_path);
337 CSA_ASSERT(
this, IsPropertyKindData(kind));
341 GotoIfNot(IsPropertyEnumerable(details), &next_descriptor);
343 TVARIABLE(Object, var_property_value, UndefinedConstant());
344 TNode<IntPtrT> descriptor_name_index = ToKeyIndex<DescriptorArray>(
345 Unsigned(TruncateIntPtrToInt32(var_descriptor_number.value())));
348 LoadPropertyFromFastObject(
object, map, descriptors,
349 descriptor_name_index, details,
350 &var_property_value);
353 TNode<Object> value = var_property_value.value();
355 if (collect_type == CollectType::kEntries) {
357 Node* array =
nullptr;
358 Node* elements =
nullptr;
359 std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
360 PACKED_ELEMENTS, array_map, SmiConstant(2),
nullptr,
362 StoreFixedArrayElement(CAST(elements), 0, next_key, SKIP_WRITE_BARRIER);
363 StoreFixedArrayElement(CAST(elements), 1, value, SKIP_WRITE_BARRIER);
364 value = TNode<JSArray>::UncheckedCast(array);
367 StoreFixedArrayElement(values_or_entries, var_result_index.value(),
369 Increment(&var_result_index, 1);
370 Goto(&next_descriptor);
372 BIND(&next_descriptor);
374 Increment(&var_descriptor_number, 1);
375 Branch(IntPtrEqual(var_result_index.value(), object_enum_length),
380 return FinalizeValuesOrEntriesJSArray(context, values_or_entries,
381 var_result_index.value(), array_map,
387 ObjectEntriesValuesBuiltinsAssembler::FinalizeValuesOrEntriesJSArray(
388 TNode<Context> context, TNode<FixedArray> result, TNode<IntPtrT> size,
389 TNode<Map> array_map, Label* if_empty) {
390 CSA_ASSERT(
this, IsJSArrayMap(array_map));
392 GotoIf(IntPtrEqual(size, IntPtrConstant(0)), if_empty);
393 Node* array = AllocateUninitializedJSArrayWithoutElements(
394 array_map, SmiTag(size),
nullptr);
395 StoreObjectField(array, JSArray::kElementsOffset, result);
396 return TNode<JSArray>::UncheckedCast(array);
399 TF_BUILTIN(ObjectPrototypeToLocaleString, CodeStubAssembler) {
400 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
401 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
403 Label if_null_or_undefined(
this, Label::kDeferred);
404 GotoIf(IsNullOrUndefined(receiver), &if_null_or_undefined);
406 TNode<Object> method =
407 GetProperty(context, receiver, factory()->toString_string());
408 Return(CallJS(CodeFactory::Call(isolate()), context, method, receiver));
410 BIND(&if_null_or_undefined);
411 ThrowTypeError(context, MessageTemplate::kCalledOnNullOrUndefined,
412 "Object.prototype.toLocaleString");
415 TF_BUILTIN(ObjectPrototypeHasOwnProperty, ObjectBuiltinsAssembler) {
416 Node*
object = Parameter(Descriptor::kReceiver);
417 Node* key = Parameter(Descriptor::kKey);
418 Node* context = Parameter(Descriptor::kContext);
420 Label call_runtime(
this), return_true(
this), return_false(
this),
425 Label if_objectisnotsmi(
this);
426 Branch(TaggedIsSmi(
object), &to_primitive, &if_objectisnotsmi);
427 BIND(&if_objectisnotsmi);
429 Node* map = LoadMap(
object);
430 TNode<Int32T> instance_type = LoadMapInstanceType(map);
433 VARIABLE(var_index, MachineType::PointerRepresentation());
434 VARIABLE(var_unique, MachineRepresentation::kTagged);
436 Label if_index(
this), if_unique_name(
this), if_notunique_name(
this);
437 TryToName(key, &if_index, &var_index, &if_unique_name, &var_unique,
438 &call_runtime, &if_notunique_name);
440 BIND(&if_unique_name);
441 TryHasOwnProperty(
object, map, instance_type, var_unique.value(),
442 &return_true, &return_false, &call_runtime);
447 GotoIf(IntPtrLessThan(var_index.value(), IntPtrConstant(0)),
449 TryLookupElement(
object, map, instance_type, var_index.value(),
450 &return_true, &return_false, &return_false,
454 BIND(&if_notunique_name);
456 Label not_in_string_table(
this);
457 TryInternalizeString(key, &if_index, &var_index, &if_unique_name,
458 &var_unique, ¬_in_string_table, &call_runtime);
460 BIND(¬_in_string_table);
465 Branch(IsSpecialReceiverInstanceType(instance_type), &call_runtime,
471 GotoIf(IsNumber(key), &return_false);
472 Branch(IsName(key), &return_false, &call_runtime);
475 Return(TrueConstant());
478 Return(FalseConstant());
481 Return(CallRuntime(Runtime::kObjectHasOwnProperty, context,
object, key));
485 TF_BUILTIN(ObjectAssign, ObjectBuiltinsAssembler) {
486 TNode<IntPtrT> argc =
487 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
488 CodeStubArguments args(
this, argc);
490 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
491 TNode<Object> target = args.GetOptionalArgumentValue(0);
494 TNode<JSReceiver> to = ToObject_Inline(context, target);
498 GotoIf(UintPtrLessThanOrEqual(argc, IntPtrConstant(1)), &done);
504 [=](Node* next_source_) {
505 TNode<Object> next_source = CAST(next_source_);
506 Label slow(
this), cont(
this);
507 ObjectAssignFast(context, to, next_source, &slow);
512 CallRuntime(Runtime::kSetDataProperties, context, to, next_source);
522 args.PopAndReturn(to);
526 void ObjectBuiltinsAssembler::ObjectAssignFast(TNode<Context> context,
527 TNode<JSReceiver> to,
534 GotoIf(TaggedIsSmi(from), &done);
535 TNode<Map> from_map = LoadMap(CAST(from));
536 TNode<Int32T> from_instance_type = LoadMapInstanceType(from_map);
539 GotoIf(IsJSReceiverInstanceType(from_instance_type), &cont);
540 GotoIfNot(IsStringInstanceType(from_instance_type), &done);
543 Word32Equal(LoadStringLengthAsWord32(CAST(from)), Int32Constant(0)),
552 TNode<Map> to_map = LoadMap(to);
553 GotoIf(IsDeprecatedMap(to_map), slow);
554 TNode<BoolT> to_is_simple_receiver = IsSimpleObjectMap(to_map);
556 GotoIfNot(IsJSObjectInstanceType(from_instance_type), slow);
557 GotoIfNot(IsEmptyFixedArray(LoadElements(CAST(from))), slow);
559 ForEachEnumerableOwnProperty(context, from_map, CAST(from),
560 [=](TNode<Name> key, TNode<Object> value) {
561 KeyedStoreGenericGenerator::SetProperty(
562 state(), context, to,
563 to_is_simple_receiver, key, value,
564 LanguageMode::kStrict);
573 TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) {
574 Node*
object = Parameter(Descriptor::kObject);
575 Node* context = Parameter(Descriptor::kContext);
577 VARIABLE(var_length, MachineRepresentation::kTagged);
578 VARIABLE(var_elements, MachineRepresentation::kTagged);
579 Label if_empty(
this, Label::kDeferred), if_empty_elements(
this),
580 if_fast(
this), if_slow(
this, Label::kDeferred), if_join(
this);
583 GotoIf(TaggedIsSmi(
object), &if_slow);
584 Node* object_map = LoadMap(
object);
585 Node* object_bit_field3 = LoadMapBitField3(object_map);
586 Node* object_enum_length =
587 DecodeWordFromWord32<Map::EnumLengthBits>(object_bit_field3);
589 WordEqual(object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)),
593 CSA_ASSERT(
this, IsJSObjectMap(object_map));
594 Node* object_elements = LoadElements(
object);
595 GotoIf(IsEmptyFixedArray(object_elements), &if_empty_elements);
596 Branch(IsEmptySlowElementDictionary(object_elements), &if_empty_elements,
600 BIND(&if_empty_elements);
601 Branch(WordEqual(object_enum_length, IntPtrConstant(0)), &if_empty, &if_fast);
606 Node* object_descriptors = LoadMapDescriptors(object_map);
607 Node* object_enum_cache =
608 LoadObjectField(object_descriptors, DescriptorArray::kEnumCacheOffset);
609 Node* object_enum_keys =
610 LoadObjectField(object_enum_cache, EnumCache::kKeysOffset);
613 Node* array =
nullptr;
614 Node* elements =
nullptr;
615 Node* native_context = LoadNativeContext(context);
616 TNode<Map> array_map =
617 LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
618 TNode<Smi> array_length = SmiTag(object_enum_length);
619 std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
620 PACKED_ELEMENTS, array_map, array_length,
nullptr, object_enum_length,
622 CopyFixedArrayElements(PACKED_ELEMENTS, object_enum_keys, elements,
623 object_enum_length, SKIP_WRITE_BARRIER);
630 var_length.Bind(SmiConstant(0));
631 var_elements.Bind(EmptyFixedArrayConstant());
638 Node* elements = CallRuntime(Runtime::kObjectKeys, context,
object);
639 var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset));
640 var_elements.Bind(elements);
647 Node* native_context = LoadNativeContext(context);
648 TNode<Map> array_map =
649 LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
650 TNode<JSArray> array = AllocateUninitializedJSArrayWithoutElements(
651 array_map, CAST(var_length.value()),
nullptr);
652 StoreObjectFieldNoWriteBarrier(array, JSArray::kElementsOffset,
653 var_elements.value());
659 TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) {
660 Node*
object = Parameter(Descriptor::kObject);
661 Node* context = Parameter(Descriptor::kContext);
663 VARIABLE(var_length, MachineRepresentation::kTagged);
664 VARIABLE(var_elements, MachineRepresentation::kTagged);
665 Label if_empty(
this, Label::kDeferred), if_empty_elements(
this),
666 if_fast(
this), try_fast(
this, Label::kDeferred),
667 if_slow(
this, Label::kDeferred), if_join(
this);
670 GotoIf(TaggedIsSmi(
object), &if_slow);
671 Node* object_map = LoadMap(
object);
672 Node* object_bit_field3 = LoadMapBitField3(object_map);
673 Node* object_enum_length =
674 DecodeWordFromWord32<Map::EnumLengthBits>(object_bit_field3);
676 WordEqual(object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)),
680 CSA_ASSERT(
this, IsJSObjectMap(object_map));
681 Node* object_elements = LoadElements(
object);
682 GotoIf(IsEmptyFixedArray(object_elements), &if_empty_elements);
683 Branch(IsEmptySlowElementDictionary(object_elements), &if_empty_elements,
687 BIND(&if_empty_elements);
688 Node* number_descriptors =
689 DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(object_bit_field3);
690 GotoIfNot(WordEqual(object_enum_length, number_descriptors), &if_slow);
693 Branch(WordEqual(object_enum_length, IntPtrConstant(0)), &if_empty, &if_fast);
699 Node* object_descriptors = LoadMapDescriptors(object_map);
700 Node* object_enum_cache =
701 LoadObjectField(object_descriptors, DescriptorArray::kEnumCacheOffset);
702 Node* object_enum_keys =
703 LoadObjectField(object_enum_cache, EnumCache::kKeysOffset);
706 Node* array =
nullptr;
707 Node* elements =
nullptr;
708 Node* native_context = LoadNativeContext(context);
709 TNode<Map> array_map =
710 LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
711 TNode<Smi> array_length = SmiTag(object_enum_length);
712 std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
713 PACKED_ELEMENTS, array_map, array_length,
nullptr, object_enum_length,
715 CopyFixedArrayElements(PACKED_ELEMENTS, object_enum_keys, elements,
716 object_enum_length, SKIP_WRITE_BARRIER);
723 Node* elements = CallRuntime(Runtime::kObjectGetOwnPropertyNamesTryFast,
725 var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset));
726 var_elements.Bind(elements);
733 var_length.Bind(SmiConstant(0));
734 var_elements.Bind(EmptyFixedArrayConstant());
742 CallRuntime(Runtime::kObjectGetOwnPropertyNames, context,
object);
743 var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset));
744 var_elements.Bind(elements);
751 Node* native_context = LoadNativeContext(context);
752 TNode<Map> array_map =
753 LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
754 TNode<JSArray> array = AllocateUninitializedJSArrayWithoutElements(
755 array_map, CAST(var_length.value()),
nullptr);
756 StoreObjectFieldNoWriteBarrier(array, JSArray::kElementsOffset,
757 var_elements.value());
762 TF_BUILTIN(ObjectValues, ObjectEntriesValuesBuiltinsAssembler) {
763 TNode<JSObject>
object =
764 TNode<JSObject>::UncheckedCast(Parameter(Descriptor::kObject));
765 TNode<Context> context =
766 TNode<Context>::UncheckedCast(Parameter(Descriptor::kContext));
767 GetOwnValuesOrEntries(context,
object, CollectType::kValues);
770 TF_BUILTIN(ObjectEntries, ObjectEntriesValuesBuiltinsAssembler) {
771 TNode<JSObject>
object =
772 TNode<JSObject>::UncheckedCast(Parameter(Descriptor::kObject));
773 TNode<Context> context =
774 TNode<Context>::UncheckedCast(Parameter(Descriptor::kContext));
775 GetOwnValuesOrEntries(context,
object, CollectType::kEntries);
779 TF_BUILTIN(ObjectPrototypeIsPrototypeOf, ObjectBuiltinsAssembler) {
780 Node* receiver = Parameter(Descriptor::kReceiver);
781 Node* value = Parameter(Descriptor::kValue);
782 Node* context = Parameter(Descriptor::kContext);
783 Label if_receiverisnullorundefined(
this, Label::kDeferred),
784 if_valueisnotreceiver(
this, Label::kDeferred);
791 GotoIf(TaggedIsSmi(value), &if_valueisnotreceiver);
802 GotoIf(IsNull(receiver), &if_receiverisnullorundefined);
803 GotoIf(IsUndefined(receiver), &if_receiverisnullorundefined);
806 Return(HasInPrototypeChain(context, value, receiver));
808 BIND(&if_receiverisnullorundefined);
813 GotoIfNot(IsJSReceiver(value), &if_valueisnotreceiver);
816 ToObject(context, receiver);
820 BIND(&if_valueisnotreceiver);
821 Return(FalseConstant());
825 TF_BUILTIN(ObjectPrototypeToString, CodeStubAssembler) {
826 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
827 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
828 Return(CallBuiltin(Builtins::kObjectToString, context, receiver));
831 TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) {
832 Label checkstringtag(
this), if_apiobject(
this, Label::kDeferred),
833 if_arguments(
this), if_array(
this), if_boolean(
this), if_date(
this),
834 if_error(
this), if_function(
this), if_number(
this, Label::kDeferred),
835 if_object(
this), if_primitive(
this), if_proxy(
this, Label::kDeferred),
836 if_regexp(
this), if_string(
this), if_symbol(
this, Label::kDeferred),
837 if_value(
this), if_bigint(
this, Label::kDeferred);
839 Node* receiver = Parameter(Descriptor::kReceiver);
840 Node* context = Parameter(Descriptor::kContext);
843 VARIABLE(var_default, MachineRepresentation::kTagged);
844 VARIABLE(var_holder, MachineRepresentation::kTagged, receiver);
845 GotoIf(TaggedIsSmi(receiver), &if_number);
846 Node* receiver_map = LoadMap(receiver);
847 Node* receiver_instance_type = LoadMapInstanceType(receiver_map);
848 GotoIf(IsPrimitiveInstanceType(receiver_instance_type), &if_primitive);
852 } kJumpTable[] = {{JS_OBJECT_TYPE, &if_object},
853 {JS_ARRAY_TYPE, &if_array},
854 {JS_FUNCTION_TYPE, &if_function},
855 {JS_REGEXP_TYPE, &if_regexp},
856 {JS_ARGUMENTS_TYPE, &if_arguments},
857 {JS_DATE_TYPE, &if_date},
858 {JS_BOUND_FUNCTION_TYPE, &if_function},
859 {JS_API_OBJECT_TYPE, &if_apiobject},
860 {JS_SPECIAL_API_OBJECT_TYPE, &if_apiobject},
861 {JS_PROXY_TYPE, &if_proxy},
862 {JS_ERROR_TYPE, &if_error},
863 {JS_VALUE_TYPE, &if_value}};
864 size_t const kNumCases = arraysize(kJumpTable);
865 Label* case_labels[kNumCases];
866 int32_t case_values[kNumCases];
867 for (
size_t i = 0;
i < kNumCases; ++
i) {
868 case_labels[
i] = kJumpTable[
i].label;
869 case_values[
i] = kJumpTable[
i].value;
871 Switch(receiver_instance_type, &if_object, case_values, case_labels,
872 arraysize(case_values));
877 VARIABLE(var_tag, MachineRepresentation::kTagged,
878 GetProperty(context, receiver,
879 isolate()->factory()->to_string_tag_symbol()));
880 Label if_tagisnotstring(
this), if_tagisstring(
this);
881 GotoIf(TaggedIsSmi(var_tag.value()), &if_tagisnotstring);
882 Branch(IsString(var_tag.value()), &if_tagisstring, &if_tagisnotstring);
883 BIND(&if_tagisnotstring);
885 var_tag.Bind(CallRuntime(Runtime::kClassOf, context, receiver));
886 Goto(&if_tagisstring);
888 BIND(&if_tagisstring);
889 ReturnToStringFormat(context, var_tag.value());
894 var_default.Bind(LoadRoot(RootIndex::karguments_to_string));
895 Goto(&checkstringtag);
900 var_default.Bind(LoadRoot(RootIndex::karray_to_string));
901 Goto(&checkstringtag);
906 Node* native_context = LoadNativeContext(context);
907 Node* boolean_constructor =
908 LoadContextElement(native_context, Context::BOOLEAN_FUNCTION_INDEX);
909 Node* boolean_initial_map = LoadObjectField(
910 boolean_constructor, JSFunction::kPrototypeOrInitialMapOffset);
911 Node* boolean_prototype =
912 LoadObjectField(boolean_initial_map, Map::kPrototypeOffset);
913 var_default.Bind(LoadRoot(RootIndex::kboolean_to_string));
914 var_holder.Bind(boolean_prototype);
915 Goto(&checkstringtag);
920 var_default.Bind(LoadRoot(RootIndex::kdate_to_string));
921 Goto(&checkstringtag);
926 var_default.Bind(LoadRoot(RootIndex::kerror_to_string));
927 Goto(&checkstringtag);
932 var_default.Bind(LoadRoot(RootIndex::kfunction_to_string));
933 Goto(&checkstringtag);
938 Node* native_context = LoadNativeContext(context);
939 Node* number_constructor =
940 LoadContextElement(native_context, Context::NUMBER_FUNCTION_INDEX);
941 Node* number_initial_map = LoadObjectField(
942 number_constructor, JSFunction::kPrototypeOrInitialMapOffset);
943 Node* number_prototype =
944 LoadObjectField(number_initial_map, Map::kPrototypeOffset);
945 var_default.Bind(LoadRoot(RootIndex::knumber_to_string));
946 var_holder.Bind(number_prototype);
947 Goto(&checkstringtag);
952 CSA_ASSERT(
this, IsJSReceiver(receiver));
953 var_default.Bind(LoadRoot(RootIndex::kobject_to_string));
954 Goto(&checkstringtag);
959 Label return_undefined(
this);
961 GotoIf(IsStringInstanceType(receiver_instance_type), &if_string);
962 GotoIf(IsBigIntInstanceType(receiver_instance_type), &if_bigint);
963 GotoIf(IsBooleanMap(receiver_map), &if_boolean);
964 GotoIf(IsHeapNumberMap(receiver_map), &if_number);
965 GotoIf(IsSymbolMap(receiver_map), &if_symbol);
966 GotoIf(IsUndefined(receiver), &return_undefined);
967 CSA_ASSERT(
this, IsNull(receiver));
968 Return(LoadRoot(RootIndex::knull_to_string));
970 BIND(&return_undefined);
971 Return(LoadRoot(RootIndex::kundefined_to_string));
981 Node* receiver_is_array =
982 CallRuntime(Runtime::kArrayIsArray, context, receiver);
983 TNode<String> builtin_tag = Select<String>(
984 IsTrue(receiver_is_array),
985 [=] {
return CAST(LoadRoot(RootIndex::kArray_string)); },
987 return Select<String>(
988 IsCallableMap(receiver_map),
989 [=] {
return CAST(LoadRoot(RootIndex::kFunction_string)); },
990 [=] {
return CAST(LoadRoot(RootIndex::kObject_string)); });
994 VARIABLE(var_tag, MachineRepresentation::kTagged,
995 GetProperty(context, receiver,
996 isolate()->factory()->to_string_tag_symbol()));
997 Label if_tagisnotstring(
this), if_tagisstring(
this);
998 GotoIf(TaggedIsSmi(var_tag.value()), &if_tagisnotstring);
999 Branch(IsString(var_tag.value()), &if_tagisstring, &if_tagisnotstring);
1000 BIND(&if_tagisnotstring);
1002 var_tag.Bind(builtin_tag);
1003 Goto(&if_tagisstring);
1005 BIND(&if_tagisstring);
1006 ReturnToStringFormat(context, var_tag.value());
1011 var_default.Bind(LoadRoot(RootIndex::kregexp_to_string));
1012 Goto(&checkstringtag);
1017 Node* native_context = LoadNativeContext(context);
1018 Node* string_constructor =
1019 LoadContextElement(native_context, Context::STRING_FUNCTION_INDEX);
1020 Node* string_initial_map = LoadObjectField(
1021 string_constructor, JSFunction::kPrototypeOrInitialMapOffset);
1022 Node* string_prototype =
1023 LoadObjectField(string_initial_map, Map::kPrototypeOffset);
1024 var_default.Bind(LoadRoot(RootIndex::kstring_to_string));
1025 var_holder.Bind(string_prototype);
1026 Goto(&checkstringtag);
1031 Node* native_context = LoadNativeContext(context);
1032 Node* symbol_constructor =
1033 LoadContextElement(native_context, Context::SYMBOL_FUNCTION_INDEX);
1034 Node* symbol_initial_map = LoadObjectField(
1035 symbol_constructor, JSFunction::kPrototypeOrInitialMapOffset);
1036 Node* symbol_prototype =
1037 LoadObjectField(symbol_initial_map, Map::kPrototypeOffset);
1038 var_default.Bind(LoadRoot(RootIndex::kobject_to_string));
1039 var_holder.Bind(symbol_prototype);
1040 Goto(&checkstringtag);
1045 Node* native_context = LoadNativeContext(context);
1046 Node* bigint_constructor =
1047 LoadContextElement(native_context, Context::BIGINT_FUNCTION_INDEX);
1048 Node* bigint_initial_map = LoadObjectField(
1049 bigint_constructor, JSFunction::kPrototypeOrInitialMapOffset);
1050 Node* bigint_prototype =
1051 LoadObjectField(bigint_initial_map, Map::kPrototypeOffset);
1052 var_default.Bind(LoadRoot(RootIndex::kobject_to_string));
1053 var_holder.Bind(bigint_prototype);
1054 Goto(&checkstringtag);
1059 Node* receiver_value = LoadJSValueValue(receiver);
1060 GotoIf(TaggedIsSmi(receiver_value), &if_number);
1061 Node* receiver_value_map = LoadMap(receiver_value);
1062 GotoIf(IsHeapNumberMap(receiver_value_map), &if_number);
1063 GotoIf(IsBooleanMap(receiver_value_map), &if_boolean);
1064 GotoIf(IsSymbolMap(receiver_value_map), &if_symbol);
1065 Node* receiver_value_instance_type =
1066 LoadMapInstanceType(receiver_value_map);
1067 GotoIf(IsBigIntInstanceType(receiver_value_instance_type), &if_bigint);
1068 CSA_ASSERT(
this, IsStringInstanceType(receiver_value_instance_type));
1072 BIND(&checkstringtag);
1077 Label loop(
this, &var_holder), return_default(
this),
1078 return_generic(
this, Label::kDeferred);
1082 Node* holder = var_holder.value();
1083 GotoIf(IsNull(holder), &return_default);
1084 Node* holder_map = LoadMap(holder);
1085 Node* holder_bit_field3 = LoadMapBitField3(holder_map);
1086 GotoIf(IsSetWord32<Map::MayHaveInterestingSymbolsBit>(holder_bit_field3),
1088 var_holder.Bind(LoadMapPrototype(holder_map));
1092 BIND(&return_generic);
1094 Node* tag = GetProperty(context, ToObject(context, receiver),
1095 LoadRoot(RootIndex::kto_string_tag_symbol));
1096 GotoIf(TaggedIsSmi(tag), &return_default);
1097 GotoIfNot(IsString(tag), &return_default);
1098 ReturnToStringFormat(context, tag);
1101 BIND(&return_default);
1102 Return(var_default.value());
1107 TF_BUILTIN(ObjectPrototypeValueOf, CodeStubAssembler) {
1108 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1109 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1111 Return(ToObject_Inline(context, receiver));
1115 TF_BUILTIN(CreateObjectWithoutProperties, ObjectBuiltinsAssembler) {
1116 Node*
const prototype = Parameter(Descriptor::kPrototypeArg);
1117 Node*
const context = Parameter(Descriptor::kContext);
1118 Node*
const native_context = LoadNativeContext(context);
1119 Label call_runtime(
this, Label::kDeferred), prototype_null(
this),
1120 prototype_jsreceiver(
this);
1122 Comment(
"Argument check: prototype");
1123 GotoIf(IsNull(prototype), &prototype_null);
1124 BranchIfJSReceiver(prototype, &prototype_jsreceiver, &call_runtime);
1127 VARIABLE(map, MachineRepresentation::kTagged);
1128 VARIABLE(properties, MachineRepresentation::kTagged);
1129 Label instantiate_map(
this);
1131 BIND(&prototype_null);
1133 Comment(
"Prototype is null");
1134 map.Bind(LoadContextElement(native_context,
1135 Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP));
1136 properties.Bind(AllocateNameDictionary(NameDictionary::kInitialCapacity));
1137 Goto(&instantiate_map);
1140 BIND(&prototype_jsreceiver);
1142 Comment(
"Prototype is JSReceiver");
1143 properties.Bind(EmptyFixedArrayConstant());
1144 Node* object_function =
1145 LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX);
1146 Node* object_function_map = LoadObjectField(
1147 object_function, JSFunction::kPrototypeOrInitialMapOffset);
1148 map.Bind(object_function_map);
1149 GotoIf(WordEqual(prototype, LoadMapPrototype(map.value())),
1151 Comment(
"Try loading the prototype info");
1152 Node* prototype_info =
1153 LoadMapPrototypeInfo(LoadMap(prototype), &call_runtime);
1154 TNode<MaybeObject> maybe_map = LoadMaybeWeakObjectField(
1155 prototype_info, PrototypeInfo::kObjectCreateMapOffset);
1156 GotoIf(IsStrongReferenceTo(maybe_map, UndefinedConstant()), &call_runtime);
1157 map.Bind(GetHeapObjectAssumeWeak(maybe_map, &call_runtime));
1158 Goto(&instantiate_map);
1161 BIND(&instantiate_map);
1163 Comment(
"Instantiate map");
1164 Node* instance = AllocateJSObjectFromMap(map.value(), properties.value());
1168 BIND(&call_runtime);
1170 Comment(
"Call Runtime (prototype is not null/jsreceiver)");
1171 Node* result = CallRuntime(Runtime::kObjectCreate, context, prototype,
1172 UndefinedConstant());
1178 TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) {
1179 int const kPrototypeArg = 0;
1180 int const kPropertiesArg = 1;
1183 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
1184 CodeStubArguments args(
this, argc);
1186 Node* prototype = args.GetOptionalArgumentValue(kPrototypeArg);
1187 Node* properties = args.GetOptionalArgumentValue(kPropertiesArg);
1188 Node* context = Parameter(Descriptor::kContext);
1190 Label call_runtime(
this, Label::kDeferred), prototype_valid(
this),
1191 no_properties(
this);
1193 Comment(
"Argument 1 check: prototype");
1194 GotoIf(IsNull(prototype), &prototype_valid);
1195 BranchIfJSReceiver(prototype, &prototype_valid, &call_runtime);
1198 BIND(&prototype_valid);
1200 Comment(
"Argument 2 check: properties");
1202 GotoIf(TaggedIsSmi(properties), &call_runtime);
1204 GotoIf(IsUndefined(properties), &no_properties);
1205 Node* properties_map = LoadMap(properties);
1206 GotoIf(IsSpecialReceiverMap(properties_map), &call_runtime);
1208 GotoIfNot(WordEqual(LoadElements(properties),
1209 LoadRoot(RootIndex::kEmptyFixedArray)),
1212 Node* bit_field3 = LoadMapBitField3(properties_map);
1213 GotoIf(IsSetWord32<Map::IsDictionaryMapBit>(bit_field3), &call_runtime);
1214 Branch(IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3),
1215 &call_runtime, &no_properties);
1219 BIND(&no_properties);
1221 VARIABLE(map, MachineRepresentation::kTagged);
1222 VARIABLE(properties, MachineRepresentation::kTagged);
1223 Label non_null_proto(
this), instantiate_map(
this), good(
this);
1225 Branch(IsNull(prototype), &good, &non_null_proto);
1229 map.Bind(LoadContextElement(
1230 context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP));
1231 properties.Bind(AllocateNameDictionary(NameDictionary::kInitialCapacity));
1232 Goto(&instantiate_map);
1235 BIND(&non_null_proto);
1237 properties.Bind(EmptyFixedArrayConstant());
1238 Node* object_function =
1239 LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX);
1240 Node* object_function_map = LoadObjectField(
1241 object_function, JSFunction::kPrototypeOrInitialMapOffset);
1242 map.Bind(object_function_map);
1243 GotoIf(WordEqual(prototype, LoadMapPrototype(map.value())),
1246 Node* prototype_info =
1247 LoadMapPrototypeInfo(LoadMap(prototype), &call_runtime);
1248 Comment(
"Load ObjectCreateMap from PrototypeInfo");
1249 TNode<MaybeObject> maybe_map = LoadMaybeWeakObjectField(
1250 prototype_info, PrototypeInfo::kObjectCreateMapOffset);
1251 GotoIf(IsStrongReferenceTo(maybe_map, UndefinedConstant()),
1253 map.Bind(GetHeapObjectAssumeWeak(maybe_map, &call_runtime));
1254 Goto(&instantiate_map);
1257 BIND(&instantiate_map);
1259 Node* instance = AllocateJSObjectFromMap(map.value(), properties.value());
1260 args.PopAndReturn(instance);
1264 BIND(&call_runtime);
1267 CallRuntime(Runtime::kObjectCreate, context, prototype, properties);
1268 args.PopAndReturn(result);
1273 TF_BUILTIN(ObjectIs, ObjectBuiltinsAssembler) {
1274 Node*
const left = Parameter(Descriptor::kLeft);
1275 Node*
const right = Parameter(Descriptor::kRight);
1277 Label return_true(
this), return_false(
this);
1278 BranchIfSameValue(left, right, &return_true, &return_false);
1281 Return(TrueConstant());
1283 BIND(&return_false);
1284 Return(FalseConstant());
1287 TF_BUILTIN(CreateIterResultObject, ObjectBuiltinsAssembler) {
1288 Node*
const value = Parameter(Descriptor::kValue);
1289 Node*
const done = Parameter(Descriptor::kDone);
1290 Node*
const context = Parameter(Descriptor::kContext);
1292 Node*
const native_context = LoadNativeContext(context);
1294 LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
1296 Node*
const result = AllocateJSObjectFromMap(map);
1298 StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset, value);
1299 StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset, done);
1304 TF_BUILTIN(HasProperty, ObjectBuiltinsAssembler) {
1305 Node* key = Parameter(Descriptor::kKey);
1306 Node*
object = Parameter(Descriptor::kObject);
1307 Node* context = Parameter(Descriptor::kContext);
1309 Return(HasProperty(context,
object, key, kHasProperty));
1312 TF_BUILTIN(InstanceOf, ObjectBuiltinsAssembler) {
1313 Node*
object = Parameter(Descriptor::kLeft);
1314 Node* callable = Parameter(Descriptor::kRight);
1315 Node* context = Parameter(Descriptor::kContext);
1317 Return(InstanceOf(
object, callable, context));
1321 TF_BUILTIN(OrdinaryHasInstance, ObjectBuiltinsAssembler) {
1322 Node* constructor = Parameter(Descriptor::kLeft);
1323 Node*
object = Parameter(Descriptor::kRight);
1324 Node* context = Parameter(Descriptor::kContext);
1326 Return(OrdinaryHasInstance(context, constructor,
object));
1329 TF_BUILTIN(GetSuperConstructor, ObjectBuiltinsAssembler) {
1330 Node*
object = Parameter(Descriptor::kObject);
1331 Node* context = Parameter(Descriptor::kContext);
1333 Return(GetSuperConstructor(context,
object));
1336 TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) {
1337 Node* closure = Parameter(Descriptor::kClosure);
1338 Node* receiver = Parameter(Descriptor::kReceiver);
1339 Node* context = Parameter(Descriptor::kContext);
1343 Label done(
this), runtime(
this);
1344 GotoIfNot(IsFunctionWithPrototypeSlotMap(LoadMap(closure)), &runtime);
1346 LoadObjectField(closure, JSFunction::kPrototypeOrInitialMapOffset);
1347 GotoIf(DoesntHaveInstanceType(maybe_map, MAP_TYPE), &runtime);
1350 LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
1351 Node* bytecode_array = LoadSharedFunctionInfoBytecodeArray(shared);
1353 Node* formal_parameter_count = ChangeInt32ToIntPtr(
1354 LoadObjectField(shared, SharedFunctionInfo::kFormalParameterCountOffset,
1355 MachineType::Uint16()));
1356 Node* frame_size = ChangeInt32ToIntPtr(LoadObjectField(
1357 bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32()));
1358 Node* size = IntPtrAdd(WordSar(frame_size, IntPtrConstant(kPointerSizeLog2)),
1359 formal_parameter_count);
1360 Node* parameters_and_registers = AllocateFixedArray(HOLEY_ELEMENTS, size);
1361 FillFixedArrayWithValue(HOLEY_ELEMENTS, parameters_and_registers,
1362 IntPtrConstant(0), size, RootIndex::kUndefinedValue);
1364 Node* result = AllocateJSObjectFromMap(maybe_map,
nullptr,
nullptr,
kNone,
1365 kWithSlackTracking);
1366 StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kFunctionOffset,
1368 StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContextOffset,
1370 StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kReceiverOffset,
1372 StoreObjectFieldNoWriteBarrier(
1373 result, JSGeneratorObject::kParametersAndRegistersOffset,
1374 parameters_and_registers);
1375 Node* executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting);
1376 StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContinuationOffset,
1378 GotoIfNot(HasInstanceType(maybe_map, JS_ASYNC_GENERATOR_OBJECT_TYPE), &done);
1379 StoreObjectFieldNoWriteBarrier(
1380 result, JSAsyncGeneratorObject::kIsAwaitingOffset, SmiConstant(0));
1388 Return(CallRuntime(Runtime::kCreateJSGeneratorObject, context, closure,
1394 TF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) {
1395 Node* argc = Parameter(Descriptor::kJSActualArgumentsCount);
1396 Node* context = Parameter(Descriptor::kContext);
1397 CSA_ASSERT(
this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
1399 CodeStubArguments args(
this, ChangeInt32ToIntPtr(argc));
1400 Node*
object = args.GetOptionalArgumentValue(0);
1401 Node* key = args.GetOptionalArgumentValue(1);
1404 object = ToObject_Inline(CAST(context), CAST(
object));
1407 key = CallBuiltin(Builtins::kToName, context, key);
1410 Label if_keyisindex(
this), if_iskeyunique(
this),
1411 call_runtime(
this, Label::kDeferred),
1412 return_undefined(
this, Label::kDeferred), if_notunique_name(
this);
1413 Node* map = LoadMap(
object);
1414 TNode<Int32T> instance_type = LoadMapInstanceType(map);
1415 GotoIf(IsSpecialReceiverInstanceType(instance_type), &call_runtime);
1417 VARIABLE(var_index, MachineType::PointerRepresentation(),
1419 VARIABLE(var_name, MachineRepresentation::kTagged);
1421 TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, &var_name,
1422 &call_runtime, &if_notunique_name);
1424 BIND(&if_notunique_name);
1426 Label not_in_string_table(
this);
1427 TryInternalizeString(key, &if_keyisindex, &var_index, &if_iskeyunique,
1428 &var_name, ¬_in_string_table, &call_runtime);
1430 BIND(¬_in_string_table);
1434 Goto(&return_undefined);
1438 BIND(&if_iskeyunique);
1440 Label if_found_value(
this), return_empty(
this), if_not_found(
this);
1442 VARIABLE(var_value, MachineRepresentation::kTagged);
1443 VARIABLE(var_details, MachineRepresentation::kWord32);
1444 VARIABLE(var_raw_value, MachineRepresentation::kTagged);
1446 TryGetOwnProperty(context,
object,
object, map, instance_type,
1447 var_name.value(), &if_found_value, &var_value,
1448 &var_details, &var_raw_value, &return_empty,
1449 &if_not_found, kReturnAccessorPair);
1451 BIND(&if_found_value);
1453 Node* js_desc = FromPropertyDetails(context, var_value.value(),
1454 var_details.value(), &call_runtime);
1455 args.PopAndReturn(js_desc);
1457 BIND(&return_empty);
1458 var_value.Bind(UndefinedConstant());
1459 args.PopAndReturn(UndefinedConstant());
1461 BIND(&if_not_found);
1462 Goto(&call_runtime);
1466 BIND(&if_keyisindex);
1467 Goto(&call_runtime);
1469 BIND(&call_runtime);
1472 CallRuntime(Runtime::kGetOwnPropertyDescriptor, context,
object, key);
1474 GotoIf(IsUndefined(desc), &return_undefined);
1476 CSA_ASSERT(
this, IsFixedArray(desc));
1479 Node* js_desc = FromPropertyDescriptor(context, desc);
1480 args.PopAndReturn(js_desc);
1482 BIND(&return_undefined);
1483 args.PopAndReturn(UndefinedConstant());
1486 void ObjectBuiltinsAssembler::AddToDictionaryIf(
1487 TNode<BoolT> condition, TNode<NameDictionary> name_dictionary,
1488 Handle<Name> name, TNode<Object> value, Label* bailout) {
1490 GotoIfNot(condition, &done);
1492 Add<NameDictionary>(name_dictionary, HeapConstant(name), value, bailout);
1498 Node* ObjectBuiltinsAssembler::FromPropertyDescriptor(Node* context,
1500 VARIABLE(js_descriptor, MachineRepresentation::kTagged);
1502 Node* flags = LoadAndUntagToWord32ObjectField(
1503 desc, PropertyDescriptorObject::kFlagsOffset);
1506 Word32And(flags, Int32Constant(PropertyDescriptorObject::kHasMask));
1508 Label if_accessor_desc(
this), if_data_desc(
this), if_generic_desc(
this),
1511 Word32Equal(has_flags,
1513 PropertyDescriptorObject::kRegularAccessorPropertyBits)),
1517 Int32Constant(PropertyDescriptorObject::kRegularDataPropertyBits)),
1519 Goto(&if_generic_desc);
1521 BIND(&if_accessor_desc);
1523 js_descriptor.Bind(ConstructAccessorDescriptor(
1524 context, LoadObjectField(desc, PropertyDescriptorObject::kGetOffset),
1525 LoadObjectField(desc, PropertyDescriptorObject::kSetOffset),
1526 IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags),
1527 IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)));
1531 BIND(&if_data_desc);
1533 js_descriptor.Bind(ConstructDataDescriptor(
1534 context, LoadObjectField(desc, PropertyDescriptorObject::kValueOffset),
1535 IsSetWord32<PropertyDescriptorObject::IsWritableBit>(flags),
1536 IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags),
1537 IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)));
1541 BIND(&if_generic_desc);
1543 Node* native_context = LoadNativeContext(context);
1544 Node* map = LoadContextElement(
1545 native_context, Context::SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP);
1548 TNode<NameDictionary> properties = AllocateNameDictionary(6);
1549 Node* js_desc = AllocateJSObjectFromMap(map, properties);
1551 Label bailout(
this, Label::kDeferred);
1553 Factory* factory = isolate()->factory();
1554 TNode<Object> value =
1555 LoadObjectField(desc, PropertyDescriptorObject::kValueOffset);
1556 AddToDictionaryIf(IsNotTheHole(value), properties, factory->value_string(),
1559 IsSetWord32<PropertyDescriptorObject::HasWritableBit>(flags),
1560 properties, factory->writable_string(),
1561 SelectBooleanConstant(
1562 IsSetWord32<PropertyDescriptorObject::IsWritableBit>(flags)),
1566 LoadObjectField(desc, PropertyDescriptorObject::kGetOffset);
1567 AddToDictionaryIf(IsNotTheHole(
get), properties, factory->get_string(),
get,
1570 LoadObjectField(desc, PropertyDescriptorObject::kSetOffset);
1571 AddToDictionaryIf(IsNotTheHole(
set), properties, factory->set_string(),
set,
1575 IsSetWord32<PropertyDescriptorObject::HasEnumerableBit>(flags),
1576 properties, factory->enumerable_string(),
1577 SelectBooleanConstant(
1578 IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags)),
1581 IsSetWord32<PropertyDescriptorObject::HasConfigurableBit>(flags),
1582 properties, factory->configurable_string(),
1583 SelectBooleanConstant(
1584 IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)),
1587 js_descriptor.Bind(js_desc);
1591 CSA_ASSERT(
this, Int32Constant(0));
1596 return js_descriptor.value();
1599 Node* ObjectBuiltinsAssembler::FromPropertyDetails(Node* context,
1602 Label* if_bailout) {
1603 VARIABLE(js_descriptor, MachineRepresentation::kTagged);
1605 Label if_accessor_desc(
this), if_data_desc(
this), return_desc(
this);
1606 BranchIfAccessorPair(raw_value, &if_accessor_desc, &if_data_desc);
1608 BIND(&if_accessor_desc);
1610 Node* getter = LoadObjectField(raw_value, AccessorPair::kGetterOffset);
1611 Node* setter = LoadObjectField(raw_value, AccessorPair::kSetterOffset);
1612 js_descriptor.Bind(ConstructAccessorDescriptor(
1613 context, GetAccessorOrUndefined(getter, if_bailout),
1614 GetAccessorOrUndefined(setter, if_bailout),
1615 IsNotSetWord32(details, PropertyDetails::kAttributesDontEnumMask),
1616 IsNotSetWord32(details, PropertyDetails::kAttributesDontDeleteMask)));
1620 BIND(&if_data_desc);
1622 js_descriptor.Bind(ConstructDataDescriptor(
1624 IsNotSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
1625 IsNotSetWord32(details, PropertyDetails::kAttributesDontEnumMask),
1626 IsNotSetWord32(details, PropertyDetails::kAttributesDontDeleteMask)));
1631 return js_descriptor.value();
1634 Node* ObjectBuiltinsAssembler::GetAccessorOrUndefined(Node* accessor,
1635 Label* if_bailout) {
1636 Label bind_undefined(
this, Label::kDeferred), return_result(
this);
1637 VARIABLE(result, MachineRepresentation::kTagged);
1639 GotoIf(IsNull(accessor), &bind_undefined);
1640 result.Bind(accessor);
1641 Node* map = LoadMap(accessor);
1643 GotoIf(IsFunctionTemplateInfoMap(map), if_bailout);
1644 Goto(&return_result);
1646 BIND(&bind_undefined);
1647 result.Bind(UndefinedConstant());
1648 Goto(&return_result);
1650 BIND(&return_result);
1651 return result.value();