* Copyright (c) 2021-2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_JS_HCLASS_H
#define ECMASCRIPT_JS_HCLASS_H
#include "ecmascript/cross_vm/js_hclass_hybrid.h"
#include "ecmascript/base/config.h"
#include "ecmascript/ecma_macros.h"
#include "ecmascript/elements.h"
#include "ecmascript/js_tagged_value_wrapper.h"
#include "ecmascript/mem/tagged_object.h"
#include "ecmascript/mem/barriers.h"
#include "ecmascript/mem/slots.h"
#include "ecmascript/mem/visitor.h"
#include "ecmascript/property_attributes.h"
#include "ecmascript/string/composite_base_class.h"
#include "ecmascript/pgo_profiler/pgo_utils.h"
#include "libpandabase/utils/bit_field.h"
* JS Object and JS HClass Layout
*
* Properties JS Object JS HClass
* +------------+ +------------+ +------------------+
* |arrayHClass + <---------| |JS HClass +-------------->| meta hclass |
* +------------+ | +------------+ +------------------+
* | property 0 | | |Hash | | hclass level |
* +------------+ | +------------+ +------------------+
* | property 1 | |------- |Properties | | supers[] |
* +------------+ +------------+ +------------------+
* |... | |------- |Elements | | vtable[] |
* +------------+ | +------------+ +------------------+
* | |inl-prop-0 | | prototype |
* Elements | +------------+ +------------------+
* +------------+ | |inl-prop-1 | | layout |
* |arrayHClass + <---------| +------------+ +------------------+
* +------------+ |... | | transitions |
* | value 0 | +------------+ +------------------+
* +------------+ | parent |
* | value 1 | +------------------+
* +------------+ |ProtoChangeMarker |
* |... | +------------------+
* +------------+ | EnumCache |
* +------------------+
*
* Proto: [[Prototype]] in Ecma spec
* Layout: record key and attr
* ProtoChangeMarker, ProtoChangeDetails: monitor [[prototype]] chain
* EnumCache: use for for-in syntax
*
*/
namespace panda::ecmascript {
class ProtoChangeDetails;
class PropertyLookupResult;
class SharedHeap;
class JSSharedArray;
class LayoutInfo;
class NameDictionary;
class ObjectFactory;
class GlobalEnv;
namespace pgo {
class HClassLayoutDesc;
class PGOHClassTreeDesc;
class PGOHandler;
}
using HClassLayoutDesc = pgo::HClassLayoutDesc;
using PGOHClassTreeDesc = pgo::PGOHClassTreeDesc;
using PGOHandler = pgo::PGOHandler;
struct Reference;
#define JSTYPE_DECL(V) \
\
V(LINE_STRING), \
V(SLICED_STRING), \
V(TREE_STRING), \
V(CACHED_EXTERNAL_STRING), \
V(COMPOSITE_BASE_CLASS), \
\
V(JS_OBJECT), \
V(JS_WRAPPED_NAPI_OBJECT), \
V(JS_XREF_OBJECT), \
V(JS_SHARED_OBJECT), \
V(JS_REALM), \
V(JS_FUNCTION_BASE), \
V(JS_FUNCTION), \
V(JS_API_FUNCTION), \
V(JS_SHARED_FUNCTION), \
V(JS_PROXY_REVOC_FUNCTION), \
V(JS_PROMISE_REACTIONS_FUNCTION), \
V(JS_PROMISE_EXECUTOR_FUNCTION), \
V(JS_ASYNC_MODULE_FULFILLED_FUNCTION), \
V(JS_ASYNC_MODULE_REJECTED_FUNCTION), \
V(JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION), \
V(JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION), \
V(JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN), \
V(JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION), \
V(JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION), \
V(JS_PROMISE_FINALLY_FUNCTION), \
V(JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION), \
V(JS_GENERATOR_FUNCTION), \
V(JS_ASYNC_GENERATOR_FUNCTION), \
V(JS_ASYNC_FUNCTION), \
V(JS_SHARED_ASYNC_FUNCTION), \
V(JS_INTL_BOUND_FUNCTION), \
V(JS_ASYNC_AWAIT_STATUS_FUNCTION), \
V(JS_BOUND_FUNCTION), \
\
V(JS_ERROR), \
V(JS_EVAL_ERROR), \
V(JS_RANGE_ERROR), \
V(JS_REFERENCE_ERROR), \
V(JS_TYPE_ERROR), \
V(JS_AGGREGATE_ERROR), \
V(JS_URI_ERROR), \
V(JS_SYNTAX_ERROR), \
V(JS_OOM_ERROR), \
V(JS_TERMINATION_ERROR), \
\
V(JS_REG_EXP), \
V(JS_SET), \
V(JS_SHARED_SET), \
V(JS_MAP), \
V(JS_SHARED_MAP), \
V(JS_WEAK_MAP), \
V(JS_WEAK_SET), \
V(JS_WEAK_REF), \
V(JS_FINALIZATION_REGISTRY), \
V(JS_DATE), \
V(JS_ITERATOR), \
V(JS_ASYNCITERATOR), \
V(JS_ASYNC_FROM_SYNC_ITERATOR), \
V(JS_FORIN_ITERATOR), \
V(JS_MAP_ITERATOR), \
V(JS_SHARED_MAP_ITERATOR), \
V(JS_SET_ITERATOR), \
V(JS_SHARED_SET_ITERATOR), \
V(JS_REG_EXP_ITERATOR), \
V(JS_API_ARRAYLIST_ITERATOR), \
V(JS_API_DEQUE_ITERATOR), \
V(JS_API_HASHMAP_ITERATOR), \
V(JS_API_HASHSET_ITERATOR), \
V(JS_API_LIGHT_WEIGHT_MAP_ITERATOR), \
V(JS_API_LIGHT_WEIGHT_SET_ITERATOR), \
V(JS_API_PLAIN_ARRAY_ITERATOR), \
V(JS_API_QUEUE_ITERATOR), \
V(JS_API_STACK_ITERATOR), \
V(JS_API_TREEMAP_ITERATOR), \
V(JS_API_TREESET_ITERATOR), \
V(JS_API_VECTOR_ITERATOR), \
V(JS_API_BITVECTOR_ITERATOR), \
V(JS_API_LINKED_LIST_ITERATOR), \
V(JS_API_LIST_ITERATOR), \
V(JS_ARRAY_ITERATOR), \
V(JS_SHARED_ARRAY_ITERATOR), \
V(JS_SEGMENT_ITERATOR), \
V(JS_STRING_ITERATOR), \
V(JS_INTL), \
V(JS_LOCALE), \
V(JS_DATE_TIME_FORMAT), \
V(JS_RELATIVE_TIME_FORMAT), \
V(JS_NUMBER_FORMAT), \
V(JS_COLLATOR), \
V(JS_PLURAL_RULES), \
V(JS_DISPLAYNAMES), \
V(JS_LIST_FORMAT), \
V(JS_SEGMENTER), \
V(JS_SEGMENTS), \
\
V(JS_ARRAY_BUFFER), \
V(JS_SHARED_ARRAY_BUFFER), \
V(JS_SENDABLE_ARRAY_BUFFER), \
V(JS_PROMISE), \
V(JS_DATA_VIEW), \
V(JS_ARGUMENTS), \
V(JS_GENERATOR_OBJECT), \
V(JS_ASYNC_GENERATOR_OBJECT), \
V(JS_ASYNC_FUNC_OBJECT), \
\
\
V(JS_ARRAY), \
V(JS_SHARED_ARRAY), \
V(JS_API_ARRAY_LIST), \
V(JS_API_LIGHT_WEIGHT_MAP), \
V(JS_API_LIGHT_WEIGHT_SET), \
V(JS_API_VECTOR), \
V(JS_API_BITVECTOR), \
V(JS_API_LINKED_LIST), \
V(JS_API_LIST), \
V(JS_API_HASH_MAP), \
V(JS_API_HASH_SET), \
V(JS_API_TREE_MAP), \
V(JS_API_TREE_SET), \
V(JS_API_DEQUE), \
V(JS_API_STACK), \
V(JS_API_PLAIN_ARRAY), \
V(JS_API_FAST_BUFFER), \
V(JS_API_QUEUE), \
V(JS_TYPED_ARRAY), \
V(JS_INT8_ARRAY), \
V(JS_UINT8_ARRAY), \
V(JS_UINT8_CLAMPED_ARRAY), \
V(JS_INT16_ARRAY), \
V(JS_UINT16_ARRAY), \
V(JS_INT32_ARRAY), \
V(JS_UINT32_ARRAY), \
V(JS_FLOAT32_ARRAY), \
V(JS_FLOAT64_ARRAY), \
V(JS_BIGINT64_ARRAY), \
V(JS_BIGUINT64_ARRAY), \
V(JS_SHARED_TYPED_ARRAY), \
V(JS_SHARED_INT8_ARRAY), \
V(JS_SHARED_UINT8_ARRAY), \
V(JS_SHARED_UINT8_CLAMPED_ARRAY), \
V(JS_SHARED_INT16_ARRAY), \
V(JS_SHARED_UINT16_ARRAY), \
V(JS_SHARED_INT32_ARRAY), \
V(JS_SHARED_UINT32_ARRAY), \
V(JS_SHARED_FLOAT32_ARRAY), \
V(JS_SHARED_FLOAT64_ARRAY), \
V(JS_SHARED_BIGINT64_ARRAY), \
V(JS_SHARED_BIGUINT64_ARRAY), \
V(JS_PRIMITIVE_REF), \
V(JS_MODULE_NAMESPACE), \
V(JS_CJS_MODULE), \
V(JS_CJS_EXPORTS), \
V(JS_CJS_REQUIRE), \
V(NATIVE_MODULE_FAILURE_INFO), \
V(JS_GLOBAL_OBJECT), \
V(JS_PROXY), \
\
V(HCLASS), \
V(BIGINT), \
V(TAGGED_ARRAY), \
V(MUTANT_TAGGED_ARRAY), \
V(BYTE_ARRAY), \
V(LEXICAL_ENV), \
V(WEAK_LINKED_HASH_MAP), \
V(SFUNCTION_ENV), \
V(SENDABLE_ENV), \
V(TAGGED_DICTIONARY), \
V(CONSTANT_POOL), \
V(PROFILE_TYPE_INFO), \
V(IC_INFO), \
V(COW_MUTANT_TAGGED_ARRAY), \
V(COW_TAGGED_ARRAY), \
V(LINKED_NODE), \
V(RB_TREENODE), \
V(FREE_OBJECT_WITH_ONE_FIELD), \
V(FREE_OBJECT_WITH_NONE_FIELD), \
V(FREE_OBJECT_WITH_TWO_FIELD), \
V(JS_NATIVE_POINTER), \
V(GLOBAL_ENV), \
V(ACCESSOR_DATA), \
V(INTERNAL_ACCESSOR), \
V(SYMBOL), \
V(ENUM_CACHE), \
V(JS_GENERATOR_CONTEXT), \
V(PROTOTYPE_HANDLER), \
V(TRANSITION_HANDLER), \
V(TRANS_WITH_PROTO_HANDLER), \
V(STORE_TS_HANDLER), \
V(PROPERTY_BOX), \
V(PROTO_CHANGE_MARKER), \
V(MARKER_CELL), \
V(TRACK_INFO), \
V(PROTOTYPE_INFO), \
V(TEMPLATE_MAP), \
V(PROGRAM), \
V(METHOD), \
V(CLASS_LITERAL), \
\
V(PROMISE_CAPABILITY), \
V(PROMISE_RECORD), \
V(RESOLVING_FUNCTIONS_RECORD), \
V(PROMISE_REACTIONS), \
V(ASYNC_GENERATOR_REQUEST), \
V(ASYNC_ITERATOR_RECORD), \
V(PROMISE_ITERATOR_RECORD), \
V(MICRO_JOB_QUEUE), \
V(PENDING_JOB), \
V(MODULE_RECORD), \
V(SOURCE_TEXT_MODULE_RECORD), \
V(IMPORTENTRY_RECORD), \
V(LOCAL_EXPORTENTRY_RECORD), \
V(INDIRECT_EXPORTENTRY_RECORD), \
V(STAR_EXPORTENTRY_RECORD), \
V(RESOLVEDBINDING_RECORD), \
V(RESOLVEDINDEXBINDING_RECORD), \
V(RESOLVEDRECORDINDEXBINDING_RECORD), \
V(RESOLVEDRECORDBINDING_RECORD), \
V(CELL_RECORD), \
V(COMPLETION_RECORD), \
V(MACHINE_CODE_OBJECT), \
V(CLASS_INFO_EXTRACTOR), \
\
V(PROFILE_TYPE_INFO_CELL_0), \
V(PROFILE_TYPE_INFO_CELL_1), \
V(PROFILE_TYPE_INFO_CELL_N), \
\
V(EXTRA_PROFILE_TYPE_INFO), \
V(FUNCTION_TEMPLATE), \
\
V(VTABLE), \
V(AOT_LITERAL_INFO)
#define PRESET_JSTYPE_DECL \
TYPE_LAST = AOT_LITERAL_INFO, \
\
JS_FUNCTION_FIRST = JS_FUNCTION, \
JS_FUNCTION_LAST = JS_ASYNC_AWAIT_STATUS_FUNCTION, \
\
JS_OBJECT_FIRST = JS_OBJECT, \
JS_OBJECT_LAST = JS_GLOBAL_OBJECT, \
\
ECMA_OBJECT_FIRST = JS_OBJECT, \
ECMA_OBJECT_LAST = JS_PROXY, \
\
JS_ERROR_FIRST = JS_ERROR, \
JS_ERROR_LAST = JS_TERMINATION_ERROR, \
\
JS_ITERATOR_FIRST = JS_ITERATOR, \
JS_ITERATOR_LAST = JS_STRING_ITERATOR, \
\
JS_RECORD_FIRST = PROMISE_CAPABILITY, \
JS_RECORD_LAST = COMPLETION_RECORD, \
\
JS_TYPED_ARRAY_FIRST = JS_TYPED_ARRAY, \
JS_TYPED_ARRAY_LAST = JS_BIGUINT64_ARRAY, \
\
JS_SHARED_TYPED_ARRAY_FIRST = JS_SHARED_TYPED_ARRAY, \
JS_SHARED_TYPED_ARRAY_LAST = JS_SHARED_BIGUINT64_ARRAY, \
\
MODULE_RECORD_FIRST = MODULE_RECORD, \
MODULE_RECORD_LAST = SOURCE_TEXT_MODULE_RECORD, \
\
STRING_FIRST = LINE_STRING, \
STRING_LAST = CACHED_EXTERNAL_STRING, \
\
PROFILE_TYPE_INFO_CELL_FIRST = PROFILE_TYPE_INFO_CELL_0, \
PROFILE_TYPE_INFO_CELL_LAST = PROFILE_TYPE_INFO_CELL_N
#define JSTYPE_IDENTITY(type) type
#define JSTYPE_STRING(type) #type
enum class JSType : uint8_t {
INVALID = 0,
JSTYPE_DECL(JSTYPE_IDENTITY),
PRESET_JSTYPE_DECL,
};
static_assert(static_cast<uint8_t>(JSType::LINE_STRING) == static_cast<uint8_t>(EcmaStringType::LINE_STRING) &&
"line string type should be same with common type");
static_assert(static_cast<uint8_t>(JSType::SLICED_STRING) == static_cast<uint8_t>(EcmaStringType::SLICED_STRING) &&
"sliced string type should be same with common type");
static_assert(static_cast<uint8_t>(JSType::TREE_STRING) == static_cast<uint8_t>(EcmaStringType::TREE_STRING) &&
"tree string type should be same with common type");
struct TransitionResult {
bool isTagged;
bool isTransition;
JSTaggedValue value;
};
class JSHClass : public TaggedObject {
public:
static constexpr int TYPE_BITFIELD_NUM = 8;
static constexpr int LEVEL_BTTFIELD_NUM = 5;
static constexpr int ELEMENTS_KIND_BITFIELD_NUM = 5;
static constexpr int CONSTRUCTION_COUNTER_BITFIELD_NUM = 3;
static constexpr unsigned BITS_PER_BYTE = 8;
using ObjectTypeBits = BitField<JSType, 0, TYPE_BITFIELD_NUM>;
using CallableBit = ObjectTypeBits::NextFlag;
using ConstructorBit = CallableBit::NextFlag;
using ExtensibleBit = ConstructorBit::NextFlag;
using IsPrototypeBit = ExtensibleBit::NextFlag;
using ElementsKindBits = IsPrototypeBit::NextField<ElementsKind, ELEMENTS_KIND_BITFIELD_NUM>;
using DictionaryElementBits = ElementsKindBits::NextFlag;
using IsDictionaryBit = DictionaryElementBits::NextFlag;
using IsStableElementsBit = IsDictionaryBit::NextFlag;
using HasConstructorBits = IsStableElementsBit::NextFlag;
using IsClassConstructorOrPrototypeBit = HasConstructorBits::NextFlag;
using IsNativeBindingObjectBit = IsClassConstructorOrPrototypeBit::NextFlag;
using IsAOTBit = IsNativeBindingObjectBit::NextFlag;
using IsJSArrayPrototypeModifiedBit = IsAOTBit::NextFlag;
using IsJSFunctionBit = IsJSArrayPrototypeModifiedBit::NextFlag;
using IsOnHeap = IsJSFunctionBit::NextFlag;
using IsJSSharedBit = IsOnHeap::NextFlag;
using ConstructionCounterBits = IsJSSharedBit::NextField<uint8_t, CONSTRUCTION_COUNTER_BITFIELD_NUM>;
using IsStableBit = ConstructionCounterBits::NextFlag;
using BitFieldLastBit = IsStableBit;
static_assert(BitFieldLastBit::START_BIT + BitFieldLastBit::SIZE <= sizeof(uint32_t) * BITS_PER_BYTE, "Invalid");
static constexpr int DEFAULT_CAPACITY_OF_IN_OBJECTS = 4;
static constexpr int OFFSET_MAX_OBJECT_SIZE_IN_WORDS_WITHOUT_INLINED = 5;
static constexpr int OFFSET_MAX_OBJECT_SIZE_IN_WORDS =
PropertyAttributes::MAX_FAST_PROPS_CAPACITY_LOG2 + OFFSET_MAX_OBJECT_SIZE_IN_WORDS_WITHOUT_INLINED;
static constexpr int MAX_OBJECT_SIZE_IN_WORDS = (1U << OFFSET_MAX_OBJECT_SIZE_IN_WORDS) - 1;
static constexpr uint8_t SLACK_TRACKING_COUNT = (1 << CONSTRUCTION_COUNTER_BITFIELD_NUM) - 1;
static constexpr int OPTIMIZED_FUNCTION_CAPACITY_OF_IN_OBJECTS = 3;
using NumberOfPropsBits = BitField<uint32_t, 0, PropertyAttributes::MAX_FAST_PROPS_CAPACITY_LOG2>;
using InlinedPropsStartBits = NumberOfPropsBits::NextField<uint32_t,
OFFSET_MAX_OBJECT_SIZE_IN_WORDS_WITHOUT_INLINED>;
using ObjectSizeInWordsBits = InlinedPropsStartBits::NextField<uint32_t, OFFSET_MAX_OBJECT_SIZE_IN_WORDS>;
using HasDeletePropertyBit = ObjectSizeInWordsBits::NextFlag;
using IsAllTaggedPropBit = HasDeletePropertyBit::NextFlag;
using BitField1LastBit = IsAllTaggedPropBit;
static_assert(BitField1LastBit::START_BIT + BitField1LastBit::SIZE <= sizeof(uint32_t) * BITS_PER_BYTE, "Invalid");
static JSHClass *Cast(const TaggedObject *object)
{
ASSERT(JSTaggedValue(object).IsJSHClass());
return static_cast<JSHClass *>(const_cast<TaggedObject *>(object));
}
inline size_t SizeFromJSHClass(TaggedObject *header);
inline bool HasReferenceField();
void Initialize(const JSThread *thread, uint32_t size, JSType type, uint32_t inlinedProps);
void Initialize(const JSThread *thread, uint32_t size, JSType type, uint32_t inlinedProps,
const JSHandle<JSTaggedValue> &layout);
static size_t GetCloneSize(JSHClass* jshclass);
static JSHandle<JSHClass> Clone(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
bool specificInlinedProps = false, uint32_t specificNumInlinedProps = 0);
static JSHandle<JSHClass> CloneWithNewSizeAndType(const JSThread *thread, const JSHandle<JSHClass> &jsHClass,
uint32_t newHClassSize, JSType type);
static JSHandle<JSHClass> CloneAndIncInlinedProperties(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
uint32_t expectedOfProperties);
static JSHandle<JSHClass> CloneWithoutInlinedProperties(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
static JSHandle<JSHClass> CloneWithElementsKind(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
const ElementsKind kind, bool isPrototype);
static void TransitionElementsToDictionary(const JSThread *thread, const JSHandle<JSObject> &obj);
#if ENABLE_V70_OPTIMIZATION
static void TransitionElementsToDictionaryOnly(const JSThread *thread, const JSHandle<JSObject> &obj);
#endif
static void OptimizeAsFastElements(const JSThread *thread, JSHandle<JSObject> obj);
static void OptimizeAsFastProperties(const JSThread *thread, const JSHandle<JSObject> &obj,
const std::vector<int> &indexArray = {}, bool isDictionary = false);
template<bool checkDuplicateKeys = false>
static JSHandle<JSHClass> SetPropertyOfObjHClass(const JSThread *thread, JSHandle<JSHClass> &jshclass,
const JSHandle<JSTaggedValue> &key,
const PropertyAttributes &attr,
const Representation &rep,
bool specificInlinedProps = false,
uint32_t specificNumInlinedProps = 0);
static void PUBLIC_API AddProperty(const JSThread *thread, const JSHandle<JSObject> &obj,
const JSHandle<JSTaggedValue> &key, const PropertyAttributes &attr,
const Representation &rep = Representation::NONE);
static void AddPropertyToNewHClassWithoutTransition(const JSThread *thread, JSHandle<JSHClass> &newJsHClass,
const JSHandle<JSTaggedValue> &key,
const PropertyAttributes &attr);
static inline void AddInlinedPropToHClass(const JSThread *thread, const PropertyDescriptor &desc, size_t attrOffset,
const JSHandle<JSTaggedValue> &key, JSHandle<JSHClass> &hClass);
static void ProcessAotHClassTransition(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
const JSHandle<JSHClass> newHClass, const JSTaggedValue &key);
inline static void RestoreElementsKindToGeneric(JSHClass *newJsHClass);
static JSHandle<JSHClass> TransitionExtension(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
static void ReBuildFunctionInheritanceRelationship(const JSThread *thread,
const JSHandle<JSTaggedValue> &proto,
const JSHandle<JSTaggedValue> &baseIhc,
const JSHandle<JSTaggedValue> &transIhc,
const JSHandle<JSTaggedValue> &transPhc);
static JSHandle<JSHClass> TransitionProto(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
const JSHandle<JSTaggedValue> &proto, bool isChangeProto = false);
static JSHClass *FindTransitionProtoForAOT(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
const JSHandle<JSTaggedValue> &proto);
static JSHandle<JSHClass> TransProtoWithoutLayout(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
const JSHandle<JSTaggedValue> &proto);
static JSHandle<JSHClass> CloneWithAddProto(const JSThread *thread, const JSHandle<JSHClass> &jshclass,
const JSHandle<JSTaggedValue> &key,
const JSHandle<JSTaggedValue> &proto);
static void TransitionToDictionary(const JSThread *thread, const JSHandle<JSObject> &obj);
static void TransitionForRepChange(const JSThread *thread, const JSHandle<JSObject> &receiver,
const JSHandle<JSTaggedValue> &key, PropertyAttributes attr);
static void TransitionForElementsKindChange(const JSThread *thread, const JSHandle<JSObject> &receiver,
const ElementsKind newKind);
static bool IsInitialArrayHClassWithElementsKind(const JSThread *thread, const JSHClass *targetHClass,
const ElementsKind targetKind);
static bool PUBLIC_API TransitToElementsKindUncheck(const JSThread *thread, const JSHandle<JSObject> &obj,
ElementsKind newKind);
static void PUBLIC_API TransitToElementsKind(const JSThread *thread, const JSHandle<JSArray> &array,
ElementsKind newKind = ElementsKind::NONE);
static bool PUBLIC_API TransitToElementsKind(const JSThread *thread, const JSHandle<JSObject> &object,
const JSHandle<JSTaggedValue> &value,
ElementsKind kind = ElementsKind::NONE);
static TransitionResult PUBLIC_API ConvertOrTransitionWithRep(const JSThread *thread,
const JSHandle<JSObject> &receiver, const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
PropertyAttributes &attr);
static void PUBLIC_API MergeRepresentation(const JSThread *thread, JSHClass *oldJsHClass, JSHClass *newJsHClass);
static void UpdateFieldType(const JSThread *thread, JSHClass *hclass, const PropertyAttributes &attr);
static JSHClass *FindFieldOwnHClass(const JSThread *thread, JSHClass *hclass, const PropertyAttributes &attr);
static void VisitAndUpdateLayout(const JSThread *thread, JSHClass *ownHClass, const PropertyAttributes &attr);
static void VisitTransitionAndUpdateObjSize(const JSThread *thread, JSHClass *ownHClass,
uint32_t finalInObjPropsNum);
static uint32_t VisitTransitionAndFindMaxNumOfProps(const JSThread *thread, JSHClass *ownHClass);
static void NotifyHClassNotPrototypeChanged(JSThread *thread, const JSHandle<JSHClass> &jsHClass);
static void NotifyLeafHClassChanged(JSThread *thread, const JSHandle<JSHClass> &jsHClass);
static JSHandle<JSTaggedValue> PUBLIC_API EnableProtoChangeMarker(
const JSThread *thread, const JSHandle<JSHClass> &jshclass);
static JSHandle<JSTaggedValue> EnablePHCProtoChangeMarker(
const JSThread *thread, const JSHandle<JSHClass> &protoClass);
static void NotifyHclassChanged(const JSThread *thread, JSHandle<JSHClass> oldHclass, JSHandle<JSHClass> newHclass);
static void NotifyHClassChangedForAot(const JSThread *thread, const JSHandle<JSHClass> oldHclass,
const JSHandle<JSHClass> newHclass);
static void NotifyAccessorChanged(const JSThread *thread, JSHandle<JSHClass> hclass);
static void RegisterOnProtoChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
static bool UnregisterOnProtoChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
static JSHandle<ProtoChangeDetails> GetProtoChangeDetails(const JSThread *thread,
const JSHandle<JSHClass> &jshclass);
static JSHandle<ProtoChangeDetails> GetProtoChangeDetails(const JSThread *thread, const JSHandle<JSObject> &obj);
static JSHandle<TaggedArray> GetEnumCacheOwnWithOutCheck(const JSThread *thread,
const JSHandle<JSHClass> &jshclass);
inline void UpdatePropertyMetaData(const JSThread *thread, const JSTaggedValue &key,
const PropertyAttributes &metaData);
template<bool isForAot>
static void MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
template<bool isForAot = false>
static void NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass);
static void RefreshUsers(const JSThread *thread, const JSHandle<JSHClass> &oldHclass,
const JSHandle<JSHClass> &newHclass);
static bool IsNeedNotifyHclassChangedForAotTransition(const JSThread *thread, const JSHandle<JSHClass> &hclass,
JSTaggedValue key);
static JSHandle<JSTaggedValue> ParseKeyFromPGOCString(ObjectFactory* factory,
const CString& key,
const PGOHandler& handler);
static CString GetJSTypeDesc(JSType type);
inline void ClearBitField()
{
SetBitField(0UL);
SetBitField1(0UL);
SetBitField2(0ULL);
}
inline JSType GetObjectType() const
{
uint32_t bits = GetBitField();
return ObjectTypeBits::Decode(bits);
}
inline void SetObjectType(JSType type)
{
uint32_t bits = GetBitField();
uint32_t newVal = ObjectTypeBits::Update(bits, type);
SetBitField(newVal);
}
inline void SetCallable(bool flag)
{
CallableBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetConstructor(bool flag) const
{
ConstructorBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetExtensible(bool flag) const
{
ExtensibleBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetIsPrototype(bool flag) const
{
IsPrototypeBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetClassConstructor(bool flag) const
{
IsClassConstructorOrPrototypeBit::Set<uint32_t>(flag, GetBitFieldAddr());
SetConstructor(flag);
}
inline void SetClassPrototype(bool flag) const
{
IsClassConstructorOrPrototypeBit::Set<uint32_t>(flag, GetBitFieldAddr());
SetIsPrototype(flag);
}
inline void SetIsNativeBindingObject(bool flag) const
{
IsNativeBindingObjectBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetIsDictionaryMode(bool flag) const
{
SetIsStable(!flag);
IsDictionaryBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetIsJSArrayPrototypeModified(bool flag) const
{
IsJSArrayPrototypeModifiedBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetAOT(bool flag) const
{
IsAOTBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetIsJSFunction(bool flag) const
{
IsJSFunctionBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetIsOnHeap(bool flag) const
{
IsOnHeap::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline void SetIsStable(bool flag) const
{
IsStableBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
inline bool IsStable() const
{
uint32_t bits = GetBitField();
return IsStableBit::Decode(bits);
}
inline bool IsJSObject() const
{
return IsJSTypeObject(GetObjectType());
}
inline bool IsOnlyJSObject() const
{
JSType type = GetObjectType();
return type == JSType::JS_OBJECT || type == JSType::JS_WRAPPED_NAPI_OBJECT;
}
inline bool IsECMAObject() const
{
JSType jsType = GetObjectType();
return (JSType::ECMA_OBJECT_FIRST <= jsType && jsType <= JSType::ECMA_OBJECT_LAST);
}
inline bool IsJSWrappedNapiObject() const
{
JSType jsType = GetObjectType();
return (jsType == JSType::JS_WRAPPED_NAPI_OBJECT || jsType == JSType::JS_XREF_OBJECT);
}
inline bool ShouldSetDefaultSupers() const
{
return IsECMAObject() || IsStringOrSymbol();
}
inline bool IsRealm() const
{
return GetObjectType() == JSType::JS_REALM;
}
inline bool IsHClass() const
{
return GetObjectType() == JSType::HCLASS;
}
inline bool IsCompositeHClass() const
{
EcmaStringType jsType = static_cast<EcmaStringType>(GetObjectType());
return (EcmaStringType::FIRST_OBJECT_TYPE <= jsType && jsType <= EcmaStringType::LAST_OBJECT_TYPE);
}
inline bool IsString() const
{
JSType jsType = GetObjectType();
return (JSType::STRING_FIRST <= jsType && jsType <= JSType::STRING_LAST);
}
inline bool IsLineString() const
{
return GetObjectType() == JSType::LINE_STRING;
}
inline bool IsSlicedString() const
{
return GetObjectType() == JSType::SLICED_STRING;
}
inline bool IsTreeString() const
{
return GetObjectType() == JSType::TREE_STRING;
}
inline bool IsCachedExternalString() const
{
return GetObjectType() == JSType::CACHED_EXTERNAL_STRING;
}
inline bool IsBigInt() const
{
return GetObjectType() == JSType::BIGINT;
}
inline bool IsSymbol() const
{
return GetObjectType() == JSType::SYMBOL;
}
inline bool IsStringOrSymbol() const
{
JSType jsType = GetObjectType();
return (JSType::STRING_FIRST <= jsType && jsType <= JSType::STRING_LAST) || (jsType == JSType::SYMBOL);
}
inline bool IsTaggedArray() const
{
JSType jsType = GetObjectType();
switch (jsType) {
case JSType::TAGGED_ARRAY:
case JSType::TAGGED_DICTIONARY:
case JSType::LEXICAL_ENV:
case JSType::WEAK_LINKED_HASH_MAP:
case JSType::SFUNCTION_ENV:
case JSType::SENDABLE_ENV:
case JSType::CONSTANT_POOL:
case JSType::IC_INFO:
case JSType::AOT_LITERAL_INFO:
case JSType::VTABLE:
case JSType::COW_TAGGED_ARRAY:
case JSType::MUTANT_TAGGED_ARRAY:
case JSType::COW_MUTANT_TAGGED_ARRAY:
return true;
default:
return false;
}
}
inline bool IsLexicalEnv() const
{
return GetObjectType() == JSType::LEXICAL_ENV;
}
inline bool IsWeakLinkedHashMap() const
{
return GetObjectType() == JSType::WEAK_LINKED_HASH_MAP;
}
inline bool IsSFunctionEnv() const
{
return GetObjectType() == JSType::SFUNCTION_ENV;
}
inline bool IsByteArray() const
{
return GetObjectType() == JSType::BYTE_ARRAY;
}
inline bool IsConstantPool() const
{
return GetObjectType() == JSType::CONSTANT_POOL;
}
inline bool IsDictionary() const
{
return GetObjectType() == JSType::TAGGED_DICTIONARY;
}
inline bool IsCOWArray() const
{
return GetObjectType() == JSType::COW_TAGGED_ARRAY ||
GetObjectType() == JSType::COW_MUTANT_TAGGED_ARRAY;
}
inline bool IsMutantTaggedArray() const
{
return GetObjectType() == JSType::MUTANT_TAGGED_ARRAY ||
GetObjectType() == JSType::COW_MUTANT_TAGGED_ARRAY;
}
inline bool IsJSNativePointer() const
{
return GetObjectType() == JSType::JS_NATIVE_POINTER;
}
inline bool IsJSSymbol() const
{
return GetObjectType() == JSType::SYMBOL;
}
inline bool IsJSArray() const
{
return GetObjectType() == JSType::JS_ARRAY;
}
inline bool IsTypedArray() const
{
JSType jsType = GetObjectType();
return (JSType::JS_TYPED_ARRAY_FIRST < jsType && jsType <= JSType::JS_TYPED_ARRAY_LAST);
}
inline bool IsSharedTypedArray() const
{
JSType jsType = GetObjectType();
return (JSType::JS_SHARED_TYPED_ARRAY_FIRST < jsType && jsType <= JSType::JS_SHARED_TYPED_ARRAY_LAST);
}
inline bool HasOrdinaryGet() const
{
return (IsSpecialContainer() || IsModuleNamespace() || IsBigInt64Array());
}
inline bool HasDependentInfos(const JSThread *thread) const
{
return GetDependentInfos(thread) != JSTaggedValue::Undefined();
}
inline bool IsJSTypedArray() const
{
return GetObjectType() == JSType::JS_TYPED_ARRAY;
}
inline bool IsJSInt8Array() const
{
return GetObjectType() == JSType::JS_INT8_ARRAY;
}
inline bool IsJSUint8Array() const
{
return GetObjectType() == JSType::JS_UINT8_ARRAY;
}
inline bool IsJSUint8ClampedArray() const
{
return GetObjectType() == JSType::JS_UINT8_CLAMPED_ARRAY;
}
inline bool IsJSInt16Array() const
{
return GetObjectType() == JSType::JS_INT16_ARRAY;
}
inline bool IsJSUint16Array() const
{
return GetObjectType() == JSType::JS_UINT16_ARRAY;
}
inline bool IsJSInt32Array() const
{
return GetObjectType() == JSType::JS_INT32_ARRAY;
}
inline bool IsJSUint32Array() const
{
return GetObjectType() == JSType::JS_UINT32_ARRAY;
}
inline bool IsJSFloat32Array() const
{
return GetObjectType() == JSType::JS_FLOAT32_ARRAY;
}
inline bool IsJSFloat64Array() const
{
return GetObjectType() == JSType::JS_FLOAT64_ARRAY;
}
inline bool IsJSBigInt64Array() const
{
return GetObjectType() == JSType::JS_BIGINT64_ARRAY;
}
inline bool IsJSBigUint64Array() const
{
return GetObjectType() == JSType::JS_BIGUINT64_ARRAY;
}
inline bool IsJSSharedTypedArray() const
{
return GetObjectType() == JSType::JS_SHARED_TYPED_ARRAY;
}
inline bool IsJSSharedInt8Array() const
{
return GetObjectType() == JSType::JS_SHARED_INT8_ARRAY;
}
inline bool IsJSSharedUint8Array() const
{
return GetObjectType() == JSType::JS_SHARED_UINT8_ARRAY;
}
inline bool IsJSSharedUint8ClampedArray() const
{
return GetObjectType() == JSType::JS_SHARED_UINT8_CLAMPED_ARRAY;
}
inline bool IsJSSharedInt16Array() const
{
return GetObjectType() == JSType::JS_SHARED_INT16_ARRAY;
}
inline bool IsJSSharedUint16Array() const
{
return GetObjectType() == JSType::JS_SHARED_UINT16_ARRAY;
}
inline bool IsJSSharedInt32Array() const
{
return GetObjectType() == JSType::JS_SHARED_INT32_ARRAY;
}
inline bool IsJSSharedUint32Array() const
{
return GetObjectType() == JSType::JS_SHARED_UINT32_ARRAY;
}
inline bool IsJSSharedFloat32Array() const
{
return GetObjectType() == JSType::JS_SHARED_FLOAT32_ARRAY;
}
inline bool IsJSSharedFloat64Array() const
{
return GetObjectType() == JSType::JS_SHARED_FLOAT64_ARRAY;
}
inline bool IsJSSharedBigInt64Array() const
{
return GetObjectType() == JSType::JS_SHARED_BIGINT64_ARRAY;
}
inline bool IsJSSharedBigUint64Array() const
{
return GetObjectType() == JSType::JS_SHARED_BIGUINT64_ARRAY;
}
inline bool IsBigInt64Array() const
{
JSType jsType = GetObjectType();
return jsType == JSType::JS_SHARED_BIGUINT64_ARRAY || jsType == JSType::JS_SHARED_BIGINT64_ARRAY ||
jsType == JSType::JS_BIGUINT64_ARRAY || jsType == JSType::JS_BIGINT64_ARRAY;
}
inline bool IsJsGlobalEnv() const
{
return GetObjectType() == JSType::GLOBAL_ENV;
}
inline bool IsJSFunctionBase() const
{
JSType jsType = GetObjectType();
return jsType >= JSType::JS_FUNCTION_BASE && jsType <= JSType::JS_BOUND_FUNCTION;
}
inline bool IsJsBoundFunction() const
{
return GetObjectType() == JSType::JS_BOUND_FUNCTION;
}
inline bool IsJSIntlBoundFunction() const
{
return GetObjectType() == JSType::JS_INTL_BOUND_FUNCTION;
}
inline bool IsJSProxyRevocFunction() const
{
return GetObjectType() == JSType::JS_PROXY_REVOC_FUNCTION;
}
inline bool IsJSAsyncFunction() const
{
return GetObjectType() == JSType::JS_ASYNC_FUNCTION || GetObjectType() == JSType::JS_SHARED_ASYNC_FUNCTION;
}
inline bool IsJSSharedAsyncFunction() const
{
return GetObjectType() == JSType::JS_SHARED_ASYNC_FUNCTION;
}
inline bool IsJSAsyncAwaitStatusFunction() const
{
return GetObjectType() == JSType::JS_ASYNC_AWAIT_STATUS_FUNCTION;
}
inline bool IsJSPromiseReactionFunction() const
{
return GetObjectType() == JSType::JS_PROMISE_REACTIONS_FUNCTION;
}
inline bool IsJSPromiseExecutorFunction() const
{
return GetObjectType() == JSType::JS_PROMISE_EXECUTOR_FUNCTION;
}
inline bool IsJSAsyncModuleFulfilledFunction() const
{
return GetObjectType() == JSType::JS_ASYNC_MODULE_FULFILLED_FUNCTION;
}
inline bool IsJSAsyncModuleRejectedFunction() const
{
return GetObjectType() == JSType::JS_ASYNC_MODULE_REJECTED_FUNCTION;
}
inline bool IsJSAsyncFromSyncIterUnwarpFunction() const
{
return GetObjectType() == JSType::JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION;
}
inline bool IsJSPromiseAllResolveElementFunction() const
{
return GetObjectType() == JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION;
}
inline bool IsJSAsyncGeneratorResNextRetProRstFtn() const
{
return GetObjectType() == JSType::JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN;
}
inline bool IsJSPromiseAnyRejectElementFunction() const
{
return GetObjectType() == JSType::JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION;
}
inline bool IsJSPromiseAllSettledElementFunction() const
{
return GetObjectType() == JSType::JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION;
}
inline bool IsJSPromiseFinallyFunction() const
{
return GetObjectType() == JSType::JS_PROMISE_FINALLY_FUNCTION;
}
inline bool IsJSPromiseValueThunkOrThrowerFunction() const
{
return GetObjectType() == JSType::JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION;
}
inline bool IsMicroJobQueue() const
{
return GetObjectType() == JSType::MICRO_JOB_QUEUE;
}
inline bool IsPendingJob() const
{
return GetObjectType() == JSType::PENDING_JOB;
}
inline bool IsJsPrimitiveRef() const
{
return GetObjectType() == JSType::JS_PRIMITIVE_REF;
}
bool IsJSSet() const
{
return GetObjectType() == JSType::JS_SET;
}
bool IsJSSharedSet() const
{
return GetObjectType() == JSType::JS_SHARED_SET;
}
bool IsJSMap() const
{
return GetObjectType() == JSType::JS_MAP;
}
bool IsJSSharedMap() const
{
return GetObjectType() == JSType::JS_SHARED_MAP;
}
bool IsJSWeakMap() const
{
return GetObjectType() == JSType::JS_WEAK_MAP;
}
bool IsJSWeakSet() const
{
return GetObjectType() == JSType::JS_WEAK_SET;
}
bool IsJSWeakRef() const
{
return GetObjectType() == JSType::JS_WEAK_REF;
}
bool IsJSFinalizationRegistry() const
{
return GetObjectType() == JSType::JS_FINALIZATION_REGISTRY;
}
bool IsJSFunction() const
{
return GetObjectType() >= JSType::JS_FUNCTION_FIRST && GetObjectType() <= JSType::JS_FUNCTION_LAST;
}
bool IsJSApiFunction() const
{
return GetObjectType() == JSType::JS_API_FUNCTION;
}
bool IsJSSharedFunction() const
{
return GetObjectType() == JSType::JS_SHARED_FUNCTION;
}
bool IsInSharedHeap() const
{
return IsJSShared();
}
bool IsJSShared() const
{
uint32_t bits = GetBitField();
return IsJSSharedBit::Decode(bits);
}
inline void SetIsJSShared(bool flag) const
{
IsJSSharedBit::Set<uint32_t>(flag, GetBitFieldAddr());
}
static constexpr uint64_t PGO_PROFILE_TYPE_MASK = ((1ULL << pgo::PGO_PROFILE_TYPE_USED_BITS) - 1);
static constexpr uint64_t BIT_FIELD2_RESERVED_MASK = (~PGO_PROFILE_TYPE_MASK);
using HasSymbolPropertiesBit = BitField<uint64_t, pgo::PGO_PROFILE_TYPE_USED_BITS, 1>;
using MayHaveInterestingPropertiesBit = HasSymbolPropertiesBit::NextFlag;
static_assert(MayHaveInterestingPropertiesBit::END_BIT <= sizeof(uint64_t) * BITS_PER_BYTE,
"Optimized flags overflow into uint64_t");
inline uint64_t GetPGOProfileType() const
{
return GetBitField2() & PGO_PROFILE_TYPE_MASK;
}
inline void SetPGOProfileType(uint64_t pgoType)
{
uint64_t optimizationBits = GetBitField2() & BIT_FIELD2_RESERVED_MASK;
SetBitField2((pgoType & PGO_PROFILE_TYPE_MASK) | optimizationBits);
}
inline void ClearPGOProfileType()
{
uint64_t optimizationBits = GetBitField2() & BIT_FIELD2_RESERVED_MASK;
SetBitField2(optimizationBits);
}
inline bool PGOProfileTypeIsNone() const
{
return (GetBitField2() & PGO_PROFILE_TYPE_MASK) == 0;
}
inline void SetMayHaveInterestingProperties(bool flag)
{
uint64_t type = GetBitField2();
type = MayHaveInterestingPropertiesBit::Update(type, flag);
SetBitField2(type);
}
inline bool MayHaveInterestingProperties() const
{
return MayHaveInterestingPropertiesBit::Decode(GetBitField2());
}
inline void SetHasSymbolProperties(bool flag)
{
uint64_t type = GetBitField2();
type = HasSymbolPropertiesBit::Update(type, flag);
SetBitField2(type);
if (flag) {
SetMayHaveInterestingProperties(true);
}
}
inline bool HasSymbolProperties() const
{
return HasSymbolPropertiesBit::Decode(GetBitField2());
}
inline bool IsJSError() const
{
JSType jsType = GetObjectType();
return jsType >= JSType::JS_ERROR_FIRST && jsType <= JSType::JS_ERROR_LAST;
}
inline bool IsArguments() const
{
return GetObjectType() == JSType::JS_ARGUMENTS;
}
inline bool IsDate() const
{
return GetObjectType() == JSType::JS_DATE;
}
inline bool IsJSRegExp() const
{
return GetObjectType() == JSType::JS_REG_EXP;
}
inline bool IsJSProxy() const
{
return GetObjectType() == JSType::JS_PROXY;
}
inline bool IsJSLocale() const
{
return GetObjectType() == JSType::JS_LOCALE;
}
inline bool IsJSIntl() const
{
return GetObjectType() == JSType::JS_INTL;
}
inline bool IsJSDateTimeFormat() const
{
return GetObjectType() == JSType::JS_DATE_TIME_FORMAT;
}
inline bool IsJSRelativeTimeFormat() const
{
return GetObjectType() == JSType::JS_RELATIVE_TIME_FORMAT;
}
inline bool IsJSNumberFormat() const
{
return GetObjectType() == JSType::JS_NUMBER_FORMAT;
}
inline bool IsJSCollator() const
{
return GetObjectType() == JSType::JS_COLLATOR;
}
inline bool IsJSPluralRules() const
{
return GetObjectType() == JSType::JS_PLURAL_RULES;
}
inline bool IsJSDisplayNames() const
{
return GetObjectType() == JSType::JS_DISPLAYNAMES;
}
inline bool IsJSSegmenter() const
{
return GetObjectType() == JSType::JS_SEGMENTER;
}
inline bool IsJSSegments() const
{
return GetObjectType() == JSType::JS_SEGMENTS;
}
inline bool IsJSSegmentIterator() const
{
return GetObjectType() == JSType::JS_SEGMENT_ITERATOR;
}
inline bool IsJSListFormat() const
{
return GetObjectType() == JSType::JS_LIST_FORMAT;
}
inline bool IsMethod() const
{
return GetObjectType() == JSType::METHOD;
}
inline bool IsClassLiteral() const
{
return GetObjectType() == JSType::CLASS_LITERAL;
}
inline bool IsSpecialContainer() const
{
return GetObjectType() >= JSType::JS_API_ARRAY_LIST && GetObjectType() <= JSType::JS_API_QUEUE;
}
inline bool IsRegularObject() const
{
return GetObjectType() < JSType::JS_API_ARRAY_LIST && GetObjectType() > JSType::STRING_LAST;
}
inline bool IsJSAPIArrayList() const
{
return GetObjectType() == JSType::JS_API_ARRAY_LIST;
}
inline bool IsJSAPIArrayListIterator() const
{
return GetObjectType() == JSType::JS_API_ARRAYLIST_ITERATOR;
}
inline bool IsJSAPILightWeightMap() const
{
return GetObjectType() == JSType::JS_API_LIGHT_WEIGHT_MAP;
}
inline bool IsJSAPILightWeightMapIterator() const
{
return GetObjectType() == JSType::JS_API_LIGHT_WEIGHT_MAP_ITERATOR;
}
inline bool IsJSAPILightWeightSet() const
{
return GetObjectType() == JSType::JS_API_LIGHT_WEIGHT_SET;
}
inline bool IsJSAPILightWeightSetIterator() const
{
return GetObjectType() == JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR;
}
inline bool IsJSAPIStack() const
{
return GetObjectType() == JSType::JS_API_STACK;
}
inline bool IsJSAPIDeque() const
{
return GetObjectType() == JSType::JS_API_DEQUE;
}
inline bool IsLinkedNode() const
{
return GetObjectType() == JSType::LINKED_NODE;
}
inline bool IsRBTreeNode() const
{
return GetObjectType() == JSType::RB_TREENODE;
}
inline bool IsJSAPIHashMap() const
{
return GetObjectType() == JSType::JS_API_HASH_MAP;
}
inline bool IsJSAPIHashSet() const
{
return GetObjectType() == JSType::JS_API_HASH_SET;
}
inline bool IsJSAPIHashMapIterator() const
{
return GetObjectType() == JSType::JS_API_HASHMAP_ITERATOR;
}
inline bool IsJSAPIHashSetIterator() const
{
return GetObjectType() == JSType::JS_API_HASHSET_ITERATOR;
}
inline bool IsJSAPIQueue() const
{
return GetObjectType() == JSType::JS_API_QUEUE;
}
inline bool IsJSAPIPlainArray() const
{
return GetObjectType() == JSType::JS_API_PLAIN_ARRAY;
}
inline bool IsJSAPIQueueIterator() const
{
return GetObjectType() == JSType::JS_API_QUEUE_ITERATOR;
}
inline bool IsJSAPIList() const
{
return GetObjectType() == JSType::JS_API_LIST;
}
inline bool IsJSAPILinkedList() const
{
return GetObjectType() == JSType::JS_API_LINKED_LIST;
}
inline bool IsJSAPITreeMap() const
{
return GetObjectType() == JSType::JS_API_TREE_MAP;
}
inline bool IsJSAPITreeSet() const
{
return GetObjectType() == JSType::JS_API_TREE_SET;
}
inline bool IsJSAPITreeMapIterator() const
{
return GetObjectType() == JSType::JS_API_TREEMAP_ITERATOR;
}
inline bool IsJSAPITreeSetIterator() const
{
return GetObjectType() == JSType::JS_API_TREESET_ITERATOR;
}
inline bool IsJSAPIVector() const
{
return GetObjectType() == JSType::JS_API_VECTOR;
}
inline bool IsJSAPIVectorIterator() const
{
return GetObjectType() == JSType::JS_API_VECTOR_ITERATOR;
}
inline bool IsJSAPIBitVector() const
{
return GetObjectType() == JSType::JS_API_BITVECTOR;
}
inline bool IsJSAPIBitVectorIterator() const
{
return GetObjectType() == JSType::JS_API_BITVECTOR_ITERATOR;
}
inline bool IsJSAPIBuffer() const
{
return GetObjectType() == JSType::JS_API_FAST_BUFFER;
}
inline bool IsAccessorData() const
{
return GetObjectType() == JSType::ACCESSOR_DATA;
}
inline bool IsInternalAccessor() const
{
return GetObjectType() == JSType::INTERNAL_ACCESSOR;
}
inline bool IsIterator() const
{
JSType jsType = GetObjectType();
return jsType >= JSType::JS_ITERATOR_FIRST && jsType <= JSType::JS_ITERATOR_LAST;
}
inline bool IsAsyncIterator() const
{
return GetObjectType() == JSType::JS_ASYNCITERATOR;
}
inline bool IsAsyncFromSyncIterator() const
{
return GetObjectType() == JSType::JS_ASYNC_FROM_SYNC_ITERATOR;
}
inline bool IsForinIterator() const
{
return GetObjectType() == JSType::JS_FORIN_ITERATOR;
}
inline bool IsStringIterator() const
{
return GetObjectType() == JSType::JS_STRING_ITERATOR;
}
inline bool IsArrayBuffer() const
{
return GetObjectType() == JSType::JS_ARRAY_BUFFER;
}
inline bool IsSharedArrayBuffer() const
{
return GetObjectType() == JSType::JS_SHARED_ARRAY_BUFFER;
}
inline bool IsSendableArrayBuffer() const
{
return GetObjectType() == JSType::JS_SENDABLE_ARRAY_BUFFER;
}
inline bool IsDataView() const
{
return GetObjectType() == JSType::JS_DATA_VIEW;
}
inline bool IsJSSetIterator() const
{
return GetObjectType() == JSType::JS_SET_ITERATOR;
}
inline bool IsJSSharedSetIterator() const
{
return GetObjectType() == JSType::JS_SHARED_SET_ITERATOR;
}
inline bool IsJSRegExpIterator() const
{
return GetObjectType() == JSType::JS_REG_EXP_ITERATOR;
}
inline bool IsJSMapIterator() const
{
return GetObjectType() == JSType::JS_MAP_ITERATOR;
}
inline bool IsJSSharedMapIterator() const
{
return GetObjectType() == JSType::JS_SHARED_MAP_ITERATOR;
}
inline bool IsJSArrayIterator() const
{
return GetObjectType() == JSType::JS_ARRAY_ITERATOR;
}
inline bool IsJSSharedArrayIterator() const
{
return GetObjectType() == JSType::JS_SHARED_ARRAY_ITERATOR;
}
inline bool IsJSAPIPlainArrayIterator() const
{
return GetObjectType() == JSType::JS_API_PLAIN_ARRAY_ITERATOR;
}
inline bool IsJSAPIDequeIterator() const
{
return GetObjectType() == JSType::JS_API_DEQUE_ITERATOR;
}
inline bool IsJSAPIStackIterator() const
{
return GetObjectType() == JSType::JS_API_STACK_ITERATOR;
}
inline bool IsJSAPILinkedListIterator() const
{
return GetObjectType() == JSType::JS_API_LINKED_LIST_ITERATOR;
}
inline bool IsJSAPIListIterator() const
{
return GetObjectType() == JSType::JS_API_LIST_ITERATOR;
}
inline bool IsPrototypeHandler() const
{
return GetObjectType() == JSType::PROTOTYPE_HANDLER;
}
inline bool IsTransitionHandler() const
{
return GetObjectType() == JSType::TRANSITION_HANDLER;
}
inline bool IsTransWithProtoHandler() const
{
return GetObjectType() == JSType::TRANS_WITH_PROTO_HANDLER;
}
inline bool IsStoreAOTHandler() const
{
return GetObjectType() == JSType::STORE_TS_HANDLER;
}
inline bool IsPropertyBox() const
{
return GetObjectType() == JSType::PROPERTY_BOX;
}
inline bool IsEnumCache() const
{
return GetObjectType() == JSType::ENUM_CACHE;
}
inline bool IsProtoChangeMarker() const
{
return GetObjectType() == JSType::PROTO_CHANGE_MARKER;
}
inline bool IsMarkerCell() const
{
return GetObjectType() == JSType::MARKER_CELL;
}
inline bool IsTrackInfoObject() const
{
return GetObjectType() == JSType::TRACK_INFO;
}
inline bool IsProtoChangeDetails() const
{
return GetObjectType() == JSType::PROTOTYPE_INFO;
}
inline bool IsProgram() const
{
return GetObjectType() == JSType::PROGRAM;
}
inline bool IsClassInfoExtractor() const
{
return GetObjectType() == JSType::CLASS_INFO_EXTRACTOR;
}
inline bool IsCallable() const
{
uint32_t bits = GetBitField();
return CallableBit::Decode(bits);
}
inline bool IsConstructor() const
{
uint32_t bits = GetBitField();
return ConstructorBit::Decode(bits);
}
inline bool IsExtensible() const
{
uint32_t bits = GetBitField();
return ExtensibleBit::Decode(bits);
}
inline bool IsPrototype() const
{
uint32_t bits = GetBitField();
return IsPrototypeBit::Decode(bits);
}
inline bool IsClassConstructor() const
{
uint32_t bits = GetBitField();
return IsClassConstructorOrPrototypeBit::Decode(bits) && IsConstructor();
}
inline bool IsJSGlobalObject() const
{
return GetObjectType() == JSType::JS_GLOBAL_OBJECT;
}
inline bool IsClassPrototype() const
{
uint32_t bits = GetBitField();
return IsClassConstructorOrPrototypeBit::Decode(bits) && IsPrototype();
}
inline bool IsNativeBindingObject() const
{
uint32_t bits = GetBitField();
return IsNativeBindingObjectBit::Decode(bits);
}
inline bool IsDictionaryMode() const
{
uint32_t bits = GetBitField();
return IsDictionaryBit::Decode(bits);
}
inline bool IsJSArrayPrototypeModifiedFromBitField() const
{
uint32_t bits = GetBitField();
return IsJSArrayPrototypeModifiedBit::Decode(bits);
}
inline bool IsAOT() const
{
uint32_t bits = GetBitField();
return IsAOTBit::Decode(bits);
}
inline bool IsJSFunctionFromBitField() const
{
uint32_t bits = GetBitField();
return IsJSFunctionBit::Decode(bits);
}
inline bool IsOnHeapFromBitField() const
{
uint32_t bits = GetBitField();
return IsOnHeap::Decode(bits);
}
inline bool IsGeneratorFunction() const
{
return GetObjectType() == JSType::JS_GENERATOR_FUNCTION;
}
inline bool IsAsyncGeneratorFunction() const
{
return GetObjectType() == JSType::JS_ASYNC_GENERATOR_FUNCTION;
}
inline bool IsGeneratorObject() const
{
JSType jsType = GetObjectType();
return jsType == JSType::JS_GENERATOR_OBJECT || jsType == JSType::JS_ASYNC_FUNC_OBJECT;
}
inline bool IsAsyncGeneratorObject() const
{
JSType jsType = GetObjectType();
return jsType == JSType::JS_ASYNC_GENERATOR_OBJECT;
}
inline bool IsGeneratorContext() const
{
return GetObjectType() == JSType::JS_GENERATOR_CONTEXT;
}
inline bool IsAsyncGeneratorRequest() const
{
JSType jsType = GetObjectType();
return jsType == JSType::ASYNC_GENERATOR_REQUEST;
}
inline bool IsAsyncIteratorRecord() const
{
JSType jsType = GetObjectType();
return jsType == JSType::ASYNC_ITERATOR_RECORD;
}
inline bool IsAsyncFuncObject() const
{
return GetObjectType() == JSType::JS_ASYNC_FUNC_OBJECT;
}
inline bool IsJSPromise() const
{
return GetObjectType() == JSType::JS_PROMISE;
}
inline bool IsResolvingFunctionsRecord() const
{
return GetObjectType() == JSType::RESOLVING_FUNCTIONS_RECORD;
}
inline bool IsPromiseRecord() const
{
return GetObjectType() == JSType::PROMISE_RECORD;
}
inline bool IsPromiseIteratorRecord() const
{
return GetObjectType() == JSType::PROMISE_ITERATOR_RECORD;
}
inline bool IsPromiseCapability() const
{
return GetObjectType() == JSType::PROMISE_CAPABILITY;
}
inline bool IsPromiseReaction() const
{
return GetObjectType() == JSType::PROMISE_REACTIONS;
}
inline bool IsCellRecord() const
{
return GetObjectType() == JSType::CELL_RECORD;
}
inline bool IsCompletionRecord() const
{
return GetObjectType() == JSType::COMPLETION_RECORD;
}
inline bool IsRecord() const
{
JSType jsType = GetObjectType();
return jsType >= JSType::JS_RECORD_FIRST && jsType <= JSType::JS_RECORD_LAST;
}
inline bool IsTemplateMap() const
{
return GetObjectType() == JSType::TEMPLATE_MAP;
}
inline bool IsFreeObject() const
{
JSType t = GetObjectType();
return (t >= JSType::FREE_OBJECT_WITH_ONE_FIELD) && (t <= JSType::FREE_OBJECT_WITH_TWO_FIELD);
}
inline bool IsFreeObjectWithShortField() const
{
switch (GetObjectType()) {
case JSType::FREE_OBJECT_WITH_ONE_FIELD:
case JSType::FREE_OBJECT_WITH_NONE_FIELD:
return true;
default:
return false;
}
}
inline bool IsFreeObjectWithOneField() const
{
return GetObjectType() == JSType::FREE_OBJECT_WITH_ONE_FIELD;
}
inline bool IsFreeObjectWithNoneField() const
{
return GetObjectType() == JSType::FREE_OBJECT_WITH_NONE_FIELD;
}
inline bool IsFreeObjectWithTwoField() const
{
return GetObjectType() == JSType::FREE_OBJECT_WITH_TWO_FIELD;
}
inline bool IsMachineCodeObject() const
{
return GetObjectType() == JSType::MACHINE_CODE_OBJECT;
}
inline bool IsAOTLiteralInfo() const
{
return GetObjectType() == JSType::AOT_LITERAL_INFO;
}
inline bool IsExtraProfileTypeInfo() const
{
return GetObjectType() == JSType::EXTRA_PROFILE_TYPE_INFO;
}
inline bool IsICInfo() const
{
return GetObjectType() == JSType::IC_INFO;
}
inline bool IsProfileTypeInfo() const
{
return GetObjectType() == JSType::PROFILE_TYPE_INFO;
}
inline bool IsProfileTypeInfoCell() const
{
JSType jsType = GetObjectType();
return jsType >= JSType::PROFILE_TYPE_INFO_CELL_FIRST && jsType <= JSType::PROFILE_TYPE_INFO_CELL_LAST;
}
inline bool IsProfileTypeInfoCell0() const
{
JSType jsType = GetObjectType();
return jsType == JSType::PROFILE_TYPE_INFO_CELL_0;
}
inline bool IsFunctionTemplate() const
{
JSType jsType = GetObjectType();
return jsType == JSType::FUNCTION_TEMPLATE;
}
inline bool IsVTable() const
{
return GetObjectType() == JSType::VTABLE;
}
inline bool IsModuleRecord() const
{
JSType jsType = GetObjectType();
return jsType >= JSType::MODULE_RECORD_FIRST && jsType <= JSType::MODULE_RECORD_LAST;
}
inline bool IsSourceTextModule() const
{
return GetObjectType() == JSType::SOURCE_TEXT_MODULE_RECORD;
}
inline bool IsCjsExports() const
{
return GetObjectType() == JSType::JS_CJS_EXPORTS;
}
inline bool IsCjsModule() const
{
return GetObjectType() == JSType::JS_CJS_MODULE;
}
inline bool IsCjsRequire() const
{
return GetObjectType() == JSType::JS_CJS_REQUIRE;
}
inline bool IsImportEntry() const
{
return GetObjectType() == JSType::IMPORTENTRY_RECORD;
}
inline bool IsLocalExportEntry() const
{
return GetObjectType() == JSType::LOCAL_EXPORTENTRY_RECORD;
}
inline bool IsIndirectExportEntry() const
{
return GetObjectType() == JSType::INDIRECT_EXPORTENTRY_RECORD;
}
inline bool IsStarExportEntry() const
{
return GetObjectType() == JSType::STAR_EXPORTENTRY_RECORD;
}
inline bool IsResolvedBinding() const
{
return GetObjectType() == JSType::RESOLVEDBINDING_RECORD;
}
inline bool IsResolvedIndexBinding() const
{
return GetObjectType() == JSType::RESOLVEDINDEXBINDING_RECORD;
}
inline bool IsResolvedRecordIndexBinding() const
{
return GetObjectType() == JSType::RESOLVEDRECORDINDEXBINDING_RECORD;
}
inline bool IsResolvedRecordBinding() const
{
return GetObjectType() == JSType::RESOLVEDRECORDBINDING_RECORD;
}
inline bool IsModuleNamespace() const
{
return GetObjectType() == JSType::JS_MODULE_NAMESPACE;
}
inline bool IsNativeModuleFailureInfo() const
{
return GetObjectType() == JSType::NATIVE_MODULE_FAILURE_INFO;
}
inline bool IsJSSharedObject() const
{
return GetObjectType() == JSType::JS_SHARED_OBJECT;
}
inline bool IsJSSharedArray() const
{
return GetObjectType() == JSType::JS_SHARED_ARRAY;
}
inline void SetElementsKind(ElementsKind kind)
{
uint32_t bits = GetBitField();
uint32_t newVal = ElementsKindBits::Update(bits, kind);
SetBitField(newVal);
}
inline ElementsKind GetElementsKind() const
{
uint32_t bits = GetBitField();
return ElementsKindBits::Decode(bits);
}
inline void SetConstructionCounter(uint8_t count)
{
uint32_t bits = GetBitField();
uint32_t newVal = ConstructionCounterBits::Update(bits, count);
SetBitField(newVal);
}
inline uint8_t GetConstructionCounter() const
{
uint32_t bits = GetBitField();
return ConstructionCounterBits::Decode(bits);
}
inline void SetIsDictionaryElement(bool value)
{
uint32_t newVal = DictionaryElementBits::Update(GetBitField(), value);
SetBitField(newVal);
}
inline bool IsDictionaryElement() const
{
return DictionaryElementBits::Decode(GetBitField());
}
inline void SetIsStableElements(bool value)
{
uint32_t newVal = IsStableElementsBit::Update(GetBitField(), value);
SetBitField(newVal);
}
inline bool IsStableElements() const
{
return IsStableElementsBit::Decode(GetBitField());
}
inline bool IsStableJSArguments() const
{
uint32_t bits = GetBitField();
auto type = ObjectTypeBits::Decode(bits);
return IsStableElementsBit::Decode(bits) && (type == JSType::JS_ARGUMENTS);
}
inline bool IsStableJSArray() const
{
uint32_t bits = GetBitField();
auto type = ObjectTypeBits::Decode(bits);
return IsStableElementsBit::Decode(bits) && (type == JSType::JS_ARRAY);
}
inline void SetHasConstructor(bool value)
{
JSTaggedType newVal = HasConstructorBits::Update(GetBitField(), value);
SetBitField(newVal);
}
inline bool HasConstructor() const
{
return HasConstructorBits::Decode(GetBitField());
}
inline void SetNumberOfProps(uint32_t num)
{
uint32_t bits = GetBitField1();
uint32_t newVal = NumberOfPropsBits::Update(bits, num);
SetBitField1(newVal);
}
inline void IncNumberOfProps()
{
ASSERT(NumberOfProps() < PropertyAttributes::MAX_FAST_PROPS_CAPACITY);
SetNumberOfProps(NumberOfProps() + 1);
}
inline uint32_t NumberOfProps() const
{
uint32_t bits = GetBitField1();
return NumberOfPropsBits::Decode(bits);
}
inline bool HasProps() const
{
return NumberOfProps() > 0;
}
inline bool PropsIsEmpty() const
{
return NumberOfProps() == 0;
}
inline uint32_t LastPropIndex() const
{
ASSERT(NumberOfProps() > 0);
return NumberOfProps() - 1;
}
inline int32_t GetNextInlinedPropsIndex() const
{
uint32_t inlinedProperties = GetInlinedProperties();
uint32_t numberOfProps = NumberOfProps();
if (numberOfProps < inlinedProperties) {
return numberOfProps;
}
return -1;
}
inline int32_t GetNextNonInlinedPropsIndex() const
{
uint32_t inlinedProperties = GetInlinedProperties();
uint32_t numberOfProps = NumberOfProps();
if (numberOfProps >= inlinedProperties) {
return numberOfProps - inlinedProperties;
}
return -1;
}
inline int32_t IsNonInlinedPropExist() const
{
uint32_t inlinedProperties = GetInlinedProperties();
uint32_t numberOfProps = NumberOfProps();
return numberOfProps > inlinedProperties;
}
inline uint32_t GetObjectSize() const
{
uint32_t bits = GetBitField1();
return ObjectSizeInWordsBits::Decode(bits) * JSTaggedValue::TaggedTypeSize();
}
inline uint32_t GetObjectSizeExcludeInlinedProps() const
{
return GetObjectSize() - GetInlinedProperties() * JSTaggedValue::TaggedTypeSize();
}
inline void SetObjectSize(uint32_t num)
{
ASSERT((num / JSTaggedValue::TaggedTypeSize()) <= MAX_OBJECT_SIZE_IN_WORDS);
uint32_t bits = GetBitField1();
uint32_t newVal = ObjectSizeInWordsBits::Update(bits, num / JSTaggedValue::TaggedTypeSize());
SetBitField1(newVal);
}
inline uint32_t GetInlinedPropertiesOffset(uint32_t index) const
{
ASSERT(index < GetInlinedProperties());
return GetInlinedPropertiesIndex(index) * JSTaggedValue::TaggedTypeSize();
}
inline uint32_t GetInlinedPropertiesIndex(uint32_t index) const
{
ASSERT(index < GetInlinedProperties());
uint32_t bits = GetBitField1();
return InlinedPropsStartBits::Decode(bits) + index;
}
inline void SetInlinedPropsStart(uint32_t num)
{
uint32_t bits = GetBitField1();
uint32_t newVal = InlinedPropsStartBits::Update(bits, num / JSTaggedValue::TaggedTypeSize());
SetBitField1(newVal);
}
inline uint32_t GetInlinedPropsStartSize() const
{
uint32_t bits = GetBitField1();
return InlinedPropsStartBits::Decode(bits) * JSTaggedValue::TaggedTypeSize();
}
inline uint32_t GetInlinedProperties() const
{
if (IsJSObject()) {
uint32_t bits = GetBitField1();
return static_cast<uint32_t>(ObjectSizeInWordsBits::Decode(bits) - InlinedPropsStartBits::Decode(bits));
} else {
return 0;
}
}
inline void SetHasDeleteProperty(bool flag) const
{
HasDeletePropertyBit::Set<uint32_t>(flag, GetBitField1Addr());
}
inline bool HasDeleteProperty() const
{
uint32_t bits = GetBitField1();
return HasDeletePropertyBit::Decode(bits);
}
inline void SetIsAllTaggedProp(bool flag) const
{
IsAllTaggedPropBit::Set<uint32_t>(flag, GetBitField1Addr());
}
inline bool IsAllTaggedProp() const
{
uint32_t bits = GetBitField1();
return IsAllTaggedPropBit::Decode(bits);
}
inline bool IsObjSizeTrackingInProgress() const
{
return GetConstructionCounter() != 0;
}
inline void StartObjSizeTracking()
{
SetConstructionCounter(SLACK_TRACKING_COUNT);
}
inline void CompleteObjSizeTracking(const JSThread *thread);
inline void ObjSizeTrackingStep(const JSThread *thread);
inline static JSHClass *FindRootHClass(const JSThread *thread, JSHClass *hclass);
inline static JSTaggedValue FindProtoHClass(const JSThread *thread, JSHClass *hclass);
inline static JSTaggedValue FindProtoRootHClass(const JSThread *thread, JSHClass *hclass);
inline static void UpdateRootHClass(const JSThread *thread, const JSHandle<JSHClass> &parent,
const JSHandle<JSHClass> &child);
inline static int FindPropertyEntry(const JSThread *thread, JSHClass *hclass, JSTaggedValue key);
static PUBLIC_API PropertyLookupResult LookupPropertyInAotHClass(const JSThread *thread, JSHClass *hclass,
JSTaggedValue key);
static PUBLIC_API PropertyLookupResult LookupPropertyInPGOHClass(const JSThread *thread, JSHClass *hclass,
JSTaggedValue key);
static PUBLIC_API PropertyLookupResult LookupPropertyInBuiltinPrototypeHClass(const JSThread *thread,
JSHClass *hclass, JSTaggedValue key);
static PUBLIC_API PropertyLookupResult LookupPropertyInBuiltinHClass(const JSThread *thread, JSHClass *hclass,
JSTaggedValue key);
static constexpr size_t BIT_FIELD_OFFSET = TaggedObjectSize();
ACCESSORS_PRIMITIVE_FIELD(BitField, uint32_t, BIT_FIELD_OFFSET, BIT_FIELD1_OFFSET);
ACCESSORS_PRIMITIVE_FIELD(BitField1, uint32_t, BIT_FIELD1_OFFSET, PROTOTYPE_OFFSET);
ACCESSORS_DCHECK(Proto, PROTOTYPE_OFFSET, LAYOUT_OFFSET, IsString);
ACCESSORS_SYNCHRONIZED_DCHECK_WITH_RB_MODE(Layout, LAYOUT_OFFSET, TRANSTIONS_OFFSET, IsString);
ACCESSORS_DCHECK(Transitions, TRANSTIONS_OFFSET, PARENT_OFFSET, IsString);
ACCESSORS_DCHECK(Parent, PARENT_OFFSET, PROTO_CHANGE_MARKER_OFFSET, IsString);
ACCESSORS_DCHECK(ProtoChangeMarker, PROTO_CHANGE_MARKER_OFFSET, PROTO_CHANGE_DETAILS_OFFSET, IsString);
ACCESSORS_DCHECK(ProtoChangeDetails, PROTO_CHANGE_DETAILS_OFFSET, ENUM_CACHE_OFFSET, IsString);
ACCESSORS_DCHECK(EnumCache, ENUM_CACHE_OFFSET, DEPENDENT_INFOS_OFFSET, IsString);
ACCESSORS_DCHECK(DependentInfos, DEPENDENT_INFOS_OFFSET, BIT_FIELD2_OFFSET, IsString);
ACCESSORS_PRIMITIVE_FIELD_DCHECK(BitField2, uint64_t, BIT_FIELD2_OFFSET, LAST_OFFSET, IsString);
DEFINE_ALIGN_SIZE(LAST_OFFSET);
static_assert(CompositeBaseClass::SIZE >= SIZE,
"CompositeBaseClass::SIZE should be larger than JSHClass::SIZE");
static JSHandle<JSHClass> SetPrototypeWithNotification(const JSThread *thread,
const JSHandle<JSHClass> &hclass,
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto = false);
static void SetPrototypeTransition(JSThread *thread, const JSHandle<JSObject> &object,
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto = false);
static void SetPrototype(const JSThread *thread, const JSHandle<JSHClass> &hclass,
JSTaggedValue proto, bool isChangeProto = false);
static void SetPrototype(const JSThread *thread, const JSHandle<JSHClass> &hclass,
const JSHandle<GlobalEnv> &env, JSTaggedValue proto, bool isChangeProto = false);
static void PUBLIC_API SetPrototype(const JSThread *thread, const JSHandle<JSHClass> &hclass,
const JSHandle<JSTaggedValue> &proto, bool isChangeProto = false);
static void OptimizePrototypeForIC(const JSThread *thread, const JSHandle<GlobalEnv> &env,
const JSHandle<JSTaggedValue> &proto,
bool isChangeProto = false);
inline JSTaggedValue GetPrototype(const JSThread *thread) const
{
return GetProto(thread);
}
inline JSHClass *FindTransitions(const JSThread *thread,
const JSTaggedValue &key,
const JSTaggedValue &metaData,
const Representation &rep);
inline JSHClass *CheckHClassForRep(const JSThread *thread, JSHClass *hclass, const Representation &rep);
DECL_DUMP()
static CString DumpJSType(JSType type);
static JSHandle<JSHClass> CreateRootHClassFromPGO(const JSThread* thread,
const HClassLayoutDesc* desc,
uint32_t maxNum);
static JSHandle<JSHClass> CreateRootHClassWithCached(const JSThread* thread,
const HClassLayoutDesc* desc,
uint32_t literalLength,
uint32_t maxPropsNum);
static JSHandle<JSHClass> CreateChildHClassFromPGO(const JSThread* thread,
const JSHandle<JSHClass>& parent,
const HClassLayoutDesc* desc);
static bool DumpRootHClassByPGO(const JSThread *thread, const JSHClass* hclass, HClassLayoutDesc* desc);
static bool DumpChildHClassByPGO(const JSThread *thread, const JSHClass* hclass, HClassLayoutDesc* desc);
static bool UpdateRootLayoutDescByPGO(const JSThread* thread, const JSHClass* hclass, HClassLayoutDesc* rootDesc);
static bool UpdateChildLayoutDescByPGO(const JSThread* thread, const JSHClass* hclass, HClassLayoutDesc* childDesc);
static std::pair<bool, CString> DumpToString(const JSThread *thread, JSTaggedType hclassVal);
DECL_VISIT_OBJECT(PROTOTYPE_OFFSET, BIT_FIELD2_OFFSET);
inline JSHClass *FindProtoTransitions(const JSThread *thread, const JSTaggedValue &key,
const JSTaggedValue &proto);
inline bool HasTransitions(const JSThread *thread) const
{
return !GetTransitions(thread).IsUndefined();
}
static JSHandle<JSHClass> CreateSHClass(JSThread *thread,
const std::vector<PropertyDescriptor> &descs,
const JSHClass *parentHClass = nullptr,
bool isFunction = false);
static JSHandle<JSHClass> CreateSConstructorHClass(JSThread *thread, const std::vector<PropertyDescriptor> &descs);
static JSHandle<JSHClass> CreateSPrototypeHClass(JSThread *thread, const std::vector<PropertyDescriptor> &descs);
JSHCLASS_PUBLIC_HYBRID_EXTENSION()
private:
static inline bool ProtoIsFastJSArray(const JSHandle<GlobalEnv> &env,
const JSHandle<JSTaggedValue> proto, const JSHandle<JSHClass> hclass);
static void CreateSInlinedLayout(JSThread *thread,
const std::vector<PropertyDescriptor> &descs,
const JSHandle<JSHClass> &hclass,
const JSHClass *parentHClass = nullptr);
static void CreateSDictLayout(JSThread *thread,
const std::vector<PropertyDescriptor> &descs,
const JSHandle<JSHClass> &hclass,
const JSHClass *parentHClass = nullptr);
static inline void AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key,
PropertyAttributes attr);
static inline void AddExtensionTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key);
static inline void AddProtoTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key,
const JSHandle<JSTaggedValue> &proto);
template<bool checkDuplicateKeys = false>
static inline void AddPropertyToNewHClass(const JSThread *thread, JSHandle<JSHClass> &jshclass,
JSHandle<JSHClass> &newJsHClass, const JSHandle<JSTaggedValue> &key,
const PropertyAttributes &attr);
void InitializeWithDefaultValue(const JSThread *thread, uint32_t size, JSType type, uint32_t inlinedProps);
static bool IsJSTypeObject(JSType type)
{
return JSType::JS_OBJECT_FIRST <= type && type <= JSType::JS_OBJECT_LAST;
}
static bool IsJSTypeShared(JSType type);
static inline void Copy(const JSThread *thread, JSHandle<JSHClass> newHClass, JSHandle<JSHClass> oldHClass);
uint32_t *GetBitFieldAddr() const
{
return reinterpret_cast<uint32_t *>(ToUintPtr(this) + BIT_FIELD_OFFSET);
}
uint32_t *GetBitField1Addr() const
{
return reinterpret_cast<uint32_t *>(ToUintPtr(this) + BIT_FIELD1_OFFSET);
}
friend class RuntimeStubs;
};
static_assert(JSHClass::BIT_FIELD_OFFSET % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT) == 0);
class PropertyLookupResult {
public:
static constexpr uint32_t OFFSET_BITFIELD_NUM = 14;
using IsFoundBit = BitField<bool, 0, 1>;
using IsLocalBit = IsFoundBit::NextFlag;
using IsNotHoleBit = IsLocalBit::NextFlag;
using IsAccessorBit = IsNotHoleBit::NextFlag;
using OffsetBits = IsAccessorBit::NextField<uint32_t, OFFSET_BITFIELD_NUM>;
using WritableField = OffsetBits::NextFlag;
using RepresentationBits = WritableField::NextField<Representation, PropertyAttributes::REPRESENTATION_NUM>;
using IsInlinedPropsBits = RepresentationBits::NextFlag;
using IsLoadFromIterResultBit = IsInlinedPropsBits::NextFlag;
explicit PropertyLookupResult(uint32_t data = 0) : data_(data) {}
~PropertyLookupResult() = default;
DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyLookupResult);
DEFAULT_COPY_SEMANTIC(PropertyLookupResult);
inline bool IsFound() const
{
return IsFoundBit::Get(data_);
}
inline void SetIsFound(bool flag)
{
IsFoundBit::Set(flag, &data_);
}
inline bool IsWritable() const
{
return WritableField::Get(data_);
}
inline void SetIsWritable(bool flag)
{
WritableField::Set(flag, &data_);
}
inline bool IsLocal() const
{
return IsLocalBit::Get(data_);
}
inline void SetIsLocal(bool flag)
{
IsLocalBit::Set(flag, &data_);
}
inline bool IsNotHole() const
{
return IsNotHoleBit::Get(data_);
}
inline void SetIsNotHole(bool flag)
{
IsNotHoleBit::Set(flag, &data_);
}
inline bool IsVtable() const
{
return IsFound() && !IsLocal();
}
inline void SetIsVtable()
{
SetIsFound(true);
SetIsLocal(false);
}
inline bool IsAccessor() const
{
return IsAccessorBit::Get(data_);
}
inline void SetIsAccessor(bool flag)
{
IsAccessorBit::Set(flag, &data_);
}
inline bool IsFunction() const
{
return IsVtable() && !IsAccessor();
}
inline uint32_t GetOffset() const
{
return OffsetBits::Get(data_);
}
inline void SetOffset(uint32_t offset)
{
OffsetBits::Set<uint32_t>(offset, &data_);
}
inline void SetRepresentation(Representation rep)
{
RepresentationBits::Set(rep, &data_);
}
inline Representation GetRepresentation()
{
return RepresentationBits::Get(data_);
}
inline void SetIsInlinedProps(bool flag)
{
IsInlinedPropsBits::Set(flag, &data_);
}
inline bool IsInlinedProps()
{
return IsInlinedPropsBits::Get(data_);
}
inline void SetIsLoadFromIterResult(bool flag)
{
IsLoadFromIterResultBit::Set(flag, &data_);
}
inline bool IsLoadFromIterResult() const
{
return IsLoadFromIterResultBit::Get(data_);
}
inline uint32_t GetData() const
{
return data_;
}
private:
uint32_t data_ {0};
};
static_assert(PropertyLookupResult::OffsetBits::MaxValue() >
(PropertyAttributes::MAX_FAST_PROPS_CAPACITY * JSTaggedValue::TaggedTypeSize()));
}
#endif