11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils-gen.h" 61cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h" 71cb0ef41Sopenharmony_ci#include "src/codegen/code-stub-assembler.h" 81cb0ef41Sopenharmony_ci#include "src/common/globals.h" 91cb0ef41Sopenharmony_ci#include "src/heap/factory-inl.h" 101cb0ef41Sopenharmony_ci#include "src/ic/accessor-assembler.h" 111cb0ef41Sopenharmony_ci#include "src/ic/keyed-store-generic.h" 121cb0ef41Sopenharmony_ci#include "src/objects/js-generator.h" 131cb0ef41Sopenharmony_ci#include "src/objects/js-objects.h" 141cb0ef41Sopenharmony_ci#include "src/objects/property-descriptor-object.h" 151cb0ef41Sopenharmony_ci#include "src/objects/property-details.h" 161cb0ef41Sopenharmony_ci#include "src/objects/shared-function-info.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace v8 { 191cb0ef41Sopenharmony_cinamespace internal { 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 221cb0ef41Sopenharmony_ci// ES6 section 19.1 Object Objects 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ciclass ObjectBuiltinsAssembler : public CodeStubAssembler { 251cb0ef41Sopenharmony_ci public: 261cb0ef41Sopenharmony_ci explicit ObjectBuiltinsAssembler(compiler::CodeAssemblerState* state) 271cb0ef41Sopenharmony_ci : CodeStubAssembler(state) {} 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci protected: 301cb0ef41Sopenharmony_ci void ReturnToStringFormat(TNode<Context> context, TNode<String> string); 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci // TODO(v8:11167) remove |context| and |object| once OrderedNameDictionary 331cb0ef41Sopenharmony_ci // supported. 341cb0ef41Sopenharmony_ci void AddToDictionaryIf(TNode<BoolT> condition, TNode<Context> context, 351cb0ef41Sopenharmony_ci TNode<Object> object, 361cb0ef41Sopenharmony_ci TNode<HeapObject> name_dictionary, Handle<Name> name, 371cb0ef41Sopenharmony_ci TNode<Object> value, Label* bailout); 381cb0ef41Sopenharmony_ci TNode<JSObject> FromPropertyDescriptor(TNode<Context> context, 391cb0ef41Sopenharmony_ci TNode<PropertyDescriptorObject> desc); 401cb0ef41Sopenharmony_ci TNode<JSObject> FromPropertyDetails(TNode<Context> context, 411cb0ef41Sopenharmony_ci TNode<Object> raw_value, 421cb0ef41Sopenharmony_ci TNode<Word32T> details, 431cb0ef41Sopenharmony_ci Label* if_bailout); 441cb0ef41Sopenharmony_ci TNode<JSObject> ConstructAccessorDescriptor(TNode<Context> context, 451cb0ef41Sopenharmony_ci TNode<Object> getter, 461cb0ef41Sopenharmony_ci TNode<Object> setter, 471cb0ef41Sopenharmony_ci TNode<BoolT> enumerable, 481cb0ef41Sopenharmony_ci TNode<BoolT> configurable); 491cb0ef41Sopenharmony_ci TNode<JSObject> ConstructDataDescriptor(TNode<Context> context, 501cb0ef41Sopenharmony_ci TNode<Object> value, 511cb0ef41Sopenharmony_ci TNode<BoolT> writable, 521cb0ef41Sopenharmony_ci TNode<BoolT> enumerable, 531cb0ef41Sopenharmony_ci TNode<BoolT> configurable); 541cb0ef41Sopenharmony_ci TNode<HeapObject> GetAccessorOrUndefined(TNode<HeapObject> accessor, 551cb0ef41Sopenharmony_ci Label* if_bailout); 561cb0ef41Sopenharmony_ci}; 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ciclass ObjectEntriesValuesBuiltinsAssembler : public ObjectBuiltinsAssembler { 591cb0ef41Sopenharmony_ci public: 601cb0ef41Sopenharmony_ci explicit ObjectEntriesValuesBuiltinsAssembler( 611cb0ef41Sopenharmony_ci compiler::CodeAssemblerState* state) 621cb0ef41Sopenharmony_ci : ObjectBuiltinsAssembler(state) {} 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci protected: 651cb0ef41Sopenharmony_ci enum CollectType { kEntries, kValues }; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci TNode<BoolT> IsPropertyEnumerable(TNode<Uint32T> details); 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci TNode<BoolT> IsPropertyKindAccessor(TNode<Uint32T> kind); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci TNode<BoolT> IsPropertyKindData(TNode<Uint32T> kind); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci TNode<Uint32T> LoadPropertyKind(TNode<Uint32T> details) { 741cb0ef41Sopenharmony_ci return DecodeWord32<PropertyDetails::KindField>(details); 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci void GetOwnValuesOrEntries(TNode<Context> context, TNode<Object> maybe_object, 781cb0ef41Sopenharmony_ci CollectType collect_type); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci TNode<JSArray> FastGetOwnValuesOrEntries( 811cb0ef41Sopenharmony_ci TNode<Context> context, TNode<JSObject> object, 821cb0ef41Sopenharmony_ci Label* if_call_runtime_with_fast_path, Label* if_no_properties, 831cb0ef41Sopenharmony_ci CollectType collect_type); 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci TNode<JSArray> FinalizeValuesOrEntriesJSArray( 861cb0ef41Sopenharmony_ci TNode<Context> context, TNode<FixedArray> values_or_entries, 871cb0ef41Sopenharmony_ci TNode<IntPtrT> size, TNode<Map> array_map, Label* if_empty); 881cb0ef41Sopenharmony_ci}; 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_civoid ObjectBuiltinsAssembler::ReturnToStringFormat(TNode<Context> context, 911cb0ef41Sopenharmony_ci TNode<String> string) { 921cb0ef41Sopenharmony_ci TNode<String> lhs = StringConstant("[object "); 931cb0ef41Sopenharmony_ci TNode<String> rhs = StringConstant("]"); 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci Callable callable = CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE); 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci Return(CallStub(callable, context, CallStub(callable, context, lhs, string), 981cb0ef41Sopenharmony_ci rhs)); 991cb0ef41Sopenharmony_ci} 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ciTNode<JSObject> ObjectBuiltinsAssembler::ConstructAccessorDescriptor( 1021cb0ef41Sopenharmony_ci TNode<Context> context, TNode<Object> getter, TNode<Object> setter, 1031cb0ef41Sopenharmony_ci TNode<BoolT> enumerable, TNode<BoolT> configurable) { 1041cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 1051cb0ef41Sopenharmony_ci TNode<Map> map = CAST(LoadContextElement( 1061cb0ef41Sopenharmony_ci native_context, Context::ACCESSOR_PROPERTY_DESCRIPTOR_MAP_INDEX)); 1071cb0ef41Sopenharmony_ci TNode<JSObject> js_desc = AllocateJSObjectFromMap(map); 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 1101cb0ef41Sopenharmony_ci js_desc, JSAccessorPropertyDescriptor::kGetOffset, getter); 1111cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 1121cb0ef41Sopenharmony_ci js_desc, JSAccessorPropertyDescriptor::kSetOffset, setter); 1131cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 1141cb0ef41Sopenharmony_ci js_desc, JSAccessorPropertyDescriptor::kEnumerableOffset, 1151cb0ef41Sopenharmony_ci SelectBooleanConstant(enumerable)); 1161cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 1171cb0ef41Sopenharmony_ci js_desc, JSAccessorPropertyDescriptor::kConfigurableOffset, 1181cb0ef41Sopenharmony_ci SelectBooleanConstant(configurable)); 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci return js_desc; 1211cb0ef41Sopenharmony_ci} 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ciTNode<JSObject> ObjectBuiltinsAssembler::ConstructDataDescriptor( 1241cb0ef41Sopenharmony_ci TNode<Context> context, TNode<Object> value, TNode<BoolT> writable, 1251cb0ef41Sopenharmony_ci TNode<BoolT> enumerable, TNode<BoolT> configurable) { 1261cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 1271cb0ef41Sopenharmony_ci TNode<Map> map = CAST(LoadContextElement( 1281cb0ef41Sopenharmony_ci native_context, Context::DATA_PROPERTY_DESCRIPTOR_MAP_INDEX)); 1291cb0ef41Sopenharmony_ci TNode<JSObject> js_desc = AllocateJSObjectFromMap(map); 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(js_desc, 1321cb0ef41Sopenharmony_ci JSDataPropertyDescriptor::kValueOffset, value); 1331cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(js_desc, 1341cb0ef41Sopenharmony_ci JSDataPropertyDescriptor::kWritableOffset, 1351cb0ef41Sopenharmony_ci SelectBooleanConstant(writable)); 1361cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(js_desc, 1371cb0ef41Sopenharmony_ci JSDataPropertyDescriptor::kEnumerableOffset, 1381cb0ef41Sopenharmony_ci SelectBooleanConstant(enumerable)); 1391cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(js_desc, 1401cb0ef41Sopenharmony_ci JSDataPropertyDescriptor::kConfigurableOffset, 1411cb0ef41Sopenharmony_ci SelectBooleanConstant(configurable)); 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci return js_desc; 1441cb0ef41Sopenharmony_ci} 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ciTNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyEnumerable( 1471cb0ef41Sopenharmony_ci TNode<Uint32T> details) { 1481cb0ef41Sopenharmony_ci TNode<Uint32T> attributes = 1491cb0ef41Sopenharmony_ci DecodeWord32<PropertyDetails::AttributesField>(details); 1501cb0ef41Sopenharmony_ci return IsNotSetWord32(attributes, PropertyAttributes::DONT_ENUM); 1511cb0ef41Sopenharmony_ci} 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ciTNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyKindAccessor( 1541cb0ef41Sopenharmony_ci TNode<Uint32T> kind) { 1551cb0ef41Sopenharmony_ci return Word32Equal(kind, 1561cb0ef41Sopenharmony_ci Int32Constant(static_cast<int>(PropertyKind::kAccessor))); 1571cb0ef41Sopenharmony_ci} 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ciTNode<BoolT> ObjectEntriesValuesBuiltinsAssembler::IsPropertyKindData( 1601cb0ef41Sopenharmony_ci TNode<Uint32T> kind) { 1611cb0ef41Sopenharmony_ci return Word32Equal(kind, 1621cb0ef41Sopenharmony_ci Int32Constant(static_cast<int>(PropertyKind::kData))); 1631cb0ef41Sopenharmony_ci} 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_civoid ObjectEntriesValuesBuiltinsAssembler::GetOwnValuesOrEntries( 1661cb0ef41Sopenharmony_ci TNode<Context> context, TNode<Object> maybe_object, 1671cb0ef41Sopenharmony_ci CollectType collect_type) { 1681cb0ef41Sopenharmony_ci TNode<JSReceiver> receiver = ToObject_Inline(context, maybe_object); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci Label if_call_runtime_with_fast_path(this, Label::kDeferred), 1711cb0ef41Sopenharmony_ci if_call_runtime(this, Label::kDeferred), 1721cb0ef41Sopenharmony_ci if_no_properties(this, Label::kDeferred); 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci TNode<Map> map = LoadMap(receiver); 1751cb0ef41Sopenharmony_ci GotoIfNot(IsJSObjectMap(map), &if_call_runtime); 1761cb0ef41Sopenharmony_ci GotoIfMapHasSlowProperties(map, &if_call_runtime); 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci TNode<JSObject> object = CAST(receiver); 1791cb0ef41Sopenharmony_ci TNode<FixedArrayBase> elements = LoadElements(object); 1801cb0ef41Sopenharmony_ci // If the object has elements, we treat it as slow case. 1811cb0ef41Sopenharmony_ci // So, we go to runtime call. 1821cb0ef41Sopenharmony_ci GotoIfNot(IsEmptyFixedArray(elements), &if_call_runtime_with_fast_path); 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci TNode<JSArray> result = FastGetOwnValuesOrEntries( 1851cb0ef41Sopenharmony_ci context, object, &if_call_runtime_with_fast_path, &if_no_properties, 1861cb0ef41Sopenharmony_ci collect_type); 1871cb0ef41Sopenharmony_ci Return(result); 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci BIND(&if_no_properties); 1901cb0ef41Sopenharmony_ci { 1911cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 1921cb0ef41Sopenharmony_ci TNode<Map> array_map = 1931cb0ef41Sopenharmony_ci LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); 1941cb0ef41Sopenharmony_ci TNode<JSArray> empty_array = AllocateJSArray( 1951cb0ef41Sopenharmony_ci PACKED_ELEMENTS, array_map, IntPtrConstant(0), SmiConstant(0)); 1961cb0ef41Sopenharmony_ci Return(empty_array); 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci BIND(&if_call_runtime_with_fast_path); 2001cb0ef41Sopenharmony_ci { 2011cb0ef41Sopenharmony_ci // In slow case, we simply call runtime. 2021cb0ef41Sopenharmony_ci if (collect_type == CollectType::kEntries) { 2031cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kObjectEntries, context, object)); 2041cb0ef41Sopenharmony_ci } else { 2051cb0ef41Sopenharmony_ci DCHECK(collect_type == CollectType::kValues); 2061cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kObjectValues, context, object)); 2071cb0ef41Sopenharmony_ci } 2081cb0ef41Sopenharmony_ci } 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci BIND(&if_call_runtime); 2111cb0ef41Sopenharmony_ci { 2121cb0ef41Sopenharmony_ci // In slow case, we simply call runtime. 2131cb0ef41Sopenharmony_ci if (collect_type == CollectType::kEntries) { 2141cb0ef41Sopenharmony_ci Return( 2151cb0ef41Sopenharmony_ci CallRuntime(Runtime::kObjectEntriesSkipFastPath, context, receiver)); 2161cb0ef41Sopenharmony_ci } else { 2171cb0ef41Sopenharmony_ci DCHECK(collect_type == CollectType::kValues); 2181cb0ef41Sopenharmony_ci Return( 2191cb0ef41Sopenharmony_ci CallRuntime(Runtime::kObjectValuesSkipFastPath, context, receiver)); 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ciTNode<JSArray> ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries( 2251cb0ef41Sopenharmony_ci TNode<Context> context, TNode<JSObject> object, 2261cb0ef41Sopenharmony_ci Label* if_call_runtime_with_fast_path, Label* if_no_properties, 2271cb0ef41Sopenharmony_ci CollectType collect_type) { 2281cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 2291cb0ef41Sopenharmony_ci TNode<Map> array_map = 2301cb0ef41Sopenharmony_ci LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); 2311cb0ef41Sopenharmony_ci TNode<Map> map = LoadMap(object); 2321cb0ef41Sopenharmony_ci TNode<Uint32T> bit_field3 = LoadMapBitField3(map); 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci Label if_has_enum_cache(this), if_not_has_enum_cache(this), 2351cb0ef41Sopenharmony_ci collect_entries(this); 2361cb0ef41Sopenharmony_ci TNode<IntPtrT> object_enum_length = 2371cb0ef41Sopenharmony_ci Signed(DecodeWordFromWord32<Map::Bits3::EnumLengthBits>(bit_field3)); 2381cb0ef41Sopenharmony_ci TNode<BoolT> has_enum_cache = WordNotEqual( 2391cb0ef41Sopenharmony_ci object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)); 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci // In case, we found enum_cache in object, 2421cb0ef41Sopenharmony_ci // we use it as array_length because it has same size for 2431cb0ef41Sopenharmony_ci // Object.(entries/values) result array object length. 2441cb0ef41Sopenharmony_ci // So object_enum_length use less memory space than 2451cb0ef41Sopenharmony_ci // NumberOfOwnDescriptorsBits value. 2461cb0ef41Sopenharmony_ci // And in case, if enum_cache_not_found, 2471cb0ef41Sopenharmony_ci // we call runtime and initialize enum_cache for subsequent call of 2481cb0ef41Sopenharmony_ci // CSA fast path. 2491cb0ef41Sopenharmony_ci Branch(has_enum_cache, &if_has_enum_cache, if_call_runtime_with_fast_path); 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci BIND(&if_has_enum_cache); 2521cb0ef41Sopenharmony_ci { 2531cb0ef41Sopenharmony_ci GotoIf(WordEqual(object_enum_length, IntPtrConstant(0)), if_no_properties); 2541cb0ef41Sopenharmony_ci TNode<FixedArray> values_or_entries = 2551cb0ef41Sopenharmony_ci CAST(AllocateFixedArray(PACKED_ELEMENTS, object_enum_length, 2561cb0ef41Sopenharmony_ci AllocationFlag::kAllowLargeObjectAllocation)); 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci // If in case we have enum_cache, 2591cb0ef41Sopenharmony_ci // we can't detect accessor of object until loop through descriptors. 2601cb0ef41Sopenharmony_ci // So if object might have accessor, 2611cb0ef41Sopenharmony_ci // we will remain invalid addresses of FixedArray. 2621cb0ef41Sopenharmony_ci // Because in that case, we need to jump to runtime call. 2631cb0ef41Sopenharmony_ci // So the array filled by the-hole even if enum_cache exists. 2641cb0ef41Sopenharmony_ci FillFixedArrayWithValue(PACKED_ELEMENTS, values_or_entries, 2651cb0ef41Sopenharmony_ci IntPtrConstant(0), object_enum_length, 2661cb0ef41Sopenharmony_ci RootIndex::kTheHoleValue); 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci TVARIABLE(IntPtrT, var_result_index, IntPtrConstant(0)); 2691cb0ef41Sopenharmony_ci TVARIABLE(IntPtrT, var_descriptor_number, IntPtrConstant(0)); 2701cb0ef41Sopenharmony_ci // Let desc be ? O.[[GetOwnProperty]](key). 2711cb0ef41Sopenharmony_ci TNode<DescriptorArray> descriptors = LoadMapDescriptors(map); 2721cb0ef41Sopenharmony_ci Label loop(this, {&var_descriptor_number, &var_result_index}), 2731cb0ef41Sopenharmony_ci after_loop(this), next_descriptor(this); 2741cb0ef41Sopenharmony_ci Branch(IntPtrEqual(var_descriptor_number.value(), object_enum_length), 2751cb0ef41Sopenharmony_ci &after_loop, &loop); 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ci // We dont use BuildFastLoop. 2781cb0ef41Sopenharmony_ci // Instead, we use hand-written loop 2791cb0ef41Sopenharmony_ci // because of we need to use 'continue' functionality. 2801cb0ef41Sopenharmony_ci BIND(&loop); 2811cb0ef41Sopenharmony_ci { 2821cb0ef41Sopenharmony_ci // Currently, we will not invoke getters, 2831cb0ef41Sopenharmony_ci // so, map will not be changed. 2841cb0ef41Sopenharmony_ci CSA_DCHECK(this, TaggedEqual(map, LoadMap(object))); 2851cb0ef41Sopenharmony_ci TNode<IntPtrT> descriptor_entry = var_descriptor_number.value(); 2861cb0ef41Sopenharmony_ci TNode<Name> next_key = 2871cb0ef41Sopenharmony_ci LoadKeyByDescriptorEntry(descriptors, descriptor_entry); 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci // Skip Symbols. 2901cb0ef41Sopenharmony_ci GotoIf(IsSymbol(next_key), &next_descriptor); 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci TNode<Uint32T> details = 2931cb0ef41Sopenharmony_ci LoadDetailsByDescriptorEntry(descriptors, descriptor_entry); 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci TNode<Uint32T> kind = LoadPropertyKind(details); 2961cb0ef41Sopenharmony_ci 2971cb0ef41Sopenharmony_ci // If property is accessor, we escape fast path and call runtime. 2981cb0ef41Sopenharmony_ci GotoIf(IsPropertyKindAccessor(kind), if_call_runtime_with_fast_path); 2991cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsPropertyKindData(kind)); 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci // If desc is not undefined and desc.[[Enumerable]] is true, then skip to 3021cb0ef41Sopenharmony_ci // the next descriptor. 3031cb0ef41Sopenharmony_ci GotoIfNot(IsPropertyEnumerable(details), &next_descriptor); 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci TVARIABLE(Object, var_property_value, UndefinedConstant()); 3061cb0ef41Sopenharmony_ci TNode<IntPtrT> descriptor_name_index = ToKeyIndex<DescriptorArray>( 3071cb0ef41Sopenharmony_ci Unsigned(TruncateIntPtrToInt32(var_descriptor_number.value()))); 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci // Let value be ? Get(O, key). 3101cb0ef41Sopenharmony_ci LoadPropertyFromFastObject(object, map, descriptors, 3111cb0ef41Sopenharmony_ci descriptor_name_index, details, 3121cb0ef41Sopenharmony_ci &var_property_value); 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci // If kind is "value", append value to properties. 3151cb0ef41Sopenharmony_ci TNode<Object> value = var_property_value.value(); 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci if (collect_type == CollectType::kEntries) { 3181cb0ef41Sopenharmony_ci // Let entry be CreateArrayFromList(« key, value »). 3191cb0ef41Sopenharmony_ci TNode<JSArray> array; 3201cb0ef41Sopenharmony_ci TNode<FixedArrayBase> elements; 3211cb0ef41Sopenharmony_ci std::tie(array, elements) = AllocateUninitializedJSArrayWithElements( 3221cb0ef41Sopenharmony_ci PACKED_ELEMENTS, array_map, SmiConstant(2), base::nullopt, 3231cb0ef41Sopenharmony_ci IntPtrConstant(2)); 3241cb0ef41Sopenharmony_ci StoreFixedArrayElement(CAST(elements), 0, next_key, SKIP_WRITE_BARRIER); 3251cb0ef41Sopenharmony_ci StoreFixedArrayElement(CAST(elements), 1, value, SKIP_WRITE_BARRIER); 3261cb0ef41Sopenharmony_ci value = array; 3271cb0ef41Sopenharmony_ci } 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci StoreFixedArrayElement(values_or_entries, var_result_index.value(), 3301cb0ef41Sopenharmony_ci value); 3311cb0ef41Sopenharmony_ci Increment(&var_result_index); 3321cb0ef41Sopenharmony_ci Goto(&next_descriptor); 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci BIND(&next_descriptor); 3351cb0ef41Sopenharmony_ci { 3361cb0ef41Sopenharmony_ci Increment(&var_descriptor_number); 3371cb0ef41Sopenharmony_ci Branch(IntPtrEqual(var_result_index.value(), object_enum_length), 3381cb0ef41Sopenharmony_ci &after_loop, &loop); 3391cb0ef41Sopenharmony_ci } 3401cb0ef41Sopenharmony_ci } 3411cb0ef41Sopenharmony_ci BIND(&after_loop); 3421cb0ef41Sopenharmony_ci return FinalizeValuesOrEntriesJSArray(context, values_or_entries, 3431cb0ef41Sopenharmony_ci var_result_index.value(), array_map, 3441cb0ef41Sopenharmony_ci if_no_properties); 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci} 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ciTNode<JSArray> 3491cb0ef41Sopenharmony_ciObjectEntriesValuesBuiltinsAssembler::FinalizeValuesOrEntriesJSArray( 3501cb0ef41Sopenharmony_ci TNode<Context> context, TNode<FixedArray> result, TNode<IntPtrT> size, 3511cb0ef41Sopenharmony_ci TNode<Map> array_map, Label* if_empty) { 3521cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsJSArrayMap(array_map)); 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci GotoIf(IntPtrEqual(size, IntPtrConstant(0)), if_empty); 3551cb0ef41Sopenharmony_ci TNode<JSArray> array = AllocateJSArray(array_map, result, SmiTag(size)); 3561cb0ef41Sopenharmony_ci return array; 3571cb0ef41Sopenharmony_ci} 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectPrototypeHasOwnProperty, ObjectBuiltinsAssembler) { 3601cb0ef41Sopenharmony_ci auto object = Parameter<Object>(Descriptor::kReceiver); 3611cb0ef41Sopenharmony_ci auto key = Parameter<Object>(Descriptor::kKey); 3621cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci Label call_runtime(this), return_true(this), return_false(this), 3651cb0ef41Sopenharmony_ci to_primitive(this); 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci // Smi receivers do not have own properties, just perform ToPrimitive on the 3681cb0ef41Sopenharmony_ci // key. 3691cb0ef41Sopenharmony_ci Label if_objectisnotsmi(this); 3701cb0ef41Sopenharmony_ci Branch(TaggedIsSmi(object), &to_primitive, &if_objectisnotsmi); 3711cb0ef41Sopenharmony_ci BIND(&if_objectisnotsmi); 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_ci TNode<HeapObject> heap_object = CAST(object); 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ci TNode<Map> map = LoadMap(heap_object); 3761cb0ef41Sopenharmony_ci TNode<Uint16T> instance_type = LoadMapInstanceType(map); 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci { 3791cb0ef41Sopenharmony_ci TVARIABLE(IntPtrT, var_index); 3801cb0ef41Sopenharmony_ci TVARIABLE(Name, var_unique); 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci Label if_index(this, &var_index), if_unique_name(this), 3831cb0ef41Sopenharmony_ci if_notunique_name(this); 3841cb0ef41Sopenharmony_ci TryToName(key, &if_index, &var_index, &if_unique_name, &var_unique, 3851cb0ef41Sopenharmony_ci &call_runtime, &if_notunique_name); 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci BIND(&if_unique_name); 3881cb0ef41Sopenharmony_ci TryHasOwnProperty(heap_object, map, instance_type, var_unique.value(), 3891cb0ef41Sopenharmony_ci &return_true, &return_false, &call_runtime); 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci BIND(&if_index); 3921cb0ef41Sopenharmony_ci { 3931cb0ef41Sopenharmony_ci TryLookupElement(heap_object, map, instance_type, var_index.value(), 3941cb0ef41Sopenharmony_ci &return_true, &return_false, &return_false, 3951cb0ef41Sopenharmony_ci &call_runtime); 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci BIND(&if_notunique_name); 3991cb0ef41Sopenharmony_ci { 4001cb0ef41Sopenharmony_ci Label not_in_string_table(this); 4011cb0ef41Sopenharmony_ci TryInternalizeString(CAST(key), &if_index, &var_index, &if_unique_name, 4021cb0ef41Sopenharmony_ci &var_unique, ¬_in_string_table, &call_runtime); 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci BIND(¬_in_string_table); 4051cb0ef41Sopenharmony_ci { 4061cb0ef41Sopenharmony_ci // If the string was not found in the string table, then no regular 4071cb0ef41Sopenharmony_ci // object can have a property with that name, so return |false|. 4081cb0ef41Sopenharmony_ci // "Special API objects" with interceptors must take the slow path. 4091cb0ef41Sopenharmony_ci Branch(IsSpecialReceiverInstanceType(instance_type), &call_runtime, 4101cb0ef41Sopenharmony_ci &return_false); 4111cb0ef41Sopenharmony_ci } 4121cb0ef41Sopenharmony_ci } 4131cb0ef41Sopenharmony_ci } 4141cb0ef41Sopenharmony_ci BIND(&to_primitive); 4151cb0ef41Sopenharmony_ci GotoIf(IsNumber(key), &return_false); 4161cb0ef41Sopenharmony_ci Branch(IsName(CAST(key)), &return_false, &call_runtime); 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci BIND(&return_true); 4191cb0ef41Sopenharmony_ci Return(TrueConstant()); 4201cb0ef41Sopenharmony_ci 4211cb0ef41Sopenharmony_ci BIND(&return_false); 4221cb0ef41Sopenharmony_ci Return(FalseConstant()); 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci BIND(&call_runtime); 4251cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kObjectHasOwnProperty, context, object, key)); 4261cb0ef41Sopenharmony_ci} 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci// ES #sec-object.assign 4291cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectAssign, ObjectBuiltinsAssembler) { 4301cb0ef41Sopenharmony_ci TNode<IntPtrT> argc = ChangeInt32ToIntPtr( 4311cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount)); 4321cb0ef41Sopenharmony_ci CodeStubArguments args(this, argc); 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 4351cb0ef41Sopenharmony_ci TNode<Object> target = args.GetOptionalArgumentValue(0); 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci // 1. Let to be ? ToObject(target). 4381cb0ef41Sopenharmony_ci TNode<JSReceiver> to = ToObject_Inline(context, target); 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ci Label done(this); 4411cb0ef41Sopenharmony_ci // 2. If only one argument was passed, return to. 4421cb0ef41Sopenharmony_ci GotoIf(UintPtrLessThanOrEqual(args.GetLengthWithoutReceiver(), 4431cb0ef41Sopenharmony_ci IntPtrConstant(1)), 4441cb0ef41Sopenharmony_ci &done); 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci // 3. Let sources be the List of argument values starting with the 4471cb0ef41Sopenharmony_ci // second argument. 4481cb0ef41Sopenharmony_ci // 4. For each element nextSource of sources, in ascending index order, 4491cb0ef41Sopenharmony_ci args.ForEach( 4501cb0ef41Sopenharmony_ci [=](TNode<Object> next_source) { 4511cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kSetDataProperties, context, to, next_source); 4521cb0ef41Sopenharmony_ci }, 4531cb0ef41Sopenharmony_ci IntPtrConstant(1)); 4541cb0ef41Sopenharmony_ci Goto(&done); 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci // 5. Return to. 4571cb0ef41Sopenharmony_ci BIND(&done); 4581cb0ef41Sopenharmony_ci args.PopAndReturn(to); 4591cb0ef41Sopenharmony_ci} 4601cb0ef41Sopenharmony_ci 4611cb0ef41Sopenharmony_ci// ES #sec-object.keys 4621cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { 4631cb0ef41Sopenharmony_ci auto object = Parameter<Object>(Descriptor::kObject); 4641cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci TVARIABLE(Smi, var_length); 4671cb0ef41Sopenharmony_ci TVARIABLE(FixedArrayBase, var_elements); 4681cb0ef41Sopenharmony_ci Label if_empty(this, Label::kDeferred), if_empty_elements(this), 4691cb0ef41Sopenharmony_ci if_fast(this), if_slow(this, Label::kDeferred), if_join(this); 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ci // Check if the {object} has a usable enum cache. 4721cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(object), &if_slow); 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci TNode<Map> object_map = LoadMap(CAST(object)); 4751cb0ef41Sopenharmony_ci TNode<Uint32T> object_bit_field3 = LoadMapBitField3(object_map); 4761cb0ef41Sopenharmony_ci TNode<UintPtrT> object_enum_length = 4771cb0ef41Sopenharmony_ci DecodeWordFromWord32<Map::Bits3::EnumLengthBits>(object_bit_field3); 4781cb0ef41Sopenharmony_ci GotoIf( 4791cb0ef41Sopenharmony_ci WordEqual(object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)), 4801cb0ef41Sopenharmony_ci &if_slow); 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_ci // Ensure that the {object} doesn't have any elements. 4831cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsJSObjectMap(object_map)); 4841cb0ef41Sopenharmony_ci TNode<FixedArrayBase> object_elements = LoadElements(CAST(object)); 4851cb0ef41Sopenharmony_ci GotoIf(IsEmptyFixedArray(object_elements), &if_empty_elements); 4861cb0ef41Sopenharmony_ci Branch(IsEmptySlowElementDictionary(object_elements), &if_empty_elements, 4871cb0ef41Sopenharmony_ci &if_slow); 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci // Check whether there are enumerable properties. 4901cb0ef41Sopenharmony_ci BIND(&if_empty_elements); 4911cb0ef41Sopenharmony_ci Branch(WordEqual(object_enum_length, IntPtrConstant(0)), &if_empty, &if_fast); 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci // TODO(solanes): These if_xxx here and below seem to be quite similar for 4941cb0ef41Sopenharmony_ci // ObjectKeys and for ObjectGetOwnPropertyNames. In particular, if_fast seem 4951cb0ef41Sopenharmony_ci // to be the exact same. 4961cb0ef41Sopenharmony_ci BIND(&if_fast); 4971cb0ef41Sopenharmony_ci { 4981cb0ef41Sopenharmony_ci // The {object} has a usable enum cache, use that. 4991cb0ef41Sopenharmony_ci TNode<DescriptorArray> object_descriptors = LoadMapDescriptors(object_map); 5001cb0ef41Sopenharmony_ci TNode<EnumCache> object_enum_cache = LoadObjectField<EnumCache>( 5011cb0ef41Sopenharmony_ci object_descriptors, DescriptorArray::kEnumCacheOffset); 5021cb0ef41Sopenharmony_ci auto object_enum_keys = LoadObjectField<FixedArrayBase>( 5031cb0ef41Sopenharmony_ci object_enum_cache, EnumCache::kKeysOffset); 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ci // Allocate a JSArray and copy the elements from the {object_enum_keys}. 5061cb0ef41Sopenharmony_ci TNode<JSArray> array; 5071cb0ef41Sopenharmony_ci TNode<FixedArrayBase> elements; 5081cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 5091cb0ef41Sopenharmony_ci TNode<Map> array_map = 5101cb0ef41Sopenharmony_ci LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); 5111cb0ef41Sopenharmony_ci TNode<IntPtrT> object_enum_length_intptr = Signed(object_enum_length); 5121cb0ef41Sopenharmony_ci TNode<Smi> array_length = SmiTag(object_enum_length_intptr); 5131cb0ef41Sopenharmony_ci std::tie(array, elements) = AllocateUninitializedJSArrayWithElements( 5141cb0ef41Sopenharmony_ci PACKED_ELEMENTS, array_map, array_length, base::nullopt, 5151cb0ef41Sopenharmony_ci object_enum_length_intptr); 5161cb0ef41Sopenharmony_ci CopyFixedArrayElements(PACKED_ELEMENTS, object_enum_keys, elements, 5171cb0ef41Sopenharmony_ci object_enum_length_intptr, SKIP_WRITE_BARRIER); 5181cb0ef41Sopenharmony_ci Return(array); 5191cb0ef41Sopenharmony_ci } 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ci BIND(&if_empty); 5221cb0ef41Sopenharmony_ci { 5231cb0ef41Sopenharmony_ci // The {object} doesn't have any enumerable keys. 5241cb0ef41Sopenharmony_ci var_length = SmiConstant(0); 5251cb0ef41Sopenharmony_ci var_elements = EmptyFixedArrayConstant(); 5261cb0ef41Sopenharmony_ci Goto(&if_join); 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_ci BIND(&if_slow); 5301cb0ef41Sopenharmony_ci { 5311cb0ef41Sopenharmony_ci // Let the runtime compute the elements. 5321cb0ef41Sopenharmony_ci TNode<FixedArray> elements = 5331cb0ef41Sopenharmony_ci CAST(CallRuntime(Runtime::kObjectKeys, context, object)); 5341cb0ef41Sopenharmony_ci var_length = LoadObjectField<Smi>(elements, FixedArray::kLengthOffset); 5351cb0ef41Sopenharmony_ci var_elements = elements; 5361cb0ef41Sopenharmony_ci Goto(&if_join); 5371cb0ef41Sopenharmony_ci } 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ci BIND(&if_join); 5401cb0ef41Sopenharmony_ci { 5411cb0ef41Sopenharmony_ci // Wrap the elements into a proper JSArray and return that. 5421cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 5431cb0ef41Sopenharmony_ci TNode<Map> array_map = 5441cb0ef41Sopenharmony_ci LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); 5451cb0ef41Sopenharmony_ci TNode<JSArray> array = 5461cb0ef41Sopenharmony_ci AllocateJSArray(array_map, var_elements.value(), var_length.value()); 5471cb0ef41Sopenharmony_ci Return(array); 5481cb0ef41Sopenharmony_ci } 5491cb0ef41Sopenharmony_ci} 5501cb0ef41Sopenharmony_ci 5511cb0ef41Sopenharmony_ci// https://github.com/tc39/proposal-accessible-object-hasownproperty 5521cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectHasOwn, ObjectBuiltinsAssembler) { 5531cb0ef41Sopenharmony_ci // Object.prototype.hasOwnProperty() 5541cb0ef41Sopenharmony_ci // 1. Let obj be ? ToObject(O). 5551cb0ef41Sopenharmony_ci // 2. Let key be ? ToPropertyKey(P). 5561cb0ef41Sopenharmony_ci // 3. Return ? HasOwnProperty(obj, key). 5571cb0ef41Sopenharmony_ci // 5581cb0ef41Sopenharmony_ci // ObjectPrototypeHasOwnProperty has similar semantics with steps 1 and 2 5591cb0ef41Sopenharmony_ci // swapped. We check if ToObject can fail and delegate the rest of the 5601cb0ef41Sopenharmony_ci // execution to ObjectPrototypeHasOwnProperty. 5611cb0ef41Sopenharmony_ci 5621cb0ef41Sopenharmony_ci auto target = Parameter<Object>(Descriptor::kJSTarget); 5631cb0ef41Sopenharmony_ci auto new_target = Parameter<Object>(Descriptor::kJSNewTarget); 5641cb0ef41Sopenharmony_ci auto object = Parameter<Object>(Descriptor::kObject); 5651cb0ef41Sopenharmony_ci auto key = Parameter<Object>(Descriptor::kKey); 5661cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci // ToObject can only fail when object is undefined or null. 5691cb0ef41Sopenharmony_ci Label undefined_or_null(this), not_undefined_nor_null(this); 5701cb0ef41Sopenharmony_ci Branch(IsNullOrUndefined(object), &undefined_or_null, 5711cb0ef41Sopenharmony_ci ¬_undefined_nor_null); 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_ci BIND(&undefined_or_null); 5741cb0ef41Sopenharmony_ci ThrowTypeError(context, MessageTemplate::kUndefinedOrNullToObject); 5751cb0ef41Sopenharmony_ci 5761cb0ef41Sopenharmony_ci BIND(¬_undefined_nor_null); 5771cb0ef41Sopenharmony_ci Return(CallBuiltin(Builtin::kObjectPrototypeHasOwnProperty, context, target, 5781cb0ef41Sopenharmony_ci new_target, JSParameterCount(1), object, key)); 5791cb0ef41Sopenharmony_ci} 5801cb0ef41Sopenharmony_ci 5811cb0ef41Sopenharmony_ci// ES #sec-object.getOwnPropertyNames 5821cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) { 5831cb0ef41Sopenharmony_ci auto object = Parameter<Object>(Descriptor::kObject); 5841cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci TVARIABLE(Smi, var_length); 5871cb0ef41Sopenharmony_ci TVARIABLE(FixedArrayBase, var_elements); 5881cb0ef41Sopenharmony_ci Label if_empty(this, Label::kDeferred), if_empty_elements(this), 5891cb0ef41Sopenharmony_ci if_fast(this), try_fast(this, Label::kDeferred), 5901cb0ef41Sopenharmony_ci if_slow(this, Label::kDeferred), if_join(this); 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci // Take the slow path if the {object} IsCustomElementsReceiverInstanceType or 5931cb0ef41Sopenharmony_ci // has any elements. 5941cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(object), &if_slow); 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci TNode<Map> object_map = LoadMap(CAST(object)); 5971cb0ef41Sopenharmony_ci TNode<Uint16T> instance_type = LoadMapInstanceType(object_map); 5981cb0ef41Sopenharmony_ci GotoIf(IsCustomElementsReceiverInstanceType(instance_type), &if_slow); 5991cb0ef41Sopenharmony_ci TNode<FixedArrayBase> object_elements = LoadElements(CAST(object)); 6001cb0ef41Sopenharmony_ci GotoIf(IsEmptyFixedArray(object_elements), &if_empty_elements); 6011cb0ef41Sopenharmony_ci Branch(IsEmptySlowElementDictionary(object_elements), &if_empty_elements, 6021cb0ef41Sopenharmony_ci &if_slow); 6031cb0ef41Sopenharmony_ci 6041cb0ef41Sopenharmony_ci // Check if the {object} has a usable enum cache. 6051cb0ef41Sopenharmony_ci BIND(&if_empty_elements); 6061cb0ef41Sopenharmony_ci TNode<Uint32T> object_bit_field3 = LoadMapBitField3(object_map); 6071cb0ef41Sopenharmony_ci TNode<UintPtrT> object_enum_length = 6081cb0ef41Sopenharmony_ci DecodeWordFromWord32<Map::Bits3::EnumLengthBits>(object_bit_field3); 6091cb0ef41Sopenharmony_ci GotoIf( 6101cb0ef41Sopenharmony_ci WordEqual(object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)), 6111cb0ef41Sopenharmony_ci &try_fast); 6121cb0ef41Sopenharmony_ci 6131cb0ef41Sopenharmony_ci // Check whether all own properties are enumerable. 6141cb0ef41Sopenharmony_ci TNode<UintPtrT> number_descriptors = 6151cb0ef41Sopenharmony_ci DecodeWordFromWord32<Map::Bits3::NumberOfOwnDescriptorsBits>( 6161cb0ef41Sopenharmony_ci object_bit_field3); 6171cb0ef41Sopenharmony_ci GotoIfNot(WordEqual(object_enum_length, number_descriptors), &if_slow); 6181cb0ef41Sopenharmony_ci 6191cb0ef41Sopenharmony_ci // Check whether there are enumerable properties. 6201cb0ef41Sopenharmony_ci Branch(WordEqual(object_enum_length, IntPtrConstant(0)), &if_empty, &if_fast); 6211cb0ef41Sopenharmony_ci 6221cb0ef41Sopenharmony_ci // TODO(solanes): These if_xxx here and below seem to be quite similar for 6231cb0ef41Sopenharmony_ci // ObjectKeys and for ObjectGetOwnPropertyNames. In particular, if_fast seem 6241cb0ef41Sopenharmony_ci // to be the exact same. 6251cb0ef41Sopenharmony_ci BIND(&if_fast); 6261cb0ef41Sopenharmony_ci { 6271cb0ef41Sopenharmony_ci // The {object} has a usable enum cache and all own properties are 6281cb0ef41Sopenharmony_ci // enumerable, use that. 6291cb0ef41Sopenharmony_ci TNode<DescriptorArray> object_descriptors = LoadMapDescriptors(object_map); 6301cb0ef41Sopenharmony_ci TNode<EnumCache> object_enum_cache = LoadObjectField<EnumCache>( 6311cb0ef41Sopenharmony_ci object_descriptors, DescriptorArray::kEnumCacheOffset); 6321cb0ef41Sopenharmony_ci auto object_enum_keys = LoadObjectField<FixedArrayBase>( 6331cb0ef41Sopenharmony_ci object_enum_cache, EnumCache::kKeysOffset); 6341cb0ef41Sopenharmony_ci 6351cb0ef41Sopenharmony_ci // Allocate a JSArray and copy the elements from the {object_enum_keys}. 6361cb0ef41Sopenharmony_ci TNode<JSArray> array; 6371cb0ef41Sopenharmony_ci TNode<FixedArrayBase> elements; 6381cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 6391cb0ef41Sopenharmony_ci TNode<Map> array_map = 6401cb0ef41Sopenharmony_ci LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); 6411cb0ef41Sopenharmony_ci TNode<IntPtrT> object_enum_length_intptr = Signed(object_enum_length); 6421cb0ef41Sopenharmony_ci TNode<Smi> array_length = SmiTag(object_enum_length_intptr); 6431cb0ef41Sopenharmony_ci std::tie(array, elements) = AllocateUninitializedJSArrayWithElements( 6441cb0ef41Sopenharmony_ci PACKED_ELEMENTS, array_map, array_length, base::nullopt, 6451cb0ef41Sopenharmony_ci object_enum_length_intptr); 6461cb0ef41Sopenharmony_ci CopyFixedArrayElements(PACKED_ELEMENTS, object_enum_keys, elements, 6471cb0ef41Sopenharmony_ci object_enum_length_intptr, SKIP_WRITE_BARRIER); 6481cb0ef41Sopenharmony_ci Return(array); 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci 6511cb0ef41Sopenharmony_ci BIND(&try_fast); 6521cb0ef41Sopenharmony_ci { 6531cb0ef41Sopenharmony_ci // Let the runtime compute the elements and try initializing enum cache. 6541cb0ef41Sopenharmony_ci TNode<FixedArray> elements = CAST(CallRuntime( 6551cb0ef41Sopenharmony_ci Runtime::kObjectGetOwnPropertyNamesTryFast, context, object)); 6561cb0ef41Sopenharmony_ci var_length = LoadObjectField<Smi>(elements, FixedArray::kLengthOffset); 6571cb0ef41Sopenharmony_ci var_elements = elements; 6581cb0ef41Sopenharmony_ci Goto(&if_join); 6591cb0ef41Sopenharmony_ci } 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ci BIND(&if_empty); 6621cb0ef41Sopenharmony_ci { 6631cb0ef41Sopenharmony_ci // The {object} doesn't have any enumerable keys. 6641cb0ef41Sopenharmony_ci var_length = SmiConstant(0); 6651cb0ef41Sopenharmony_ci var_elements = EmptyFixedArrayConstant(); 6661cb0ef41Sopenharmony_ci Goto(&if_join); 6671cb0ef41Sopenharmony_ci } 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_ci BIND(&if_slow); 6701cb0ef41Sopenharmony_ci { 6711cb0ef41Sopenharmony_ci // Let the runtime compute the elements. 6721cb0ef41Sopenharmony_ci TNode<FixedArray> elements = 6731cb0ef41Sopenharmony_ci CAST(CallRuntime(Runtime::kObjectGetOwnPropertyNames, context, object)); 6741cb0ef41Sopenharmony_ci var_length = LoadObjectField<Smi>(elements, FixedArray::kLengthOffset); 6751cb0ef41Sopenharmony_ci var_elements = elements; 6761cb0ef41Sopenharmony_ci Goto(&if_join); 6771cb0ef41Sopenharmony_ci } 6781cb0ef41Sopenharmony_ci 6791cb0ef41Sopenharmony_ci BIND(&if_join); 6801cb0ef41Sopenharmony_ci { 6811cb0ef41Sopenharmony_ci // Wrap the elements into a proper JSArray and return that. 6821cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 6831cb0ef41Sopenharmony_ci TNode<Map> array_map = 6841cb0ef41Sopenharmony_ci LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); 6851cb0ef41Sopenharmony_ci TNode<JSArray> array = 6861cb0ef41Sopenharmony_ci AllocateJSArray(array_map, var_elements.value(), var_length.value()); 6871cb0ef41Sopenharmony_ci Return(array); 6881cb0ef41Sopenharmony_ci } 6891cb0ef41Sopenharmony_ci} 6901cb0ef41Sopenharmony_ci 6911cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectValues, ObjectEntriesValuesBuiltinsAssembler) { 6921cb0ef41Sopenharmony_ci auto object = UncheckedParameter<JSObject>(Descriptor::kObject); 6931cb0ef41Sopenharmony_ci auto context = UncheckedParameter<Context>(Descriptor::kContext); 6941cb0ef41Sopenharmony_ci GetOwnValuesOrEntries(context, object, CollectType::kValues); 6951cb0ef41Sopenharmony_ci} 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectEntries, ObjectEntriesValuesBuiltinsAssembler) { 6981cb0ef41Sopenharmony_ci auto object = UncheckedParameter<JSObject>(Descriptor::kObject); 6991cb0ef41Sopenharmony_ci auto context = UncheckedParameter<Context>(Descriptor::kContext); 7001cb0ef41Sopenharmony_ci GetOwnValuesOrEntries(context, object, CollectType::kEntries); 7011cb0ef41Sopenharmony_ci} 7021cb0ef41Sopenharmony_ci 7031cb0ef41Sopenharmony_ci// ES #sec-object.prototype.isprototypeof 7041cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectPrototypeIsPrototypeOf, ObjectBuiltinsAssembler) { 7051cb0ef41Sopenharmony_ci auto receiver = Parameter<Object>(Descriptor::kReceiver); 7061cb0ef41Sopenharmony_ci auto value = Parameter<Object>(Descriptor::kValue); 7071cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 7081cb0ef41Sopenharmony_ci Label if_receiverisnullorundefined(this, Label::kDeferred), 7091cb0ef41Sopenharmony_ci if_valueisnotreceiver(this, Label::kDeferred); 7101cb0ef41Sopenharmony_ci 7111cb0ef41Sopenharmony_ci // We only check whether {value} is a Smi here, so that the 7121cb0ef41Sopenharmony_ci // prototype chain walk below can safely access the {value}s 7131cb0ef41Sopenharmony_ci // map. We don't rule out Primitive {value}s, since all of 7141cb0ef41Sopenharmony_ci // them have null as their prototype, so the chain walk below 7151cb0ef41Sopenharmony_ci // immediately aborts and returns false anyways. 7161cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(value), &if_valueisnotreceiver); 7171cb0ef41Sopenharmony_ci 7181cb0ef41Sopenharmony_ci { 7191cb0ef41Sopenharmony_ci TNode<HeapObject> value_heap_object = CAST(value); 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci // Check if {receiver} is either null or undefined and in that case, 7221cb0ef41Sopenharmony_ci // invoke the ToObject builtin, which raises the appropriate error. 7231cb0ef41Sopenharmony_ci // Otherwise we don't need to invoke ToObject, since {receiver} is 7241cb0ef41Sopenharmony_ci // either already a JSReceiver, in which case ToObject is a no-op, 7251cb0ef41Sopenharmony_ci // or it's a Primitive and ToObject would allocate a fresh 7261cb0ef41Sopenharmony_ci // JSPrimitiveWrapper wrapper, which wouldn't be identical to any existing 7271cb0ef41Sopenharmony_ci // JSReceiver found in the prototype chain of {value}, hence it will return 7281cb0ef41Sopenharmony_ci // false no matter if we search for the Primitive {receiver} or 7291cb0ef41Sopenharmony_ci // a newly allocated JSPrimitiveWrapper wrapper for {receiver}. 7301cb0ef41Sopenharmony_ci GotoIf(IsNull(receiver), &if_receiverisnullorundefined); 7311cb0ef41Sopenharmony_ci GotoIf(IsUndefined(receiver), &if_receiverisnullorundefined); 7321cb0ef41Sopenharmony_ci 7331cb0ef41Sopenharmony_ci // Loop through the prototype chain looking for the {receiver}. 7341cb0ef41Sopenharmony_ci Return(HasInPrototypeChain(context, value_heap_object, receiver)); 7351cb0ef41Sopenharmony_ci 7361cb0ef41Sopenharmony_ci BIND(&if_receiverisnullorundefined); 7371cb0ef41Sopenharmony_ci { 7381cb0ef41Sopenharmony_ci // If {value} is a primitive HeapObject, we need to return 7391cb0ef41Sopenharmony_ci // false instead of throwing an exception per order of the 7401cb0ef41Sopenharmony_ci // steps in the specification, so check that first here. 7411cb0ef41Sopenharmony_ci GotoIfNot(IsJSReceiver(value_heap_object), &if_valueisnotreceiver); 7421cb0ef41Sopenharmony_ci 7431cb0ef41Sopenharmony_ci // Simulate the ToObject invocation on {receiver}. 7441cb0ef41Sopenharmony_ci ToObject(context, receiver); 7451cb0ef41Sopenharmony_ci Unreachable(); 7461cb0ef41Sopenharmony_ci } 7471cb0ef41Sopenharmony_ci } 7481cb0ef41Sopenharmony_ci 7491cb0ef41Sopenharmony_ci BIND(&if_valueisnotreceiver); 7501cb0ef41Sopenharmony_ci Return(FalseConstant()); 7511cb0ef41Sopenharmony_ci} 7521cb0ef41Sopenharmony_ci 7531cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) { 7541cb0ef41Sopenharmony_ci Label checkstringtag(this), if_arguments(this), if_array(this), 7551cb0ef41Sopenharmony_ci if_boolean(this), if_date(this), if_error(this), if_function(this), 7561cb0ef41Sopenharmony_ci if_number(this, Label::kDeferred), if_object(this), if_primitive(this), 7571cb0ef41Sopenharmony_ci if_proxy(this, Label::kDeferred), if_regexp(this), if_string(this), 7581cb0ef41Sopenharmony_ci if_symbol(this, Label::kDeferred), if_value(this), 7591cb0ef41Sopenharmony_ci if_bigint(this, Label::kDeferred); 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_ci auto receiver = Parameter<Object>(Descriptor::kReceiver); 7621cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 7631cb0ef41Sopenharmony_ci 7641cb0ef41Sopenharmony_ci TVARIABLE(String, var_default); 7651cb0ef41Sopenharmony_ci TVARIABLE(HeapObject, var_holder); 7661cb0ef41Sopenharmony_ci 7671cb0ef41Sopenharmony_ci // This is arranged to check the likely cases first. 7681cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(receiver), &if_number); 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_ci TNode<HeapObject> receiver_heap_object = CAST(receiver); 7711cb0ef41Sopenharmony_ci TNode<Map> receiver_map = LoadMap(receiver_heap_object); 7721cb0ef41Sopenharmony_ci var_holder = receiver_heap_object; 7731cb0ef41Sopenharmony_ci TNode<Uint16T> receiver_instance_type = LoadMapInstanceType(receiver_map); 7741cb0ef41Sopenharmony_ci GotoIf(IsPrimitiveInstanceType(receiver_instance_type), &if_primitive); 7751cb0ef41Sopenharmony_ci GotoIf(IsFunctionInstanceType(receiver_instance_type), &if_function); 7761cb0ef41Sopenharmony_ci const struct { 7771cb0ef41Sopenharmony_ci InstanceType value; 7781cb0ef41Sopenharmony_ci Label* label; 7791cb0ef41Sopenharmony_ci } kJumpTable[] = {{JS_OBJECT_TYPE, &if_object}, 7801cb0ef41Sopenharmony_ci {JS_ARRAY_TYPE, &if_array}, 7811cb0ef41Sopenharmony_ci {JS_REG_EXP_TYPE, &if_regexp}, 7821cb0ef41Sopenharmony_ci {JS_ARGUMENTS_OBJECT_TYPE, &if_arguments}, 7831cb0ef41Sopenharmony_ci {JS_DATE_TYPE, &if_date}, 7841cb0ef41Sopenharmony_ci {JS_API_OBJECT_TYPE, &if_object}, 7851cb0ef41Sopenharmony_ci {JS_SPECIAL_API_OBJECT_TYPE, &if_object}, 7861cb0ef41Sopenharmony_ci {JS_PROXY_TYPE, &if_proxy}, 7871cb0ef41Sopenharmony_ci {JS_ERROR_TYPE, &if_error}, 7881cb0ef41Sopenharmony_ci {JS_PRIMITIVE_WRAPPER_TYPE, &if_value}}; 7891cb0ef41Sopenharmony_ci size_t const kNumCases = arraysize(kJumpTable); 7901cb0ef41Sopenharmony_ci Label* case_labels[kNumCases]; 7911cb0ef41Sopenharmony_ci int32_t case_values[kNumCases]; 7921cb0ef41Sopenharmony_ci for (size_t i = 0; i < kNumCases; ++i) { 7931cb0ef41Sopenharmony_ci case_labels[i] = kJumpTable[i].label; 7941cb0ef41Sopenharmony_ci case_values[i] = kJumpTable[i].value; 7951cb0ef41Sopenharmony_ci } 7961cb0ef41Sopenharmony_ci Switch(receiver_instance_type, &if_object, case_values, case_labels, 7971cb0ef41Sopenharmony_ci arraysize(case_values)); 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_ci BIND(&if_arguments); 8001cb0ef41Sopenharmony_ci { 8011cb0ef41Sopenharmony_ci var_default = ArgumentsToStringConstant(); 8021cb0ef41Sopenharmony_ci Goto(&checkstringtag); 8031cb0ef41Sopenharmony_ci } 8041cb0ef41Sopenharmony_ci 8051cb0ef41Sopenharmony_ci BIND(&if_array); 8061cb0ef41Sopenharmony_ci { 8071cb0ef41Sopenharmony_ci var_default = ArrayToStringConstant(); 8081cb0ef41Sopenharmony_ci Goto(&checkstringtag); 8091cb0ef41Sopenharmony_ci } 8101cb0ef41Sopenharmony_ci 8111cb0ef41Sopenharmony_ci BIND(&if_boolean); 8121cb0ef41Sopenharmony_ci { 8131cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 8141cb0ef41Sopenharmony_ci TNode<JSFunction> boolean_constructor = CAST( 8151cb0ef41Sopenharmony_ci LoadContextElement(native_context, Context::BOOLEAN_FUNCTION_INDEX)); 8161cb0ef41Sopenharmony_ci TNode<Map> boolean_initial_map = LoadObjectField<Map>( 8171cb0ef41Sopenharmony_ci boolean_constructor, JSFunction::kPrototypeOrInitialMapOffset); 8181cb0ef41Sopenharmony_ci TNode<HeapObject> boolean_prototype = 8191cb0ef41Sopenharmony_ci LoadObjectField<HeapObject>(boolean_initial_map, Map::kPrototypeOffset); 8201cb0ef41Sopenharmony_ci var_default = BooleanToStringConstant(); 8211cb0ef41Sopenharmony_ci var_holder = boolean_prototype; 8221cb0ef41Sopenharmony_ci Goto(&checkstringtag); 8231cb0ef41Sopenharmony_ci } 8241cb0ef41Sopenharmony_ci 8251cb0ef41Sopenharmony_ci BIND(&if_date); 8261cb0ef41Sopenharmony_ci { 8271cb0ef41Sopenharmony_ci var_default = DateToStringConstant(); 8281cb0ef41Sopenharmony_ci Goto(&checkstringtag); 8291cb0ef41Sopenharmony_ci } 8301cb0ef41Sopenharmony_ci 8311cb0ef41Sopenharmony_ci BIND(&if_error); 8321cb0ef41Sopenharmony_ci { 8331cb0ef41Sopenharmony_ci var_default = ErrorToStringConstant(); 8341cb0ef41Sopenharmony_ci Goto(&checkstringtag); 8351cb0ef41Sopenharmony_ci } 8361cb0ef41Sopenharmony_ci 8371cb0ef41Sopenharmony_ci BIND(&if_function); 8381cb0ef41Sopenharmony_ci { 8391cb0ef41Sopenharmony_ci var_default = FunctionToStringConstant(); 8401cb0ef41Sopenharmony_ci Goto(&checkstringtag); 8411cb0ef41Sopenharmony_ci } 8421cb0ef41Sopenharmony_ci 8431cb0ef41Sopenharmony_ci BIND(&if_number); 8441cb0ef41Sopenharmony_ci { 8451cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 8461cb0ef41Sopenharmony_ci TNode<JSFunction> number_constructor = CAST( 8471cb0ef41Sopenharmony_ci LoadContextElement(native_context, Context::NUMBER_FUNCTION_INDEX)); 8481cb0ef41Sopenharmony_ci TNode<Map> number_initial_map = LoadObjectField<Map>( 8491cb0ef41Sopenharmony_ci number_constructor, JSFunction::kPrototypeOrInitialMapOffset); 8501cb0ef41Sopenharmony_ci TNode<HeapObject> number_prototype = 8511cb0ef41Sopenharmony_ci LoadObjectField<HeapObject>(number_initial_map, Map::kPrototypeOffset); 8521cb0ef41Sopenharmony_ci var_default = NumberToStringConstant(); 8531cb0ef41Sopenharmony_ci var_holder = number_prototype; 8541cb0ef41Sopenharmony_ci Goto(&checkstringtag); 8551cb0ef41Sopenharmony_ci } 8561cb0ef41Sopenharmony_ci 8571cb0ef41Sopenharmony_ci BIND(&if_object); 8581cb0ef41Sopenharmony_ci { 8591cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsJSReceiver(CAST(receiver))); 8601cb0ef41Sopenharmony_ci var_default = ObjectToStringConstant(); 8611cb0ef41Sopenharmony_ci Goto(&checkstringtag); 8621cb0ef41Sopenharmony_ci } 8631cb0ef41Sopenharmony_ci 8641cb0ef41Sopenharmony_ci BIND(&if_primitive); 8651cb0ef41Sopenharmony_ci { 8661cb0ef41Sopenharmony_ci Label return_undefined(this); 8671cb0ef41Sopenharmony_ci 8681cb0ef41Sopenharmony_ci GotoIf(IsStringInstanceType(receiver_instance_type), &if_string); 8691cb0ef41Sopenharmony_ci GotoIf(IsBigIntInstanceType(receiver_instance_type), &if_bigint); 8701cb0ef41Sopenharmony_ci GotoIf(IsBooleanMap(receiver_map), &if_boolean); 8711cb0ef41Sopenharmony_ci GotoIf(IsHeapNumberMap(receiver_map), &if_number); 8721cb0ef41Sopenharmony_ci GotoIf(IsSymbolMap(receiver_map), &if_symbol); 8731cb0ef41Sopenharmony_ci GotoIf(IsUndefined(receiver), &return_undefined); 8741cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsNull(receiver)); 8751cb0ef41Sopenharmony_ci Return(NullToStringConstant()); 8761cb0ef41Sopenharmony_ci 8771cb0ef41Sopenharmony_ci BIND(&return_undefined); 8781cb0ef41Sopenharmony_ci Return(UndefinedToStringConstant()); 8791cb0ef41Sopenharmony_ci } 8801cb0ef41Sopenharmony_ci 8811cb0ef41Sopenharmony_ci BIND(&if_proxy); 8821cb0ef41Sopenharmony_ci { 8831cb0ef41Sopenharmony_ci // If {receiver} is a proxy for a JSArray, we default to "[object Array]", 8841cb0ef41Sopenharmony_ci // otherwise we default to "[object Object]" or "[object Function]" here, 8851cb0ef41Sopenharmony_ci // depending on whether the {receiver} is callable. The order matters here, 8861cb0ef41Sopenharmony_ci // i.e. we need to execute the %ArrayIsArray check before the [[Get]] below, 8871cb0ef41Sopenharmony_ci // as the exception is observable. 8881cb0ef41Sopenharmony_ci TNode<Object> receiver_is_array = 8891cb0ef41Sopenharmony_ci CallRuntime(Runtime::kArrayIsArray, context, receiver); 8901cb0ef41Sopenharmony_ci TNode<String> builtin_tag = Select<String>( 8911cb0ef41Sopenharmony_ci IsTrue(receiver_is_array), [=] { return ArrayStringConstant(); }, 8921cb0ef41Sopenharmony_ci [=] { 8931cb0ef41Sopenharmony_ci return Select<String>( 8941cb0ef41Sopenharmony_ci IsCallableMap(receiver_map), 8951cb0ef41Sopenharmony_ci [=] { return FunctionStringConstant(); }, 8961cb0ef41Sopenharmony_ci [=] { return ObjectStringConstant(); }); 8971cb0ef41Sopenharmony_ci }); 8981cb0ef41Sopenharmony_ci 8991cb0ef41Sopenharmony_ci // Lookup the @@toStringTag property on the {receiver}. 9001cb0ef41Sopenharmony_ci TVARIABLE(Object, var_tag, 9011cb0ef41Sopenharmony_ci GetProperty(context, receiver, 9021cb0ef41Sopenharmony_ci isolate()->factory()->to_string_tag_symbol())); 9031cb0ef41Sopenharmony_ci Label if_tagisnotstring(this), if_tagisstring(this); 9041cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(var_tag.value()), &if_tagisnotstring); 9051cb0ef41Sopenharmony_ci Branch(IsString(CAST(var_tag.value())), &if_tagisstring, 9061cb0ef41Sopenharmony_ci &if_tagisnotstring); 9071cb0ef41Sopenharmony_ci BIND(&if_tagisnotstring); 9081cb0ef41Sopenharmony_ci { 9091cb0ef41Sopenharmony_ci var_tag = builtin_tag; 9101cb0ef41Sopenharmony_ci Goto(&if_tagisstring); 9111cb0ef41Sopenharmony_ci } 9121cb0ef41Sopenharmony_ci BIND(&if_tagisstring); 9131cb0ef41Sopenharmony_ci ReturnToStringFormat(context, CAST(var_tag.value())); 9141cb0ef41Sopenharmony_ci } 9151cb0ef41Sopenharmony_ci 9161cb0ef41Sopenharmony_ci BIND(&if_regexp); 9171cb0ef41Sopenharmony_ci { 9181cb0ef41Sopenharmony_ci var_default = RegexpToStringConstant(); 9191cb0ef41Sopenharmony_ci Goto(&checkstringtag); 9201cb0ef41Sopenharmony_ci } 9211cb0ef41Sopenharmony_ci 9221cb0ef41Sopenharmony_ci BIND(&if_string); 9231cb0ef41Sopenharmony_ci { 9241cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 9251cb0ef41Sopenharmony_ci TNode<JSFunction> string_constructor = CAST( 9261cb0ef41Sopenharmony_ci LoadContextElement(native_context, Context::STRING_FUNCTION_INDEX)); 9271cb0ef41Sopenharmony_ci TNode<Map> string_initial_map = LoadObjectField<Map>( 9281cb0ef41Sopenharmony_ci string_constructor, JSFunction::kPrototypeOrInitialMapOffset); 9291cb0ef41Sopenharmony_ci TNode<HeapObject> string_prototype = 9301cb0ef41Sopenharmony_ci LoadObjectField<HeapObject>(string_initial_map, Map::kPrototypeOffset); 9311cb0ef41Sopenharmony_ci var_default = StringToStringConstant(); 9321cb0ef41Sopenharmony_ci var_holder = string_prototype; 9331cb0ef41Sopenharmony_ci Goto(&checkstringtag); 9341cb0ef41Sopenharmony_ci } 9351cb0ef41Sopenharmony_ci 9361cb0ef41Sopenharmony_ci BIND(&if_symbol); 9371cb0ef41Sopenharmony_ci { 9381cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 9391cb0ef41Sopenharmony_ci TNode<JSFunction> symbol_constructor = CAST( 9401cb0ef41Sopenharmony_ci LoadContextElement(native_context, Context::SYMBOL_FUNCTION_INDEX)); 9411cb0ef41Sopenharmony_ci TNode<Map> symbol_initial_map = LoadObjectField<Map>( 9421cb0ef41Sopenharmony_ci symbol_constructor, JSFunction::kPrototypeOrInitialMapOffset); 9431cb0ef41Sopenharmony_ci TNode<HeapObject> symbol_prototype = 9441cb0ef41Sopenharmony_ci LoadObjectField<HeapObject>(symbol_initial_map, Map::kPrototypeOffset); 9451cb0ef41Sopenharmony_ci var_default = ObjectToStringConstant(); 9461cb0ef41Sopenharmony_ci var_holder = symbol_prototype; 9471cb0ef41Sopenharmony_ci Goto(&checkstringtag); 9481cb0ef41Sopenharmony_ci } 9491cb0ef41Sopenharmony_ci 9501cb0ef41Sopenharmony_ci BIND(&if_bigint); 9511cb0ef41Sopenharmony_ci { 9521cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 9531cb0ef41Sopenharmony_ci TNode<JSFunction> bigint_constructor = CAST( 9541cb0ef41Sopenharmony_ci LoadContextElement(native_context, Context::BIGINT_FUNCTION_INDEX)); 9551cb0ef41Sopenharmony_ci TNode<Map> bigint_initial_map = LoadObjectField<Map>( 9561cb0ef41Sopenharmony_ci bigint_constructor, JSFunction::kPrototypeOrInitialMapOffset); 9571cb0ef41Sopenharmony_ci TNode<HeapObject> bigint_prototype = 9581cb0ef41Sopenharmony_ci LoadObjectField<HeapObject>(bigint_initial_map, Map::kPrototypeOffset); 9591cb0ef41Sopenharmony_ci var_default = ObjectToStringConstant(); 9601cb0ef41Sopenharmony_ci var_holder = bigint_prototype; 9611cb0ef41Sopenharmony_ci Goto(&checkstringtag); 9621cb0ef41Sopenharmony_ci } 9631cb0ef41Sopenharmony_ci 9641cb0ef41Sopenharmony_ci BIND(&if_value); 9651cb0ef41Sopenharmony_ci { 9661cb0ef41Sopenharmony_ci Label if_value_is_number(this, Label::kDeferred), 9671cb0ef41Sopenharmony_ci if_value_is_boolean(this, Label::kDeferred), 9681cb0ef41Sopenharmony_ci if_value_is_symbol(this, Label::kDeferred), 9691cb0ef41Sopenharmony_ci if_value_is_bigint(this, Label::kDeferred), 9701cb0ef41Sopenharmony_ci if_value_is_string(this, Label::kDeferred); 9711cb0ef41Sopenharmony_ci 9721cb0ef41Sopenharmony_ci TNode<Object> receiver_value = 9731cb0ef41Sopenharmony_ci LoadJSPrimitiveWrapperValue(CAST(receiver_heap_object)); 9741cb0ef41Sopenharmony_ci // We need to start with the object to see if the value was a subclass 9751cb0ef41Sopenharmony_ci // which might have interesting properties. 9761cb0ef41Sopenharmony_ci var_holder = receiver_heap_object; 9771cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(receiver_value), &if_value_is_number); 9781cb0ef41Sopenharmony_ci TNode<Map> receiver_value_map = LoadMap(CAST(receiver_value)); 9791cb0ef41Sopenharmony_ci GotoIf(IsHeapNumberMap(receiver_value_map), &if_value_is_number); 9801cb0ef41Sopenharmony_ci GotoIf(IsBooleanMap(receiver_value_map), &if_value_is_boolean); 9811cb0ef41Sopenharmony_ci GotoIf(IsSymbolMap(receiver_value_map), &if_value_is_symbol); 9821cb0ef41Sopenharmony_ci TNode<Uint16T> receiver_value_instance_type = 9831cb0ef41Sopenharmony_ci LoadMapInstanceType(receiver_value_map); 9841cb0ef41Sopenharmony_ci GotoIf(IsBigIntInstanceType(receiver_value_instance_type), 9851cb0ef41Sopenharmony_ci &if_value_is_bigint); 9861cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsStringInstanceType(receiver_value_instance_type)); 9871cb0ef41Sopenharmony_ci Goto(&if_value_is_string); 9881cb0ef41Sopenharmony_ci 9891cb0ef41Sopenharmony_ci BIND(&if_value_is_number); 9901cb0ef41Sopenharmony_ci { 9911cb0ef41Sopenharmony_ci var_default = NumberToStringConstant(); 9921cb0ef41Sopenharmony_ci Goto(&checkstringtag); 9931cb0ef41Sopenharmony_ci } 9941cb0ef41Sopenharmony_ci 9951cb0ef41Sopenharmony_ci BIND(&if_value_is_boolean); 9961cb0ef41Sopenharmony_ci { 9971cb0ef41Sopenharmony_ci var_default = BooleanToStringConstant(); 9981cb0ef41Sopenharmony_ci Goto(&checkstringtag); 9991cb0ef41Sopenharmony_ci } 10001cb0ef41Sopenharmony_ci 10011cb0ef41Sopenharmony_ci BIND(&if_value_is_string); 10021cb0ef41Sopenharmony_ci { 10031cb0ef41Sopenharmony_ci var_default = StringToStringConstant(); 10041cb0ef41Sopenharmony_ci Goto(&checkstringtag); 10051cb0ef41Sopenharmony_ci } 10061cb0ef41Sopenharmony_ci 10071cb0ef41Sopenharmony_ci BIND(&if_value_is_bigint); 10081cb0ef41Sopenharmony_ci { 10091cb0ef41Sopenharmony_ci var_default = ObjectToStringConstant(); 10101cb0ef41Sopenharmony_ci Goto(&checkstringtag); 10111cb0ef41Sopenharmony_ci } 10121cb0ef41Sopenharmony_ci 10131cb0ef41Sopenharmony_ci BIND(&if_value_is_symbol); 10141cb0ef41Sopenharmony_ci { 10151cb0ef41Sopenharmony_ci var_default = ObjectToStringConstant(); 10161cb0ef41Sopenharmony_ci Goto(&checkstringtag); 10171cb0ef41Sopenharmony_ci } 10181cb0ef41Sopenharmony_ci } 10191cb0ef41Sopenharmony_ci 10201cb0ef41Sopenharmony_ci BIND(&checkstringtag); 10211cb0ef41Sopenharmony_ci { 10221cb0ef41Sopenharmony_ci // Check if all relevant maps (including the prototype maps) don't 10231cb0ef41Sopenharmony_ci // have any interesting symbols (i.e. that none of them have the 10241cb0ef41Sopenharmony_ci // @@toStringTag property). 10251cb0ef41Sopenharmony_ci Label loop(this, &var_holder), return_default(this), 10261cb0ef41Sopenharmony_ci return_generic(this, Label::kDeferred); 10271cb0ef41Sopenharmony_ci Goto(&loop); 10281cb0ef41Sopenharmony_ci BIND(&loop); 10291cb0ef41Sopenharmony_ci { 10301cb0ef41Sopenharmony_ci TNode<HeapObject> holder = var_holder.value(); 10311cb0ef41Sopenharmony_ci GotoIf(IsNull(holder), &return_default); 10321cb0ef41Sopenharmony_ci TNode<Map> holder_map = LoadMap(holder); 10331cb0ef41Sopenharmony_ci TNode<Uint32T> holder_bit_field3 = LoadMapBitField3(holder_map); 10341cb0ef41Sopenharmony_ci GotoIf(IsSetWord32<Map::Bits3::MayHaveInterestingSymbolsBit>( 10351cb0ef41Sopenharmony_ci holder_bit_field3), 10361cb0ef41Sopenharmony_ci &return_generic); 10371cb0ef41Sopenharmony_ci var_holder = LoadMapPrototype(holder_map); 10381cb0ef41Sopenharmony_ci Goto(&loop); 10391cb0ef41Sopenharmony_ci } 10401cb0ef41Sopenharmony_ci 10411cb0ef41Sopenharmony_ci BIND(&return_generic); 10421cb0ef41Sopenharmony_ci { 10431cb0ef41Sopenharmony_ci TNode<Object> tag = GetProperty(context, ToObject(context, receiver), 10441cb0ef41Sopenharmony_ci ToStringTagSymbolConstant()); 10451cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(tag), &return_default); 10461cb0ef41Sopenharmony_ci GotoIfNot(IsString(CAST(tag)), &return_default); 10471cb0ef41Sopenharmony_ci ReturnToStringFormat(context, CAST(tag)); 10481cb0ef41Sopenharmony_ci } 10491cb0ef41Sopenharmony_ci 10501cb0ef41Sopenharmony_ci BIND(&return_default); 10511cb0ef41Sopenharmony_ci Return(var_default.value()); 10521cb0ef41Sopenharmony_ci } 10531cb0ef41Sopenharmony_ci} 10541cb0ef41Sopenharmony_ci 10551cb0ef41Sopenharmony_ci// ES #sec-object.create 10561cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) { 10571cb0ef41Sopenharmony_ci int const kPrototypeArg = 0; 10581cb0ef41Sopenharmony_ci int const kPropertiesArg = 1; 10591cb0ef41Sopenharmony_ci 10601cb0ef41Sopenharmony_ci TNode<IntPtrT> argc = ChangeInt32ToIntPtr( 10611cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount)); 10621cb0ef41Sopenharmony_ci CodeStubArguments args(this, argc); 10631cb0ef41Sopenharmony_ci 10641cb0ef41Sopenharmony_ci TNode<Object> prototype = args.GetOptionalArgumentValue(kPrototypeArg); 10651cb0ef41Sopenharmony_ci TNode<Object> properties = args.GetOptionalArgumentValue(kPropertiesArg); 10661cb0ef41Sopenharmony_ci auto native_context = Parameter<NativeContext>(Descriptor::kContext); 10671cb0ef41Sopenharmony_ci 10681cb0ef41Sopenharmony_ci Label call_runtime(this, Label::kDeferred), prototype_valid(this), 10691cb0ef41Sopenharmony_ci no_properties(this); 10701cb0ef41Sopenharmony_ci 10711cb0ef41Sopenharmony_ci { 10721cb0ef41Sopenharmony_ci Comment("Argument 1 check: prototype"); 10731cb0ef41Sopenharmony_ci GotoIf(IsNull(prototype), &prototype_valid); 10741cb0ef41Sopenharmony_ci BranchIfJSReceiver(prototype, &prototype_valid, &call_runtime); 10751cb0ef41Sopenharmony_ci } 10761cb0ef41Sopenharmony_ci 10771cb0ef41Sopenharmony_ci BIND(&prototype_valid); 10781cb0ef41Sopenharmony_ci { 10791cb0ef41Sopenharmony_ci Comment("Argument 2 check: properties"); 10801cb0ef41Sopenharmony_ci // Check that we have a simple object 10811cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(properties), &call_runtime); 10821cb0ef41Sopenharmony_ci // Undefined implies no properties. 10831cb0ef41Sopenharmony_ci GotoIf(IsUndefined(properties), &no_properties); 10841cb0ef41Sopenharmony_ci TNode<Map> properties_map = LoadMap(CAST(properties)); 10851cb0ef41Sopenharmony_ci GotoIf(IsSpecialReceiverMap(properties_map), &call_runtime); 10861cb0ef41Sopenharmony_ci // Stay on the fast path only if there are no elements. 10871cb0ef41Sopenharmony_ci GotoIfNot( 10881cb0ef41Sopenharmony_ci TaggedEqual(LoadElements(CAST(properties)), EmptyFixedArrayConstant()), 10891cb0ef41Sopenharmony_ci &call_runtime); 10901cb0ef41Sopenharmony_ci // Handle dictionary objects or fast objects with properties in runtime. 10911cb0ef41Sopenharmony_ci TNode<Uint32T> bit_field3 = LoadMapBitField3(properties_map); 10921cb0ef41Sopenharmony_ci GotoIf(IsSetWord32<Map::Bits3::IsDictionaryMapBit>(bit_field3), 10931cb0ef41Sopenharmony_ci &call_runtime); 10941cb0ef41Sopenharmony_ci Branch(IsSetWord32<Map::Bits3::NumberOfOwnDescriptorsBits>(bit_field3), 10951cb0ef41Sopenharmony_ci &call_runtime, &no_properties); 10961cb0ef41Sopenharmony_ci } 10971cb0ef41Sopenharmony_ci 10981cb0ef41Sopenharmony_ci // Create a new object with the given prototype. 10991cb0ef41Sopenharmony_ci BIND(&no_properties); 11001cb0ef41Sopenharmony_ci { 11011cb0ef41Sopenharmony_ci TVARIABLE(Map, map); 11021cb0ef41Sopenharmony_ci TVARIABLE(HeapObject, new_properties); 11031cb0ef41Sopenharmony_ci Label null_proto(this), non_null_proto(this), instantiate_map(this); 11041cb0ef41Sopenharmony_ci 11051cb0ef41Sopenharmony_ci Branch(IsNull(prototype), &null_proto, &non_null_proto); 11061cb0ef41Sopenharmony_ci 11071cb0ef41Sopenharmony_ci BIND(&null_proto); 11081cb0ef41Sopenharmony_ci { 11091cb0ef41Sopenharmony_ci map = LoadSlowObjectWithNullPrototypeMap(native_context); 11101cb0ef41Sopenharmony_ci if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { 11111cb0ef41Sopenharmony_ci new_properties = 11121cb0ef41Sopenharmony_ci AllocateSwissNameDictionary(SwissNameDictionary::kInitialCapacity); 11131cb0ef41Sopenharmony_ci } else { 11141cb0ef41Sopenharmony_ci new_properties = 11151cb0ef41Sopenharmony_ci AllocateNameDictionary(NameDictionary::kInitialCapacity); 11161cb0ef41Sopenharmony_ci } 11171cb0ef41Sopenharmony_ci Goto(&instantiate_map); 11181cb0ef41Sopenharmony_ci } 11191cb0ef41Sopenharmony_ci 11201cb0ef41Sopenharmony_ci BIND(&non_null_proto); 11211cb0ef41Sopenharmony_ci { 11221cb0ef41Sopenharmony_ci new_properties = EmptyFixedArrayConstant(); 11231cb0ef41Sopenharmony_ci map = LoadObjectFunctionInitialMap(native_context); 11241cb0ef41Sopenharmony_ci GotoIf(TaggedEqual(prototype, LoadMapPrototype(map.value())), 11251cb0ef41Sopenharmony_ci &instantiate_map); 11261cb0ef41Sopenharmony_ci // Try loading the prototype info. 11271cb0ef41Sopenharmony_ci TNode<PrototypeInfo> prototype_info = 11281cb0ef41Sopenharmony_ci LoadMapPrototypeInfo(LoadMap(CAST(prototype)), &call_runtime); 11291cb0ef41Sopenharmony_ci Comment("Load ObjectCreateMap from PrototypeInfo"); 11301cb0ef41Sopenharmony_ci TNode<MaybeObject> maybe_map = LoadMaybeWeakObjectField( 11311cb0ef41Sopenharmony_ci prototype_info, PrototypeInfo::kObjectCreateMapOffset); 11321cb0ef41Sopenharmony_ci GotoIf(TaggedEqual(maybe_map, UndefinedConstant()), &call_runtime); 11331cb0ef41Sopenharmony_ci map = CAST(GetHeapObjectAssumeWeak(maybe_map, &call_runtime)); 11341cb0ef41Sopenharmony_ci Goto(&instantiate_map); 11351cb0ef41Sopenharmony_ci } 11361cb0ef41Sopenharmony_ci 11371cb0ef41Sopenharmony_ci BIND(&instantiate_map); 11381cb0ef41Sopenharmony_ci { 11391cb0ef41Sopenharmony_ci TNode<JSObject> instance = 11401cb0ef41Sopenharmony_ci AllocateJSObjectFromMap(map.value(), new_properties.value()); 11411cb0ef41Sopenharmony_ci args.PopAndReturn(instance); 11421cb0ef41Sopenharmony_ci } 11431cb0ef41Sopenharmony_ci } 11441cb0ef41Sopenharmony_ci 11451cb0ef41Sopenharmony_ci BIND(&call_runtime); 11461cb0ef41Sopenharmony_ci { 11471cb0ef41Sopenharmony_ci TNode<Object> result = CallRuntime(Runtime::kObjectCreate, native_context, 11481cb0ef41Sopenharmony_ci prototype, properties); 11491cb0ef41Sopenharmony_ci args.PopAndReturn(result); 11501cb0ef41Sopenharmony_ci } 11511cb0ef41Sopenharmony_ci} 11521cb0ef41Sopenharmony_ci 11531cb0ef41Sopenharmony_ci// ES #sec-object.is 11541cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectIs, ObjectBuiltinsAssembler) { 11551cb0ef41Sopenharmony_ci const auto left = Parameter<Object>(Descriptor::kLeft); 11561cb0ef41Sopenharmony_ci const auto right = Parameter<Object>(Descriptor::kRight); 11571cb0ef41Sopenharmony_ci 11581cb0ef41Sopenharmony_ci Label return_true(this), return_false(this); 11591cb0ef41Sopenharmony_ci BranchIfSameValue(left, right, &return_true, &return_false); 11601cb0ef41Sopenharmony_ci 11611cb0ef41Sopenharmony_ci BIND(&return_true); 11621cb0ef41Sopenharmony_ci Return(TrueConstant()); 11631cb0ef41Sopenharmony_ci 11641cb0ef41Sopenharmony_ci BIND(&return_false); 11651cb0ef41Sopenharmony_ci Return(FalseConstant()); 11661cb0ef41Sopenharmony_ci} 11671cb0ef41Sopenharmony_ci 11681cb0ef41Sopenharmony_ciTF_BUILTIN(CreateIterResultObject, ObjectBuiltinsAssembler) { 11691cb0ef41Sopenharmony_ci const auto value = Parameter<Object>(Descriptor::kValue); 11701cb0ef41Sopenharmony_ci const auto done = Parameter<Oddball>(Descriptor::kDone); 11711cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 11721cb0ef41Sopenharmony_ci 11731cb0ef41Sopenharmony_ci const TNode<NativeContext> native_context = LoadNativeContext(context); 11741cb0ef41Sopenharmony_ci const TNode<Map> map = CAST( 11751cb0ef41Sopenharmony_ci LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX)); 11761cb0ef41Sopenharmony_ci 11771cb0ef41Sopenharmony_ci const TNode<JSObject> result = AllocateJSObjectFromMap(map); 11781cb0ef41Sopenharmony_ci 11791cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset, value); 11801cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset, done); 11811cb0ef41Sopenharmony_ci 11821cb0ef41Sopenharmony_ci Return(result); 11831cb0ef41Sopenharmony_ci} 11841cb0ef41Sopenharmony_ci 11851cb0ef41Sopenharmony_ciTF_BUILTIN(HasProperty, ObjectBuiltinsAssembler) { 11861cb0ef41Sopenharmony_ci auto key = Parameter<Object>(Descriptor::kKey); 11871cb0ef41Sopenharmony_ci auto object = Parameter<Object>(Descriptor::kObject); 11881cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 11891cb0ef41Sopenharmony_ci 11901cb0ef41Sopenharmony_ci Return(HasProperty(context, object, key, kHasProperty)); 11911cb0ef41Sopenharmony_ci} 11921cb0ef41Sopenharmony_ci 11931cb0ef41Sopenharmony_ciTF_BUILTIN(InstanceOf, ObjectBuiltinsAssembler) { 11941cb0ef41Sopenharmony_ci auto object = Parameter<Object>(Descriptor::kLeft); 11951cb0ef41Sopenharmony_ci auto callable = Parameter<Object>(Descriptor::kRight); 11961cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 11971cb0ef41Sopenharmony_ci 11981cb0ef41Sopenharmony_ci Return(InstanceOf(object, callable, context)); 11991cb0ef41Sopenharmony_ci} 12001cb0ef41Sopenharmony_ci 12011cb0ef41Sopenharmony_ciTF_BUILTIN(InstanceOf_WithFeedback, ObjectBuiltinsAssembler) { 12021cb0ef41Sopenharmony_ci auto object = Parameter<Object>(Descriptor::kLeft); 12031cb0ef41Sopenharmony_ci auto callable = Parameter<Object>(Descriptor::kRight); 12041cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 12051cb0ef41Sopenharmony_ci auto feedback_vector = Parameter<HeapObject>(Descriptor::kFeedbackVector); 12061cb0ef41Sopenharmony_ci auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); 12071cb0ef41Sopenharmony_ci 12081cb0ef41Sopenharmony_ci CollectInstanceOfFeedback(callable, context, feedback_vector, slot); 12091cb0ef41Sopenharmony_ci Return(InstanceOf(object, callable, context)); 12101cb0ef41Sopenharmony_ci} 12111cb0ef41Sopenharmony_ci 12121cb0ef41Sopenharmony_ciTF_BUILTIN(InstanceOf_Baseline, ObjectBuiltinsAssembler) { 12131cb0ef41Sopenharmony_ci auto object = Parameter<Object>(Descriptor::kLeft); 12141cb0ef41Sopenharmony_ci auto callable = Parameter<Object>(Descriptor::kRight); 12151cb0ef41Sopenharmony_ci auto context = LoadContextFromBaseline(); 12161cb0ef41Sopenharmony_ci auto feedback_vector = LoadFeedbackVectorFromBaseline(); 12171cb0ef41Sopenharmony_ci auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); 12181cb0ef41Sopenharmony_ci 12191cb0ef41Sopenharmony_ci CollectInstanceOfFeedback(callable, context, feedback_vector, slot); 12201cb0ef41Sopenharmony_ci Return(InstanceOf(object, callable, context)); 12211cb0ef41Sopenharmony_ci} 12221cb0ef41Sopenharmony_ci 12231cb0ef41Sopenharmony_ci// ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) 12241cb0ef41Sopenharmony_ciTF_BUILTIN(OrdinaryHasInstance, ObjectBuiltinsAssembler) { 12251cb0ef41Sopenharmony_ci auto constructor = Parameter<Object>(Descriptor::kLeft); 12261cb0ef41Sopenharmony_ci auto object = Parameter<Object>(Descriptor::kRight); 12271cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 12281cb0ef41Sopenharmony_ci 12291cb0ef41Sopenharmony_ci Return(OrdinaryHasInstance(context, constructor, object)); 12301cb0ef41Sopenharmony_ci} 12311cb0ef41Sopenharmony_ci 12321cb0ef41Sopenharmony_ciTF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) { 12331cb0ef41Sopenharmony_ci auto closure = Parameter<JSFunction>(Descriptor::kClosure); 12341cb0ef41Sopenharmony_ci auto receiver = Parameter<Object>(Descriptor::kReceiver); 12351cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 12361cb0ef41Sopenharmony_ci 12371cb0ef41Sopenharmony_ci // Get the initial map from the function, jumping to the runtime if we don't 12381cb0ef41Sopenharmony_ci // have one. 12391cb0ef41Sopenharmony_ci Label done(this), runtime(this); 12401cb0ef41Sopenharmony_ci GotoIfNot(IsFunctionWithPrototypeSlotMap(LoadMap(closure)), &runtime); 12411cb0ef41Sopenharmony_ci TNode<HeapObject> maybe_map = LoadObjectField<HeapObject>( 12421cb0ef41Sopenharmony_ci closure, JSFunction::kPrototypeOrInitialMapOffset); 12431cb0ef41Sopenharmony_ci GotoIf(DoesntHaveInstanceType(maybe_map, MAP_TYPE), &runtime); 12441cb0ef41Sopenharmony_ci TNode<Map> map = CAST(maybe_map); 12451cb0ef41Sopenharmony_ci 12461cb0ef41Sopenharmony_ci TNode<SharedFunctionInfo> shared = LoadObjectField<SharedFunctionInfo>( 12471cb0ef41Sopenharmony_ci closure, JSFunction::kSharedFunctionInfoOffset); 12481cb0ef41Sopenharmony_ci TNode<BytecodeArray> bytecode_array = 12491cb0ef41Sopenharmony_ci LoadSharedFunctionInfoBytecodeArray(shared); 12501cb0ef41Sopenharmony_ci 12511cb0ef41Sopenharmony_ci TNode<IntPtrT> formal_parameter_count = ChangeInt32ToIntPtr( 12521cb0ef41Sopenharmony_ci LoadSharedFunctionInfoFormalParameterCountWithoutReceiver(shared)); 12531cb0ef41Sopenharmony_ci TNode<IntPtrT> frame_size = ChangeInt32ToIntPtr( 12541cb0ef41Sopenharmony_ci LoadObjectField<Int32T>(bytecode_array, BytecodeArray::kFrameSizeOffset)); 12551cb0ef41Sopenharmony_ci TNode<IntPtrT> size = 12561cb0ef41Sopenharmony_ci IntPtrAdd(WordSar(frame_size, IntPtrConstant(kTaggedSizeLog2)), 12571cb0ef41Sopenharmony_ci formal_parameter_count); 12581cb0ef41Sopenharmony_ci TNode<FixedArrayBase> parameters_and_registers = AllocateFixedArray( 12591cb0ef41Sopenharmony_ci HOLEY_ELEMENTS, size, AllocationFlag::kAllowLargeObjectAllocation); 12601cb0ef41Sopenharmony_ci FillFixedArrayWithValue(HOLEY_ELEMENTS, parameters_and_registers, 12611cb0ef41Sopenharmony_ci IntPtrConstant(0), size, RootIndex::kUndefinedValue); 12621cb0ef41Sopenharmony_ci // TODO(cbruni): support start_offset to avoid double initialization. 12631cb0ef41Sopenharmony_ci TNode<JSObject> result = 12641cb0ef41Sopenharmony_ci AllocateJSObjectFromMap(map, base::nullopt, base::nullopt, 12651cb0ef41Sopenharmony_ci AllocationFlag::kNone, kWithSlackTracking); 12661cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kFunctionOffset, 12671cb0ef41Sopenharmony_ci closure); 12681cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContextOffset, 12691cb0ef41Sopenharmony_ci context); 12701cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kReceiverOffset, 12711cb0ef41Sopenharmony_ci receiver); 12721cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 12731cb0ef41Sopenharmony_ci result, JSGeneratorObject::kParametersAndRegistersOffset, 12741cb0ef41Sopenharmony_ci parameters_and_registers); 12751cb0ef41Sopenharmony_ci TNode<Smi> resume_mode = SmiConstant(JSGeneratorObject::ResumeMode::kNext); 12761cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kResumeModeOffset, 12771cb0ef41Sopenharmony_ci resume_mode); 12781cb0ef41Sopenharmony_ci TNode<Smi> executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting); 12791cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContinuationOffset, 12801cb0ef41Sopenharmony_ci executing); 12811cb0ef41Sopenharmony_ci GotoIfNot(InstanceTypeEqual(LoadMapInstanceType(map), 12821cb0ef41Sopenharmony_ci JS_ASYNC_GENERATOR_OBJECT_TYPE), 12831cb0ef41Sopenharmony_ci &done); 12841cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 12851cb0ef41Sopenharmony_ci result, JSAsyncGeneratorObject::kIsAwaitingOffset, SmiConstant(0)); 12861cb0ef41Sopenharmony_ci Goto(&done); 12871cb0ef41Sopenharmony_ci 12881cb0ef41Sopenharmony_ci BIND(&done); 12891cb0ef41Sopenharmony_ci { Return(result); } 12901cb0ef41Sopenharmony_ci 12911cb0ef41Sopenharmony_ci BIND(&runtime); 12921cb0ef41Sopenharmony_ci { 12931cb0ef41Sopenharmony_ci Return(CallRuntime(Runtime::kCreateJSGeneratorObject, context, closure, 12941cb0ef41Sopenharmony_ci receiver)); 12951cb0ef41Sopenharmony_ci } 12961cb0ef41Sopenharmony_ci} 12971cb0ef41Sopenharmony_ci 12981cb0ef41Sopenharmony_ci// ES6 section 19.1.2.7 Object.getOwnPropertyDescriptor ( O, P ) 12991cb0ef41Sopenharmony_ciTF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) { 13001cb0ef41Sopenharmony_ci auto argc = UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount); 13011cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 13021cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsUndefined(Parameter<Object>(Descriptor::kJSNewTarget))); 13031cb0ef41Sopenharmony_ci 13041cb0ef41Sopenharmony_ci CodeStubArguments args(this, argc); 13051cb0ef41Sopenharmony_ci TNode<Object> object_input = args.GetOptionalArgumentValue(0); 13061cb0ef41Sopenharmony_ci TNode<Object> key = args.GetOptionalArgumentValue(1); 13071cb0ef41Sopenharmony_ci 13081cb0ef41Sopenharmony_ci // 1. Let obj be ? ToObject(O). 13091cb0ef41Sopenharmony_ci TNode<JSReceiver> object = ToObject_Inline(context, object_input); 13101cb0ef41Sopenharmony_ci 13111cb0ef41Sopenharmony_ci // 2. Let key be ? ToPropertyKey(P). 13121cb0ef41Sopenharmony_ci key = CallBuiltin(Builtin::kToName, context, key); 13131cb0ef41Sopenharmony_ci 13141cb0ef41Sopenharmony_ci // 3. Let desc be ? obj.[[GetOwnProperty]](key). 13151cb0ef41Sopenharmony_ci Label if_keyisindex(this), if_iskeyunique(this), 13161cb0ef41Sopenharmony_ci call_runtime(this, Label::kDeferred), 13171cb0ef41Sopenharmony_ci return_undefined(this, Label::kDeferred), if_notunique_name(this); 13181cb0ef41Sopenharmony_ci 13191cb0ef41Sopenharmony_ci TNode<Map> map = LoadMap(object); 13201cb0ef41Sopenharmony_ci TNode<Uint16T> instance_type = LoadMapInstanceType(map); 13211cb0ef41Sopenharmony_ci GotoIf(IsSpecialReceiverInstanceType(instance_type), &call_runtime); 13221cb0ef41Sopenharmony_ci { 13231cb0ef41Sopenharmony_ci TVARIABLE(IntPtrT, var_index, IntPtrConstant(0)); 13241cb0ef41Sopenharmony_ci TVARIABLE(Name, var_name); 13251cb0ef41Sopenharmony_ci 13261cb0ef41Sopenharmony_ci TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, &var_name, 13271cb0ef41Sopenharmony_ci &call_runtime, &if_notunique_name); 13281cb0ef41Sopenharmony_ci 13291cb0ef41Sopenharmony_ci BIND(&if_notunique_name); 13301cb0ef41Sopenharmony_ci { 13311cb0ef41Sopenharmony_ci Label not_in_string_table(this); 13321cb0ef41Sopenharmony_ci TryInternalizeString(CAST(key), &if_keyisindex, &var_index, 13331cb0ef41Sopenharmony_ci &if_iskeyunique, &var_name, ¬_in_string_table, 13341cb0ef41Sopenharmony_ci &call_runtime); 13351cb0ef41Sopenharmony_ci 13361cb0ef41Sopenharmony_ci BIND(¬_in_string_table); 13371cb0ef41Sopenharmony_ci { 13381cb0ef41Sopenharmony_ci // If the string was not found in the string table, then no regular 13391cb0ef41Sopenharmony_ci // object can have a property with that name, so return |undefined|. 13401cb0ef41Sopenharmony_ci Goto(&return_undefined); 13411cb0ef41Sopenharmony_ci } 13421cb0ef41Sopenharmony_ci } 13431cb0ef41Sopenharmony_ci 13441cb0ef41Sopenharmony_ci BIND(&if_iskeyunique); 13451cb0ef41Sopenharmony_ci { 13461cb0ef41Sopenharmony_ci Label if_found_value(this), return_empty(this), if_not_found(this); 13471cb0ef41Sopenharmony_ci 13481cb0ef41Sopenharmony_ci TVARIABLE(Object, var_value); 13491cb0ef41Sopenharmony_ci TVARIABLE(Uint32T, var_details); 13501cb0ef41Sopenharmony_ci TVARIABLE(Object, var_raw_value); 13511cb0ef41Sopenharmony_ci 13521cb0ef41Sopenharmony_ci TryGetOwnProperty(context, object, object, map, instance_type, 13531cb0ef41Sopenharmony_ci var_name.value(), &if_found_value, &var_value, 13541cb0ef41Sopenharmony_ci &var_details, &var_raw_value, &return_empty, 13551cb0ef41Sopenharmony_ci &if_not_found, kReturnAccessorPair); 13561cb0ef41Sopenharmony_ci 13571cb0ef41Sopenharmony_ci BIND(&if_found_value); 13581cb0ef41Sopenharmony_ci // 4. Return FromPropertyDetails(desc). 13591cb0ef41Sopenharmony_ci TNode<JSObject> js_desc = FromPropertyDetails( 13601cb0ef41Sopenharmony_ci context, var_value.value(), var_details.value(), &call_runtime); 13611cb0ef41Sopenharmony_ci args.PopAndReturn(js_desc); 13621cb0ef41Sopenharmony_ci 13631cb0ef41Sopenharmony_ci BIND(&return_empty); 13641cb0ef41Sopenharmony_ci var_value = UndefinedConstant(); 13651cb0ef41Sopenharmony_ci args.PopAndReturn(UndefinedConstant()); 13661cb0ef41Sopenharmony_ci 13671cb0ef41Sopenharmony_ci BIND(&if_not_found); 13681cb0ef41Sopenharmony_ci Goto(&call_runtime); 13691cb0ef41Sopenharmony_ci } 13701cb0ef41Sopenharmony_ci } 13711cb0ef41Sopenharmony_ci 13721cb0ef41Sopenharmony_ci BIND(&if_keyisindex); 13731cb0ef41Sopenharmony_ci Goto(&call_runtime); 13741cb0ef41Sopenharmony_ci 13751cb0ef41Sopenharmony_ci BIND(&call_runtime); 13761cb0ef41Sopenharmony_ci { 13771cb0ef41Sopenharmony_ci TNode<Object> desc = 13781cb0ef41Sopenharmony_ci CallRuntime(Runtime::kGetOwnPropertyDescriptor, context, object, key); 13791cb0ef41Sopenharmony_ci 13801cb0ef41Sopenharmony_ci GotoIf(IsUndefined(desc), &return_undefined); 13811cb0ef41Sopenharmony_ci 13821cb0ef41Sopenharmony_ci TNode<PropertyDescriptorObject> desc_object = CAST(desc); 13831cb0ef41Sopenharmony_ci 13841cb0ef41Sopenharmony_ci // 4. Return FromPropertyDescriptor(desc). 13851cb0ef41Sopenharmony_ci TNode<JSObject> js_desc = FromPropertyDescriptor(context, desc_object); 13861cb0ef41Sopenharmony_ci args.PopAndReturn(js_desc); 13871cb0ef41Sopenharmony_ci } 13881cb0ef41Sopenharmony_ci BIND(&return_undefined); 13891cb0ef41Sopenharmony_ci args.PopAndReturn(UndefinedConstant()); 13901cb0ef41Sopenharmony_ci} 13911cb0ef41Sopenharmony_ci 13921cb0ef41Sopenharmony_ci// TODO(v8:11167) remove remove |context| and |object| parameters once 13931cb0ef41Sopenharmony_ci// OrderedNameDictionary supported. 13941cb0ef41Sopenharmony_civoid ObjectBuiltinsAssembler::AddToDictionaryIf( 13951cb0ef41Sopenharmony_ci TNode<BoolT> condition, TNode<Context> context, TNode<Object> object, 13961cb0ef41Sopenharmony_ci TNode<HeapObject> name_dictionary, Handle<Name> name, TNode<Object> value, 13971cb0ef41Sopenharmony_ci Label* bailout) { 13981cb0ef41Sopenharmony_ci Label done(this); 13991cb0ef41Sopenharmony_ci GotoIfNot(condition, &done); 14001cb0ef41Sopenharmony_ci 14011cb0ef41Sopenharmony_ci Add<PropertyDictionary>(CAST(name_dictionary), HeapConstant(name), value, 14021cb0ef41Sopenharmony_ci bailout); 14031cb0ef41Sopenharmony_ci Goto(&done); 14041cb0ef41Sopenharmony_ci 14051cb0ef41Sopenharmony_ci BIND(&done); 14061cb0ef41Sopenharmony_ci} 14071cb0ef41Sopenharmony_ci 14081cb0ef41Sopenharmony_ciTNode<JSObject> ObjectBuiltinsAssembler::FromPropertyDescriptor( 14091cb0ef41Sopenharmony_ci TNode<Context> context, TNode<PropertyDescriptorObject> desc) { 14101cb0ef41Sopenharmony_ci TVARIABLE(JSObject, js_descriptor); 14111cb0ef41Sopenharmony_ci 14121cb0ef41Sopenharmony_ci TNode<Int32T> flags = LoadAndUntagToWord32ObjectField( 14131cb0ef41Sopenharmony_ci desc, PropertyDescriptorObject::kFlagsOffset); 14141cb0ef41Sopenharmony_ci 14151cb0ef41Sopenharmony_ci TNode<Int32T> has_flags = 14161cb0ef41Sopenharmony_ci Word32And(flags, Int32Constant(PropertyDescriptorObject::kHasMask)); 14171cb0ef41Sopenharmony_ci 14181cb0ef41Sopenharmony_ci Label if_accessor_desc(this), if_data_desc(this), if_generic_desc(this), 14191cb0ef41Sopenharmony_ci return_desc(this); 14201cb0ef41Sopenharmony_ci GotoIf( 14211cb0ef41Sopenharmony_ci Word32Equal(has_flags, 14221cb0ef41Sopenharmony_ci Int32Constant( 14231cb0ef41Sopenharmony_ci PropertyDescriptorObject::kRegularAccessorPropertyBits)), 14241cb0ef41Sopenharmony_ci &if_accessor_desc); 14251cb0ef41Sopenharmony_ci GotoIf(Word32Equal( 14261cb0ef41Sopenharmony_ci has_flags, 14271cb0ef41Sopenharmony_ci Int32Constant(PropertyDescriptorObject::kRegularDataPropertyBits)), 14281cb0ef41Sopenharmony_ci &if_data_desc); 14291cb0ef41Sopenharmony_ci Goto(&if_generic_desc); 14301cb0ef41Sopenharmony_ci 14311cb0ef41Sopenharmony_ci BIND(&if_accessor_desc); 14321cb0ef41Sopenharmony_ci { 14331cb0ef41Sopenharmony_ci js_descriptor = ConstructAccessorDescriptor( 14341cb0ef41Sopenharmony_ci context, LoadObjectField(desc, PropertyDescriptorObject::kGetOffset), 14351cb0ef41Sopenharmony_ci LoadObjectField(desc, PropertyDescriptorObject::kSetOffset), 14361cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags), 14371cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)); 14381cb0ef41Sopenharmony_ci Goto(&return_desc); 14391cb0ef41Sopenharmony_ci } 14401cb0ef41Sopenharmony_ci 14411cb0ef41Sopenharmony_ci BIND(&if_data_desc); 14421cb0ef41Sopenharmony_ci { 14431cb0ef41Sopenharmony_ci js_descriptor = ConstructDataDescriptor( 14441cb0ef41Sopenharmony_ci context, LoadObjectField(desc, PropertyDescriptorObject::kValueOffset), 14451cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::IsWritableBit>(flags), 14461cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags), 14471cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)); 14481cb0ef41Sopenharmony_ci Goto(&return_desc); 14491cb0ef41Sopenharmony_ci } 14501cb0ef41Sopenharmony_ci 14511cb0ef41Sopenharmony_ci BIND(&if_generic_desc); 14521cb0ef41Sopenharmony_ci { 14531cb0ef41Sopenharmony_ci TNode<NativeContext> native_context = LoadNativeContext(context); 14541cb0ef41Sopenharmony_ci TNode<Map> map = CAST(LoadContextElement( 14551cb0ef41Sopenharmony_ci native_context, Context::SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP)); 14561cb0ef41Sopenharmony_ci // We want to preallocate the slots for value, writable, get, set, 14571cb0ef41Sopenharmony_ci // enumerable and configurable - a total of 6 14581cb0ef41Sopenharmony_ci TNode<HeapObject> properties = 14591cb0ef41Sopenharmony_ci V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL 14601cb0ef41Sopenharmony_ci ? TNode<HeapObject>(AllocateSwissNameDictionary(6)) 14611cb0ef41Sopenharmony_ci : AllocateNameDictionary(6); 14621cb0ef41Sopenharmony_ci TNode<JSObject> js_desc = AllocateJSObjectFromMap(map, properties); 14631cb0ef41Sopenharmony_ci 14641cb0ef41Sopenharmony_ci Label bailout(this, Label::kDeferred); 14651cb0ef41Sopenharmony_ci 14661cb0ef41Sopenharmony_ci Factory* factory = isolate()->factory(); 14671cb0ef41Sopenharmony_ci TNode<Object> value = 14681cb0ef41Sopenharmony_ci LoadObjectField(desc, PropertyDescriptorObject::kValueOffset); 14691cb0ef41Sopenharmony_ci AddToDictionaryIf(IsNotTheHole(value), context, js_desc, properties, 14701cb0ef41Sopenharmony_ci factory->value_string(), value, &bailout); 14711cb0ef41Sopenharmony_ci AddToDictionaryIf( 14721cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::HasWritableBit>(flags), context, 14731cb0ef41Sopenharmony_ci js_desc, properties, factory->writable_string(), 14741cb0ef41Sopenharmony_ci SelectBooleanConstant( 14751cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::IsWritableBit>(flags)), 14761cb0ef41Sopenharmony_ci &bailout); 14771cb0ef41Sopenharmony_ci 14781cb0ef41Sopenharmony_ci TNode<Object> get = 14791cb0ef41Sopenharmony_ci LoadObjectField(desc, PropertyDescriptorObject::kGetOffset); 14801cb0ef41Sopenharmony_ci AddToDictionaryIf(IsNotTheHole(get), context, js_desc, properties, 14811cb0ef41Sopenharmony_ci factory->get_string(), get, &bailout); 14821cb0ef41Sopenharmony_ci TNode<Object> set = 14831cb0ef41Sopenharmony_ci LoadObjectField(desc, PropertyDescriptorObject::kSetOffset); 14841cb0ef41Sopenharmony_ci AddToDictionaryIf(IsNotTheHole(set), context, js_desc, properties, 14851cb0ef41Sopenharmony_ci factory->set_string(), set, &bailout); 14861cb0ef41Sopenharmony_ci 14871cb0ef41Sopenharmony_ci AddToDictionaryIf( 14881cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::HasEnumerableBit>(flags), context, 14891cb0ef41Sopenharmony_ci js_desc, properties, factory->enumerable_string(), 14901cb0ef41Sopenharmony_ci SelectBooleanConstant( 14911cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags)), 14921cb0ef41Sopenharmony_ci &bailout); 14931cb0ef41Sopenharmony_ci AddToDictionaryIf( 14941cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::HasConfigurableBit>(flags), 14951cb0ef41Sopenharmony_ci context, js_desc, properties, factory->configurable_string(), 14961cb0ef41Sopenharmony_ci SelectBooleanConstant( 14971cb0ef41Sopenharmony_ci IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)), 14981cb0ef41Sopenharmony_ci &bailout); 14991cb0ef41Sopenharmony_ci 15001cb0ef41Sopenharmony_ci js_descriptor = js_desc; 15011cb0ef41Sopenharmony_ci Goto(&return_desc); 15021cb0ef41Sopenharmony_ci 15031cb0ef41Sopenharmony_ci BIND(&bailout); 15041cb0ef41Sopenharmony_ci CSA_DCHECK(this, Int32Constant(0)); 15051cb0ef41Sopenharmony_ci Unreachable(); 15061cb0ef41Sopenharmony_ci } 15071cb0ef41Sopenharmony_ci 15081cb0ef41Sopenharmony_ci BIND(&return_desc); 15091cb0ef41Sopenharmony_ci return js_descriptor.value(); 15101cb0ef41Sopenharmony_ci} 15111cb0ef41Sopenharmony_ci 15121cb0ef41Sopenharmony_ciTNode<JSObject> ObjectBuiltinsAssembler::FromPropertyDetails( 15131cb0ef41Sopenharmony_ci TNode<Context> context, TNode<Object> raw_value, TNode<Word32T> details, 15141cb0ef41Sopenharmony_ci Label* if_bailout) { 15151cb0ef41Sopenharmony_ci TVARIABLE(JSObject, js_descriptor); 15161cb0ef41Sopenharmony_ci 15171cb0ef41Sopenharmony_ci Label if_accessor_desc(this), if_data_desc(this), return_desc(this); 15181cb0ef41Sopenharmony_ci BranchIfAccessorPair(raw_value, &if_accessor_desc, &if_data_desc); 15191cb0ef41Sopenharmony_ci 15201cb0ef41Sopenharmony_ci BIND(&if_accessor_desc); 15211cb0ef41Sopenharmony_ci { 15221cb0ef41Sopenharmony_ci TNode<AccessorPair> accessor_pair_value = CAST(raw_value); 15231cb0ef41Sopenharmony_ci TNode<HeapObject> getter = LoadObjectField<HeapObject>( 15241cb0ef41Sopenharmony_ci accessor_pair_value, AccessorPair::kGetterOffset); 15251cb0ef41Sopenharmony_ci TNode<HeapObject> setter = LoadObjectField<HeapObject>( 15261cb0ef41Sopenharmony_ci accessor_pair_value, AccessorPair::kSetterOffset); 15271cb0ef41Sopenharmony_ci js_descriptor = ConstructAccessorDescriptor( 15281cb0ef41Sopenharmony_ci context, GetAccessorOrUndefined(getter, if_bailout), 15291cb0ef41Sopenharmony_ci GetAccessorOrUndefined(setter, if_bailout), 15301cb0ef41Sopenharmony_ci IsNotSetWord32(details, PropertyDetails::kAttributesDontEnumMask), 15311cb0ef41Sopenharmony_ci IsNotSetWord32(details, PropertyDetails::kAttributesDontDeleteMask)); 15321cb0ef41Sopenharmony_ci Goto(&return_desc); 15331cb0ef41Sopenharmony_ci } 15341cb0ef41Sopenharmony_ci 15351cb0ef41Sopenharmony_ci BIND(&if_data_desc); 15361cb0ef41Sopenharmony_ci { 15371cb0ef41Sopenharmony_ci js_descriptor = ConstructDataDescriptor( 15381cb0ef41Sopenharmony_ci context, raw_value, 15391cb0ef41Sopenharmony_ci IsNotSetWord32(details, PropertyDetails::kAttributesReadOnlyMask), 15401cb0ef41Sopenharmony_ci IsNotSetWord32(details, PropertyDetails::kAttributesDontEnumMask), 15411cb0ef41Sopenharmony_ci IsNotSetWord32(details, PropertyDetails::kAttributesDontDeleteMask)); 15421cb0ef41Sopenharmony_ci Goto(&return_desc); 15431cb0ef41Sopenharmony_ci } 15441cb0ef41Sopenharmony_ci 15451cb0ef41Sopenharmony_ci BIND(&return_desc); 15461cb0ef41Sopenharmony_ci return js_descriptor.value(); 15471cb0ef41Sopenharmony_ci} 15481cb0ef41Sopenharmony_ci 15491cb0ef41Sopenharmony_ciTNode<HeapObject> ObjectBuiltinsAssembler::GetAccessorOrUndefined( 15501cb0ef41Sopenharmony_ci TNode<HeapObject> accessor, Label* if_bailout) { 15511cb0ef41Sopenharmony_ci Label bind_undefined(this, Label::kDeferred), return_result(this); 15521cb0ef41Sopenharmony_ci TVARIABLE(HeapObject, result); 15531cb0ef41Sopenharmony_ci 15541cb0ef41Sopenharmony_ci GotoIf(IsNull(accessor), &bind_undefined); 15551cb0ef41Sopenharmony_ci result = accessor; 15561cb0ef41Sopenharmony_ci TNode<Map> map = LoadMap(accessor); 15571cb0ef41Sopenharmony_ci // TODO(ishell): probe template instantiations cache. 15581cb0ef41Sopenharmony_ci GotoIf(IsFunctionTemplateInfoMap(map), if_bailout); 15591cb0ef41Sopenharmony_ci Goto(&return_result); 15601cb0ef41Sopenharmony_ci 15611cb0ef41Sopenharmony_ci BIND(&bind_undefined); 15621cb0ef41Sopenharmony_ci result = UndefinedConstant(); 15631cb0ef41Sopenharmony_ci Goto(&return_result); 15641cb0ef41Sopenharmony_ci 15651cb0ef41Sopenharmony_ci BIND(&return_result); 15661cb0ef41Sopenharmony_ci return result.value(); 15671cb0ef41Sopenharmony_ci} 15681cb0ef41Sopenharmony_ci} // namespace internal 15691cb0ef41Sopenharmony_ci} // namespace v8 1570