14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_JSOBJECT_INL_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_JSOBJECT_INL_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/js_object.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ci#include "ecmascript/element_accessor-inl.h" 224514f5e3Sopenharmony_ci#include "ecmascript/js_array.h" 234514f5e3Sopenharmony_ci#include "ecmascript/js_hclass-inl.h" 244514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value-inl.h" 254514f5e3Sopenharmony_ci#include "ecmascript/js_typed_array.h" 264514f5e3Sopenharmony_ci#include "ecmascript/object_operator.h" 274514f5e3Sopenharmony_ci#include "ecmascript/tagged_array-inl.h" 284514f5e3Sopenharmony_ci#include "ecmascript/tagged_queue.h" 294514f5e3Sopenharmony_ci#include "ecmascript/tagged_dictionary.h" 304514f5e3Sopenharmony_ci 314514f5e3Sopenharmony_cinamespace panda::ecmascript { 324514f5e3Sopenharmony_ciinline void ECMAObject::SetCallable(bool flag) 334514f5e3Sopenharmony_ci{ 344514f5e3Sopenharmony_ci GetClass()->SetCallable(flag); 354514f5e3Sopenharmony_ci} 364514f5e3Sopenharmony_ci 374514f5e3Sopenharmony_ciinline bool ECMAObject::IsCallable() const 384514f5e3Sopenharmony_ci{ 394514f5e3Sopenharmony_ci return GetClass()->IsCallable(); 404514f5e3Sopenharmony_ci} 414514f5e3Sopenharmony_ci 424514f5e3Sopenharmony_ci// JSObject 434514f5e3Sopenharmony_ciinline bool JSObject::IsExtensible() const 444514f5e3Sopenharmony_ci{ 454514f5e3Sopenharmony_ci return GetJSHClass()->IsExtensible(); 464514f5e3Sopenharmony_ci} 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ciinline void JSObject::FillElementsWithHoles(const JSThread *thread, uint32_t start, uint32_t end) 494514f5e3Sopenharmony_ci{ 504514f5e3Sopenharmony_ci if (start >= end) { 514514f5e3Sopenharmony_ci return; 524514f5e3Sopenharmony_ci } 534514f5e3Sopenharmony_ci 544514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> holeHandle(thread, JSTaggedValue::Hole()); 554514f5e3Sopenharmony_ci JSHandle<JSObject> thisObj(thread, this); 564514f5e3Sopenharmony_ci for (uint32_t i = start; i < end; i++) { 574514f5e3Sopenharmony_ci ElementAccessor::Set(thread, thisObj, i, holeHandle, false); 584514f5e3Sopenharmony_ci } 594514f5e3Sopenharmony_ci} 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ciinline uint32_t JSObject::GetNonInlinedFastPropsCapacity() const 624514f5e3Sopenharmony_ci{ 634514f5e3Sopenharmony_ci uint32_t inlineProps = GetJSHClass()->GetInlinedProperties(); 644514f5e3Sopenharmony_ci return PropertyAttributes::MAX_FAST_PROPS_CAPACITY - inlineProps; 654514f5e3Sopenharmony_ci} 664514f5e3Sopenharmony_ci 674514f5e3Sopenharmony_ciinline bool JSObject::IsJSGlobalObject() const 684514f5e3Sopenharmony_ci{ 694514f5e3Sopenharmony_ci return GetJSHClass()->IsJSGlobalObject(); 704514f5e3Sopenharmony_ci} 714514f5e3Sopenharmony_ci 724514f5e3Sopenharmony_ciinline bool JSObject::IsConstructor() const 734514f5e3Sopenharmony_ci{ 744514f5e3Sopenharmony_ci return GetJSHClass()->IsConstructor(); 754514f5e3Sopenharmony_ci} 764514f5e3Sopenharmony_ci 774514f5e3Sopenharmony_ciinline bool JSObject::IsECMAObject() const 784514f5e3Sopenharmony_ci{ 794514f5e3Sopenharmony_ci return GetJSHClass()->IsECMAObject(); 804514f5e3Sopenharmony_ci} 814514f5e3Sopenharmony_ci 824514f5e3Sopenharmony_ciinline bool JSObject::IsJSError() const 834514f5e3Sopenharmony_ci{ 844514f5e3Sopenharmony_ci return GetJSHClass()->IsJSError(); 854514f5e3Sopenharmony_ci} 864514f5e3Sopenharmony_ci 874514f5e3Sopenharmony_ciinline bool JSObject::IsArguments() const 884514f5e3Sopenharmony_ci{ 894514f5e3Sopenharmony_ci return GetJSHClass()->IsArguments(); 904514f5e3Sopenharmony_ci} 914514f5e3Sopenharmony_ci 924514f5e3Sopenharmony_ciinline bool JSObject::IsDate() const 934514f5e3Sopenharmony_ci{ 944514f5e3Sopenharmony_ci return GetJSHClass()->IsDate(); 954514f5e3Sopenharmony_ci} 964514f5e3Sopenharmony_ci 974514f5e3Sopenharmony_ciinline bool JSObject::IsJSArray() const 984514f5e3Sopenharmony_ci{ 994514f5e3Sopenharmony_ci return GetJSHClass()->IsJSArray(); 1004514f5e3Sopenharmony_ci} 1014514f5e3Sopenharmony_ci 1024514f5e3Sopenharmony_ciinline bool JSObject::IsJSSArray() const 1034514f5e3Sopenharmony_ci{ 1044514f5e3Sopenharmony_ci return GetJSHClass()->IsJSSharedArray(); 1054514f5e3Sopenharmony_ci} 1064514f5e3Sopenharmony_ci 1074514f5e3Sopenharmony_ciinline bool JSObject::IsJSShared() const 1084514f5e3Sopenharmony_ci{ 1094514f5e3Sopenharmony_ci return GetJSHClass()->IsJSShared(); 1104514f5e3Sopenharmony_ci} 1114514f5e3Sopenharmony_ci 1124514f5e3Sopenharmony_ciinline bool JSObject::IsJSMap() const 1134514f5e3Sopenharmony_ci{ 1144514f5e3Sopenharmony_ci return GetJSHClass()->IsJSMap(); 1154514f5e3Sopenharmony_ci} 1164514f5e3Sopenharmony_ci 1174514f5e3Sopenharmony_ciinline bool JSObject::IsJSSet() const 1184514f5e3Sopenharmony_ci{ 1194514f5e3Sopenharmony_ci return GetJSHClass()->IsJSSet(); 1204514f5e3Sopenharmony_ci} 1214514f5e3Sopenharmony_ci 1224514f5e3Sopenharmony_ciinline bool JSObject::IsJSRegExp() const 1234514f5e3Sopenharmony_ci{ 1244514f5e3Sopenharmony_ci return GetJSHClass()->IsJSRegExp(); 1254514f5e3Sopenharmony_ci} 1264514f5e3Sopenharmony_ci 1274514f5e3Sopenharmony_ciinline bool JSObject::IsJSFunction() const 1284514f5e3Sopenharmony_ci{ 1294514f5e3Sopenharmony_ci return GetJSHClass()->IsJSFunction(); 1304514f5e3Sopenharmony_ci} 1314514f5e3Sopenharmony_ci 1324514f5e3Sopenharmony_ciinline bool JSObject::IsBoundFunction() const 1334514f5e3Sopenharmony_ci{ 1344514f5e3Sopenharmony_ci return GetJSHClass()->IsJsBoundFunction(); 1354514f5e3Sopenharmony_ci} 1364514f5e3Sopenharmony_ci 1374514f5e3Sopenharmony_ciinline bool JSObject::IsJSIntlBoundFunction() const 1384514f5e3Sopenharmony_ci{ 1394514f5e3Sopenharmony_ci return GetJSHClass()->IsJSIntlBoundFunction(); 1404514f5e3Sopenharmony_ci} 1414514f5e3Sopenharmony_ci 1424514f5e3Sopenharmony_ciinline bool JSObject::IsProxyRevocFunction() const 1434514f5e3Sopenharmony_ci{ 1444514f5e3Sopenharmony_ci return GetJSHClass()->IsJSProxyRevocFunction(); 1454514f5e3Sopenharmony_ci} 1464514f5e3Sopenharmony_ci 1474514f5e3Sopenharmony_ciinline bool JSObject::IsAccessorData() const 1484514f5e3Sopenharmony_ci{ 1494514f5e3Sopenharmony_ci return GetJSHClass()->IsAccessorData(); 1504514f5e3Sopenharmony_ci} 1514514f5e3Sopenharmony_ci 1524514f5e3Sopenharmony_ciinline bool JSObject::IsJSGlobalEnv() const 1534514f5e3Sopenharmony_ci{ 1544514f5e3Sopenharmony_ci return GetJSHClass()->IsJsGlobalEnv(); 1554514f5e3Sopenharmony_ci} 1564514f5e3Sopenharmony_ci 1574514f5e3Sopenharmony_ciinline bool JSObject::IsJSProxy() const 1584514f5e3Sopenharmony_ci{ 1594514f5e3Sopenharmony_ci return GetJSHClass()->IsJSProxy(); 1604514f5e3Sopenharmony_ci} 1614514f5e3Sopenharmony_ci 1624514f5e3Sopenharmony_ciinline bool JSObject::IsGeneratorObject() const 1634514f5e3Sopenharmony_ci{ 1644514f5e3Sopenharmony_ci return GetJSHClass()->IsGeneratorObject(); 1654514f5e3Sopenharmony_ci} 1664514f5e3Sopenharmony_ci 1674514f5e3Sopenharmony_ciinline bool JSObject::IsAsyncGeneratorObject() const 1684514f5e3Sopenharmony_ci{ 1694514f5e3Sopenharmony_ci return GetJSHClass()->IsAsyncGeneratorObject(); 1704514f5e3Sopenharmony_ci} 1714514f5e3Sopenharmony_ci 1724514f5e3Sopenharmony_ciinline bool JSObject::IsForinIterator() const 1734514f5e3Sopenharmony_ci{ 1744514f5e3Sopenharmony_ci return GetJSHClass()->IsForinIterator(); 1754514f5e3Sopenharmony_ci} 1764514f5e3Sopenharmony_ci 1774514f5e3Sopenharmony_ciinline bool JSObject::IsJSSetIterator() const 1784514f5e3Sopenharmony_ci{ 1794514f5e3Sopenharmony_ci return GetJSHClass()->IsJSSetIterator(); 1804514f5e3Sopenharmony_ci} 1814514f5e3Sopenharmony_ci 1824514f5e3Sopenharmony_ciinline bool JSObject::IsJSRegExpIterator() const 1834514f5e3Sopenharmony_ci{ 1844514f5e3Sopenharmony_ci return GetJSHClass()->IsJSRegExpIterator(); 1854514f5e3Sopenharmony_ci} 1864514f5e3Sopenharmony_ci 1874514f5e3Sopenharmony_ciinline bool JSObject::IsJSMapIterator() const 1884514f5e3Sopenharmony_ci{ 1894514f5e3Sopenharmony_ci return GetJSHClass()->IsJSMapIterator(); 1904514f5e3Sopenharmony_ci} 1914514f5e3Sopenharmony_ci 1924514f5e3Sopenharmony_ciinline bool JSObject::IsJSArrayIterator() const 1934514f5e3Sopenharmony_ci{ 1944514f5e3Sopenharmony_ci return GetJSHClass()->IsJSArrayIterator(); 1954514f5e3Sopenharmony_ci} 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIArrayListIterator() const 1984514f5e3Sopenharmony_ci{ 1994514f5e3Sopenharmony_ci return GetJSHClass()->IsJSAPIArrayListIterator(); 2004514f5e3Sopenharmony_ci} 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIStackIterator() const 2034514f5e3Sopenharmony_ci{ 2044514f5e3Sopenharmony_ci return GetJSHClass()->IsJSAPIStackIterator(); 2054514f5e3Sopenharmony_ci} 2064514f5e3Sopenharmony_ci 2074514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIVectorIterator() const 2084514f5e3Sopenharmony_ci{ 2094514f5e3Sopenharmony_ci return GetJSHClass()->IsJSAPIVectorIterator(); 2104514f5e3Sopenharmony_ci} 2114514f5e3Sopenharmony_ci 2124514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIBitVectorIterator() const 2134514f5e3Sopenharmony_ci{ 2144514f5e3Sopenharmony_ci return GetJSHClass()->IsJSAPIBitVectorIterator(); 2154514f5e3Sopenharmony_ci} 2164514f5e3Sopenharmony_ci 2174514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPILinkedListIterator() const 2184514f5e3Sopenharmony_ci{ 2194514f5e3Sopenharmony_ci return GetJSHClass()->IsJSAPILinkedListIterator(); 2204514f5e3Sopenharmony_ci} 2214514f5e3Sopenharmony_ci 2224514f5e3Sopenharmony_ciinline bool JSObject::IsJSAPIListIterator() const 2234514f5e3Sopenharmony_ci{ 2244514f5e3Sopenharmony_ci return GetJSHClass()->IsJSAPIListIterator(); 2254514f5e3Sopenharmony_ci} 2264514f5e3Sopenharmony_ci 2274514f5e3Sopenharmony_ciinline bool JSObject::IsJSPrimitiveRef() const 2284514f5e3Sopenharmony_ci{ 2294514f5e3Sopenharmony_ci return GetJSHClass()->IsJsPrimitiveRef(); 2304514f5e3Sopenharmony_ci} 2314514f5e3Sopenharmony_ci 2324514f5e3Sopenharmony_ciinline bool JSObject::IsElementDict() const 2334514f5e3Sopenharmony_ci{ 2344514f5e3Sopenharmony_ci return TaggedArray::Cast(GetElements().GetTaggedObject())->IsDictionaryMode(); 2354514f5e3Sopenharmony_ci} 2364514f5e3Sopenharmony_ci 2374514f5e3Sopenharmony_ciinline bool JSObject::IsPropertiesDict() const 2384514f5e3Sopenharmony_ci{ 2394514f5e3Sopenharmony_ci return TaggedArray::Cast(GetProperties().GetTaggedObject())->IsDictionaryMode(); 2404514f5e3Sopenharmony_ci} 2414514f5e3Sopenharmony_ci 2424514f5e3Sopenharmony_ciinline bool JSObject::IsTypedArray() const 2434514f5e3Sopenharmony_ci{ 2444514f5e3Sopenharmony_ci return GetJSHClass()->IsTypedArray(); 2454514f5e3Sopenharmony_ci} 2464514f5e3Sopenharmony_ci 2474514f5e3Sopenharmony_cistd::pair<bool, JSTaggedValue> JSObject::ConvertValueWithRep(PropertyAttributes attr, JSTaggedValue value) 2484514f5e3Sopenharmony_ci{ 2494514f5e3Sopenharmony_ci if (attr.IsDoubleRep()) { 2504514f5e3Sopenharmony_ci if (value.IsInt()) { 2514514f5e3Sopenharmony_ci double doubleValue = value.GetInt(); 2524514f5e3Sopenharmony_ci return std::pair(true, JSTaggedValue(bit_cast<JSTaggedType>(doubleValue))); 2534514f5e3Sopenharmony_ci } else if (value.IsDouble()) { 2544514f5e3Sopenharmony_ci return std::pair(true, JSTaggedValue(bit_cast<JSTaggedType>(value.GetDouble()))); 2554514f5e3Sopenharmony_ci } else { 2564514f5e3Sopenharmony_ci return std::pair(false, value); 2574514f5e3Sopenharmony_ci } 2584514f5e3Sopenharmony_ci } else if (attr.IsIntRep()) { 2594514f5e3Sopenharmony_ci if (value.IsInt()) { 2604514f5e3Sopenharmony_ci int intValue = value.GetInt(); 2614514f5e3Sopenharmony_ci return std::pair(true, JSTaggedValue(static_cast<JSTaggedType>(intValue))); 2624514f5e3Sopenharmony_ci } else { 2634514f5e3Sopenharmony_ci return std::pair(false, value); 2644514f5e3Sopenharmony_ci } 2654514f5e3Sopenharmony_ci } 2664514f5e3Sopenharmony_ci return std::pair(true, value); 2674514f5e3Sopenharmony_ci} 2684514f5e3Sopenharmony_ci 2694514f5e3Sopenharmony_civoid JSObject::SetPropertyInlinedPropsWithRep(const JSThread *thread, uint32_t index, JSTaggedValue value) 2704514f5e3Sopenharmony_ci{ 2714514f5e3Sopenharmony_ci auto layout = LayoutInfo::Cast(GetJSHClass()->GetLayout().GetTaggedObject()); 2724514f5e3Sopenharmony_ci auto attr = layout->GetAttr(index); 2734514f5e3Sopenharmony_ci if (attr.IsTaggedRep()) { 2744514f5e3Sopenharmony_ci SetPropertyInlinedProps<true>(thread, index, value); 2754514f5e3Sopenharmony_ci } else { 2764514f5e3Sopenharmony_ci SetPropertyInlinedProps<false>(thread, index, value); 2774514f5e3Sopenharmony_ci } 2784514f5e3Sopenharmony_ci} 2794514f5e3Sopenharmony_ci 2804514f5e3Sopenharmony_citemplate <bool needBarrier> 2814514f5e3Sopenharmony_civoid JSObject::SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value) 2824514f5e3Sopenharmony_ci{ 2834514f5e3Sopenharmony_ci SetPropertyInlinedProps<needBarrier>(thread, GetJSHClass(), index, value); 2844514f5e3Sopenharmony_ci} 2854514f5e3Sopenharmony_ci 2864514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetPropertyInlinedPropsWithRep(uint32_t index, PropertyAttributes attr) const 2874514f5e3Sopenharmony_ci{ 2884514f5e3Sopenharmony_ci return GetPropertyInlinedPropsWithRep(GetJSHClass(), index, attr); 2894514f5e3Sopenharmony_ci} 2904514f5e3Sopenharmony_ci 2914514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetPropertyInlinedPropsWithRep(const JSHClass *hclass, uint32_t index, 2924514f5e3Sopenharmony_ci PropertyAttributes attr) const 2934514f5e3Sopenharmony_ci{ 2944514f5e3Sopenharmony_ci auto value = GetPropertyInlinedProps(hclass, index); 2954514f5e3Sopenharmony_ci if (attr.IsDoubleRep()) { 2964514f5e3Sopenharmony_ci value = JSTaggedValue(bit_cast<double>(value.GetRawData())); 2974514f5e3Sopenharmony_ci } else if (attr.IsIntRep()) { 2984514f5e3Sopenharmony_ci value = JSTaggedValue(static_cast<int32_t>(value.GetRawData())); 2994514f5e3Sopenharmony_ci } 3004514f5e3Sopenharmony_ci return value; 3014514f5e3Sopenharmony_ci} 3024514f5e3Sopenharmony_ci 3034514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetPropertyInlinedProps(uint32_t index) const 3044514f5e3Sopenharmony_ci{ 3054514f5e3Sopenharmony_ci return GetPropertyInlinedProps(GetJSHClass(), index); 3064514f5e3Sopenharmony_ci} 3074514f5e3Sopenharmony_ci 3084514f5e3Sopenharmony_citemplate <bool needBarrier> 3094514f5e3Sopenharmony_civoid JSObject::SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index, 3104514f5e3Sopenharmony_ci JSTaggedValue value) 3114514f5e3Sopenharmony_ci{ 3124514f5e3Sopenharmony_ci uint32_t offset = hclass->GetInlinedPropertiesOffset(index); 3134514f5e3Sopenharmony_ci ASSERT(hclass->GetObjectSize() > offset); 3144514f5e3Sopenharmony_ci if constexpr (needBarrier) { 3154514f5e3Sopenharmony_ci SET_VALUE_WITH_BARRIER(thread, this, offset, value); 3164514f5e3Sopenharmony_ci } else { 3174514f5e3Sopenharmony_ci SET_VALUE_PRIMITIVE(this, offset, value); 3184514f5e3Sopenharmony_ci } 3194514f5e3Sopenharmony_ci} 3204514f5e3Sopenharmony_ci 3214514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetPropertyInlinedProps(const JSHClass *hclass, uint32_t index) const 3224514f5e3Sopenharmony_ci{ 3234514f5e3Sopenharmony_ci uint32_t offset = hclass->GetInlinedPropertiesOffset(index); 3244514f5e3Sopenharmony_ci return JSTaggedValue(GET_VALUE(this, offset)); 3254514f5e3Sopenharmony_ci} 3264514f5e3Sopenharmony_ci 3274514f5e3Sopenharmony_ciJSTaggedValue JSObject::GetProperty(const JSHClass *hclass, PropertyAttributes attr) const 3284514f5e3Sopenharmony_ci{ 3294514f5e3Sopenharmony_ci if (attr.IsInlinedProps()) { 3304514f5e3Sopenharmony_ci return GetPropertyInlinedPropsWithRep(hclass, attr.GetOffset(), attr); 3314514f5e3Sopenharmony_ci } 3324514f5e3Sopenharmony_ci TaggedArray *array = TaggedArray::Cast(GetProperties().GetTaggedObject()); 3334514f5e3Sopenharmony_ci return array->Get(attr.GetOffset() - hclass->GetInlinedProperties()); 3344514f5e3Sopenharmony_ci} 3354514f5e3Sopenharmony_ci 3364514f5e3Sopenharmony_citemplate <bool needBarrier> 3374514f5e3Sopenharmony_civoid JSObject::SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr, JSTaggedValue value) 3384514f5e3Sopenharmony_ci{ 3394514f5e3Sopenharmony_ci if (attr.IsInlinedProps()) { 3404514f5e3Sopenharmony_ci SetPropertyInlinedProps<needBarrier>(thread, hclass, attr.GetOffset(), value); 3414514f5e3Sopenharmony_ci } else { 3424514f5e3Sopenharmony_ci TaggedArray *array = TaggedArray::Cast(GetProperties().GetTaggedObject()); 3434514f5e3Sopenharmony_ci array->Set<needBarrier>(thread, attr.GetOffset() - hclass->GetInlinedProperties(), value); 3444514f5e3Sopenharmony_ci } 3454514f5e3Sopenharmony_ci} 3464514f5e3Sopenharmony_ci 3474514f5e3Sopenharmony_ciinline bool JSObject::ShouldTransToDict(uint32_t capacity, uint32_t index) 3484514f5e3Sopenharmony_ci{ 3494514f5e3Sopenharmony_ci if (index < capacity) { 3504514f5e3Sopenharmony_ci return false; 3514514f5e3Sopenharmony_ci } 3524514f5e3Sopenharmony_ci 3534514f5e3Sopenharmony_ci if (index - capacity > MAX_GAP) { 3544514f5e3Sopenharmony_ci return true; 3554514f5e3Sopenharmony_ci } 3564514f5e3Sopenharmony_ci 3574514f5e3Sopenharmony_ci if (index >= static_cast<uint32_t>(INT32_MAX)) { 3584514f5e3Sopenharmony_ci return true; 3594514f5e3Sopenharmony_ci } 3604514f5e3Sopenharmony_ci 3614514f5e3Sopenharmony_ci if (capacity >= MIN_GAP) { 3624514f5e3Sopenharmony_ci return index > capacity * FAST_ELEMENTS_FACTOR; 3634514f5e3Sopenharmony_ci } 3644514f5e3Sopenharmony_ci 3654514f5e3Sopenharmony_ci return false; 3664514f5e3Sopenharmony_ci} 3674514f5e3Sopenharmony_ci 3684514f5e3Sopenharmony_ciinline bool JSObject::ShouldTransToFastElements(JSThread *thread, TaggedArray *elements, 3694514f5e3Sopenharmony_ci uint32_t capacity, uint32_t index) 3704514f5e3Sopenharmony_ci{ 3714514f5e3Sopenharmony_ci JSHandle<NumberDictionary> dictionary(thread, elements); 3724514f5e3Sopenharmony_ci if (index >= static_cast<uint32_t>(INT32_MAX)) { 3734514f5e3Sopenharmony_ci return false; 3744514f5e3Sopenharmony_ci } 3754514f5e3Sopenharmony_ci // Turn fast if only saves 50% space. 3764514f5e3Sopenharmony_ci if (static_cast<uint32_t>(dictionary->GetLength()) * SHOULD_TRANS_TO_FAST_ELEMENTS_FACTOR >= capacity || 3774514f5e3Sopenharmony_ci static_cast<uint64_t>(dictionary->NextEnumerationIndex(thread)) > 3784514f5e3Sopenharmony_ci PropertyAttributes::DictionaryOrderField::MaxValue()) { 3794514f5e3Sopenharmony_ci return true; 3804514f5e3Sopenharmony_ci } 3814514f5e3Sopenharmony_ci return false; 3824514f5e3Sopenharmony_ci} 3834514f5e3Sopenharmony_ci 3844514f5e3Sopenharmony_ciinline uint32_t JSObject::ComputeElementCapacity(uint32_t oldCapacity, bool isNew) 3854514f5e3Sopenharmony_ci{ 3864514f5e3Sopenharmony_ci uint32_t newCapacity = isNew ? oldCapacity : (oldCapacity + (oldCapacity >> 1U)); 3874514f5e3Sopenharmony_ci return newCapacity > MIN_ELEMENTS_LENGTH ? newCapacity : MIN_ELEMENTS_LENGTH; 3884514f5e3Sopenharmony_ci} 3894514f5e3Sopenharmony_ci 3904514f5e3Sopenharmony_ciinline uint32_t JSObject::ComputeElementCapacityHighGrowth(uint32_t oldCapacity) 3914514f5e3Sopenharmony_ci{ 3924514f5e3Sopenharmony_ci uint32_t newCapacity = oldCapacity * 2; 3934514f5e3Sopenharmony_ci return newCapacity > MIN_ELEMENTS_LENGTH ? newCapacity : MIN_ELEMENTS_LENGTH; 3944514f5e3Sopenharmony_ci} 3954514f5e3Sopenharmony_ci 3964514f5e3Sopenharmony_ciinline uint32_t JSObject::ComputeElementCapacityWithHint(uint32_t oldCapacity, uint32_t hint) 3974514f5e3Sopenharmony_ci{ 3984514f5e3Sopenharmony_ci uint32_t newCapacity = 0; 3994514f5e3Sopenharmony_ci if ((oldCapacity >= hint) || (hint < MIN_ELEMENTS_HINT_LENGTH) || (hint >= MAX_ELEMENTS_HINT_LENGTH)) { 4004514f5e3Sopenharmony_ci return newCapacity; 4014514f5e3Sopenharmony_ci } 4024514f5e3Sopenharmony_ci if ((hint / oldCapacity) <= ELEMENTS_HINT_FACTOR) { 4034514f5e3Sopenharmony_ci newCapacity = hint; 4044514f5e3Sopenharmony_ci } 4054514f5e3Sopenharmony_ci return newCapacity; 4064514f5e3Sopenharmony_ci} 4074514f5e3Sopenharmony_ci 4084514f5e3Sopenharmony_ciinline uint32_t JSObject::ComputeNonInlinedFastPropsCapacity(JSThread *thread, uint32_t oldCapacity, 4094514f5e3Sopenharmony_ci uint32_t maxNonInlinedFastPropsCapacity) 4104514f5e3Sopenharmony_ci{ 4114514f5e3Sopenharmony_ci uint32_t newCapacity = oldCapacity + thread->GetPropertiesGrowStep(); 4124514f5e3Sopenharmony_ci return newCapacity > maxNonInlinedFastPropsCapacity ? maxNonInlinedFastPropsCapacity : newCapacity; 4134514f5e3Sopenharmony_ci} 4144514f5e3Sopenharmony_ci 4154514f5e3Sopenharmony_ci// static 4164514f5e3Sopenharmony_citemplate<ElementTypes types> 4174514f5e3Sopenharmony_ciJSHandle<JSTaggedValue> JSObject::CreateListFromArrayLike(JSThread *thread, const JSHandle<JSTaggedValue> &obj) 4184514f5e3Sopenharmony_ci{ 4194514f5e3Sopenharmony_ci // 3. If Type(obj) is not Object, throw a TypeError exception. 4204514f5e3Sopenharmony_ci if (!obj->IsECMAObject()) { 4214514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "CreateListFromArrayLike must accept object", 4224514f5e3Sopenharmony_ci JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception())); 4234514f5e3Sopenharmony_ci } 4244514f5e3Sopenharmony_ci if (obj->IsTypedArray()) { 4254514f5e3Sopenharmony_ci uint32_t len = JSHandle<JSTypedArray>::Cast(obj)->GetArrayLength(); 4264514f5e3Sopenharmony_ci JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len); 4274514f5e3Sopenharmony_ci JSTypedArray::FastCopyElementToArray(thread, obj, array); 4284514f5e3Sopenharmony_ci // c. ReturnIfAbrupt(next). 4294514f5e3Sopenharmony_ci RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); 4304514f5e3Sopenharmony_ci return JSHandle<JSTaggedValue>(array); 4314514f5e3Sopenharmony_ci } 4324514f5e3Sopenharmony_ci // 4. Let len be ToLength(Get(obj, "length")). 4334514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); 4344514f5e3Sopenharmony_ci 4354514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value = GetProperty(thread, obj, lengthKeyHandle).GetValue(); 4364514f5e3Sopenharmony_ci JSTaggedNumber number = JSTaggedValue::ToLength(thread, value); 4374514f5e3Sopenharmony_ci // 5. ReturnIfAbrupt(len). 4384514f5e3Sopenharmony_ci RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); 4394514f5e3Sopenharmony_ci if (number.GetNumber() > MAX_ELEMENT_INDEX) { 4404514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "len is bigger than 2^32 - 1", 4414514f5e3Sopenharmony_ci JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception())); 4424514f5e3Sopenharmony_ci } 4434514f5e3Sopenharmony_ci 4444514f5e3Sopenharmony_ci uint32_t len = number.ToUint32(); 4454514f5e3Sopenharmony_ci // 6. Let list be an empty List. 4464514f5e3Sopenharmony_ci JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len); 4474514f5e3Sopenharmony_ci // 8. Repeat while index < len 4484514f5e3Sopenharmony_ci for (uint32_t i = 0; i < len; i++) { 4494514f5e3Sopenharmony_ci JSTaggedValue next = JSTaggedValue::GetProperty(thread, obj, i).GetValue().GetTaggedValue(); 4504514f5e3Sopenharmony_ci // c. ReturnIfAbrupt(next). 4514514f5e3Sopenharmony_ci RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); 4524514f5e3Sopenharmony_ci 4534514f5e3Sopenharmony_ci if constexpr (types == ElementTypes::STRING_AND_SYMBOL) { 4544514f5e3Sopenharmony_ci if (!next.IsString() && !next.IsSymbol()) { 4554514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "CreateListFromArrayLike: not an element of elementTypes", 4564514f5e3Sopenharmony_ci JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception())); 4574514f5e3Sopenharmony_ci } 4584514f5e3Sopenharmony_ci } 4594514f5e3Sopenharmony_ci 4604514f5e3Sopenharmony_ci array->Set(thread, i, next); 4614514f5e3Sopenharmony_ci } 4624514f5e3Sopenharmony_ci return JSHandle<JSTaggedValue>(array); 4634514f5e3Sopenharmony_ci} 4644514f5e3Sopenharmony_ci 4654514f5e3Sopenharmony_ciinline JSTaggedValue JSObject::ShouldGetValueFromBox(ObjectOperator *op) 4664514f5e3Sopenharmony_ci{ 4674514f5e3Sopenharmony_ci JSTaggedValue result = op->GetValue(); 4684514f5e3Sopenharmony_ci if (result.IsPropertyBox()) { 4694514f5e3Sopenharmony_ci result = PropertyBox::Cast(result.GetTaggedObject())->GetValue(); 4704514f5e3Sopenharmony_ci } 4714514f5e3Sopenharmony_ci return result; 4724514f5e3Sopenharmony_ci} 4734514f5e3Sopenharmony_ci 4744514f5e3Sopenharmony_ciinline bool JSObject::CheckHClassHit(const JSHandle<JSObject> &obj, const JSHandle<JSHClass> &cls) 4754514f5e3Sopenharmony_ci{ 4764514f5e3Sopenharmony_ci return obj->GetJSHClass() == *cls; 4774514f5e3Sopenharmony_ci} 4784514f5e3Sopenharmony_ci 4794514f5e3Sopenharmony_ciinline uint32_t JSObject::SetValuesOrEntries(JSThread *thread, const JSHandle<TaggedArray> &prop, uint32_t index, 4804514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value, 4814514f5e3Sopenharmony_ci PropertyKind kind) 4824514f5e3Sopenharmony_ci{ 4834514f5e3Sopenharmony_ci if (kind == PropertyKind::VALUE) { 4844514f5e3Sopenharmony_ci prop->Set(thread, index++, value); 4854514f5e3Sopenharmony_ci return index; 4864514f5e3Sopenharmony_ci } 4874514f5e3Sopenharmony_ci JSHandle<TaggedArray> keyValue = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(2); // 2: key-value pair 4884514f5e3Sopenharmony_ci keyValue->Set(thread, 0, key); 4894514f5e3Sopenharmony_ci keyValue->Set(thread, 1, value); 4904514f5e3Sopenharmony_ci JSHandle<JSArray> entry = JSArray::CreateArrayFromList(thread, keyValue); 4914514f5e3Sopenharmony_ci prop->Set(thread, index++, entry.GetTaggedValue()); 4924514f5e3Sopenharmony_ci return index; 4934514f5e3Sopenharmony_ci} 4944514f5e3Sopenharmony_ci 4954514f5e3Sopenharmony_ciinline void JSObject::SetEnumCacheKind(JSThread *thread, TaggedArray *array, EnumCacheKind kind) 4964514f5e3Sopenharmony_ci{ 4974514f5e3Sopenharmony_ci array->Set(thread, EnumCache::ENUM_CACHE_KIND_OFFSET, JSTaggedValue(static_cast<uint8_t>(kind))); 4984514f5e3Sopenharmony_ci} 4994514f5e3Sopenharmony_ci 5004514f5e3Sopenharmony_ciinline EnumCacheKind JSObject::GetEnumCacheKind(JSThread *thread, TaggedArray *array) 5014514f5e3Sopenharmony_ci{ 5024514f5e3Sopenharmony_ci return static_cast<EnumCacheKind>(array->Get(thread, EnumCache::ENUM_CACHE_KIND_OFFSET).GetInt()); 5034514f5e3Sopenharmony_ci} 5044514f5e3Sopenharmony_ci 5054514f5e3Sopenharmony_ciinline EnumCacheKind JSObject::GetEnumCacheKind(JSThread *thread, JSTaggedValue enumCache) 5064514f5e3Sopenharmony_ci{ 5074514f5e3Sopenharmony_ci if (enumCache.IsUndefinedOrNull()) { 5084514f5e3Sopenharmony_ci return EnumCacheKind::NONE; 5094514f5e3Sopenharmony_ci } 5104514f5e3Sopenharmony_ci JSTaggedValue emptyArray = thread->GlobalConstants()->GetEmptyArray(); 5114514f5e3Sopenharmony_ci if (enumCache == emptyArray) { 5124514f5e3Sopenharmony_ci return EnumCacheKind::SIMPLE; 5134514f5e3Sopenharmony_ci } 5144514f5e3Sopenharmony_ci TaggedArray *array = TaggedArray::Cast(enumCache.GetTaggedObject()); 5154514f5e3Sopenharmony_ci return JSObject::GetEnumCacheKind(thread, array); 5164514f5e3Sopenharmony_ci} 5174514f5e3Sopenharmony_ci 5184514f5e3Sopenharmony_ciinline JSTaggedValue JSObject::GetPrototype(JSTaggedValue obj) 5194514f5e3Sopenharmony_ci{ 5204514f5e3Sopenharmony_ci JSHClass *hclass = obj.GetTaggedObject()->GetClass(); 5214514f5e3Sopenharmony_ci return hclass->GetPrototype(); 5224514f5e3Sopenharmony_ci} 5234514f5e3Sopenharmony_ci 5244514f5e3Sopenharmony_ciinline bool JSObject::IsDepulicateKeys(JSThread *thread, JSHandle<TaggedArray> keys, int32_t lastLength, 5254514f5e3Sopenharmony_ci JSHandle<TaggedQueue> shadowQueue, JSHandle<JSTaggedValue> key) 5264514f5e3Sopenharmony_ci{ 5274514f5e3Sopenharmony_ci if (lastLength < 0) { 5284514f5e3Sopenharmony_ci return false; 5294514f5e3Sopenharmony_ci } 5304514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 5314514f5e3Sopenharmony_ci for (int32_t i = EnumCache::ENUM_CACHE_HEADER_SIZE; i < lastLength; i++) { 5324514f5e3Sopenharmony_ci value.Update(keys->Get(i)); 5334514f5e3Sopenharmony_ci bool has = JSTaggedValue::Equal(thread, value, key); 5344514f5e3Sopenharmony_ci if (has) { 5354514f5e3Sopenharmony_ci return true; 5364514f5e3Sopenharmony_ci } 5374514f5e3Sopenharmony_ci } 5384514f5e3Sopenharmony_ci 5394514f5e3Sopenharmony_ci uint32_t shadowSize = shadowQueue->Size(); 5404514f5e3Sopenharmony_ci for (uint32_t i = 0; i < shadowSize; i++) { 5414514f5e3Sopenharmony_ci value.Update(shadowQueue->Get(i)); 5424514f5e3Sopenharmony_ci bool has = JSTaggedValue::Equal(thread, value, key); 5434514f5e3Sopenharmony_ci if (has) { 5444514f5e3Sopenharmony_ci return true; 5454514f5e3Sopenharmony_ci } 5464514f5e3Sopenharmony_ci } 5474514f5e3Sopenharmony_ci return false; 5484514f5e3Sopenharmony_ci} 5494514f5e3Sopenharmony_ci 5504514f5e3Sopenharmony_ciinline void JSObject::ClearHasDeleteProperty(JSHandle<JSTaggedValue> object) 5514514f5e3Sopenharmony_ci{ 5524514f5e3Sopenharmony_ci object->GetTaggedObject()->GetClass()->SetHasDeleteProperty(false); 5534514f5e3Sopenharmony_ci} 5544514f5e3Sopenharmony_ci 5554514f5e3Sopenharmony_ciinline std::pair<JSHandle<TaggedArray>, JSHandle<TaggedArray>> JSObject::GetOwnEnumerableNamesInFastMode( 5564514f5e3Sopenharmony_ci JSThread *thread, const JSHandle<JSObject> &obj, uint32_t *copyLengthOfKeys, uint32_t *copyLengthOfElements) 5574514f5e3Sopenharmony_ci{ 5584514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 5594514f5e3Sopenharmony_ci std::pair<uint32_t, uint32_t> numOfKeys = obj->GetNumberOfEnumKeys(); 5604514f5e3Sopenharmony_ci uint32_t numOfEnumKeys = numOfKeys.first; 5614514f5e3Sopenharmony_ci uint32_t numOfElements = obj->GetNumberOfElements(); 5624514f5e3Sopenharmony_ci JSHandle<TaggedArray> elementArray = numOfElements > 0 ? JSObject::GetEnumElementKeys( 5634514f5e3Sopenharmony_ci thread, obj, 0, numOfElements, copyLengthOfElements) : factory->EmptyArray(); 5644514f5e3Sopenharmony_ci JSHandle<TaggedArray> keyArray = numOfEnumKeys > 0 ? JSObject::GetAllEnumKeys( 5654514f5e3Sopenharmony_ci thread, obj, numOfEnumKeys, copyLengthOfKeys) : factory->EmptyArray(); 5664514f5e3Sopenharmony_ci return std::make_pair(keyArray, elementArray); 5674514f5e3Sopenharmony_ci} 5684514f5e3Sopenharmony_ci 5694514f5e3Sopenharmony_ciinline bool JSObject::HasMutantTaggedArrayElements(const JSHandle<JSObject> &obj) 5704514f5e3Sopenharmony_ci{ 5714514f5e3Sopenharmony_ci return obj->GetElements().IsMutantTaggedArray(); 5724514f5e3Sopenharmony_ci} 5734514f5e3Sopenharmony_ci} // namespace panda::ecmascript 5744514f5e3Sopenharmony_ci#endif // ECMASCRIPT_JSOBJECT_INL_H 575