From 57fb428a6b44692245141bd389bd4d8db779de66 Mon Sep 17 00:00:00 2001 From: hewei Date: Fri, 23 May 2025 09:16:57 +0800 Subject: [PATCH] Refactor circuit builder Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IC9ZF5 Signed-off-by: hewei Change-Id: Ice5bb53858da7afeaad57d931a15533193721ce3 --- ecmascript/compiler/async_function_lowering.h | 2 +- ecmascript/compiler/circuit_builder-inl.h | 27 +- ecmascript/compiler/hcr_circuit_builder.cpp | 53 ++++ ecmascript/compiler/hcr_circuit_builder.h | 218 +-------------- ecmascript/compiler/lcr_circuit_builder.cpp | 25 -- ecmascript/compiler/lcr_circuit_builder.h | 47 ++-- ecmascript/compiler/mcr_circuit_builder.cpp | 76 ++---- ecmascript/compiler/mcr_circuit_builder.h | 252 ++++++++++++++++++ ecmascript/compiler/mcr_lowering.cpp | 1 + .../compiler/number_speculative_lowering.h | 2 + .../compiler/number_speculative_retype.h | 1 + ecmascript/compiler/post_schedule.h | 1 + ecmascript/compiler/stub_builder.h | 3 + .../compiler/typed_bytecode_lowering.cpp | 1 + ecmascript/compiler/typed_hcr_lowering.cpp | 1 + .../compiler/typed_native_inline_lowering.cpp | 1 + 16 files changed, 367 insertions(+), 344 deletions(-) diff --git a/ecmascript/compiler/async_function_lowering.h b/ecmascript/compiler/async_function_lowering.h index 860b9f25f2..64446cdec9 100644 --- a/ecmascript/compiler/async_function_lowering.h +++ b/ecmascript/compiler/async_function_lowering.h @@ -18,8 +18,8 @@ #include "ecmascript/compiler/bytecode_circuit_builder.h" #include "ecmascript/compiler/circuit.h" -#include "ecmascript/compiler/circuit_builder-inl.h" #include "ecmascript/compiler/circuit_builder.h" +#include "ecmascript/compiler/lcr_circuit_builder.h" #include "ecmascript/mem/chunk_containers.h" namespace panda::ecmascript::kungfu { diff --git a/ecmascript/compiler/circuit_builder-inl.h b/ecmascript/compiler/circuit_builder-inl.h index 12d75ab3b0..dc10fcbad9 100644 --- a/ecmascript/compiler/circuit_builder-inl.h +++ b/ecmascript/compiler/circuit_builder-inl.h @@ -15,10 +15,8 @@ #ifndef ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H #define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H -#include "ecmascript/compiler/lcr_circuit_builder.h" -#include "ecmascript/compiler/mcr_circuit_builder.h" -#include "ecmascript/compiler/hcr_circuit_builder.h" #include "ecmascript/compiler/circuit_builder.h" +#include "ecmascript/compiler/circuit_builder_helper.h" #include "ecmascript/mem/region.h" #include "ecmascript/method.h" @@ -53,11 +51,6 @@ GateRef CircuitBuilder::DoubleIsINF(GateRef x) return BitOr(diff1, diff2); } -GateRef CircuitBuilder::DoubleIsNanOrInf(GateRef x) -{ - return BitOr(DoubleIsNAN(x), DoubleIsINF(x)); -} - // Js World // cast operation @@ -80,24 +73,6 @@ int CircuitBuilder::NextVariableId() return env_->NextVariableId(); } -void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit) -{ - BRANCH(Equal(result, ExceptionConstant()), fail, success); - Bind(fail); - { - Jump(exit); - } -} - -void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal) -{ - BRANCH(Equal(result, exceptionVal), fail, success); - Bind(fail); - { - Jump(exit); - } -} - void CircuitBuilder::SubCfgEntry(Label *entry) { ASSERT(env_ != nullptr); diff --git a/ecmascript/compiler/hcr_circuit_builder.cpp b/ecmascript/compiler/hcr_circuit_builder.cpp index 2bdef20f9f..7e0106c071 100644 --- a/ecmascript/compiler/hcr_circuit_builder.cpp +++ b/ecmascript/compiler/hcr_circuit_builder.cpp @@ -745,4 +745,57 @@ GateRef CircuitBuilder::NumberToString(GateRef number) currentLabel->SetDepend(newGate); return newGate; } + +GateRef CircuitBuilder::IsEnumCacheValid(GateRef glue, GateRef receiver, + GateRef cachedHclass, GateRef kind) +{ + Label entry(env_); + SubCfgEntry(&entry); + Label exit(env_); + DEFVALUE(result, env_, VariableType::BOOL(), False()); + + Label isSameHclass(env_); + Label isSimpleEnumCache(env_); + Label notSimpleEnumCache(env_); + Label isEnumCache(env_); + Label isProtoChainEnumCache(env_); + Label prototypeIsHeapObj(env_); + Label protoChainNotChanged(env_); + + GateRef hclass = LoadHClass(glue, receiver); + BRANCH(Int64Equal(hclass, cachedHclass), &isSameHclass, &exit); + Bind(&isSameHclass); + BRANCH(Int32Equal(kind, Int32(static_cast(EnumCacheKind::SIMPLE))), + &isSimpleEnumCache, ¬SimpleEnumCache); + Bind(&isSimpleEnumCache); + { + result = True(); + Jump(&exit); + } + Bind(¬SimpleEnumCache); + BRANCH(Int32Equal(kind, Int32(static_cast(EnumCacheKind::NONE))), + &exit, &isProtoChainEnumCache); + Bind(&isProtoChainEnumCache); + GateRef prototype = GetPrototypeFromHClass(glue, hclass); + BRANCH(TaggedIsHeapObject(prototype), &prototypeIsHeapObj, + &protoChainNotChanged); + Bind(&prototypeIsHeapObj); + GateRef protoHClass = LoadHClass(glue, prototype); + GateRef enumCache = GetEnumCacheFromHClass(glue, protoHClass); + BRANCH(TaggedIsEnumCache(glue, enumCache), &isEnumCache, &exit); + Bind(&isEnumCache); + GateRef protoEnumCacheAll = GetEnumCacheAllFromEnumCache(glue, enumCache); + BRANCH(TaggedIsNull(protoEnumCacheAll), &exit, &protoChainNotChanged); + + Bind(&protoChainNotChanged); + { + result = True(); + Jump(&exit); + } + + Bind(&exit); + auto ret = *result; + SubCfgExit(); + return ret; +} } diff --git a/ecmascript/compiler/hcr_circuit_builder.h b/ecmascript/compiler/hcr_circuit_builder.h index 4b297ed867..2d5750261d 100644 --- a/ecmascript/compiler/hcr_circuit_builder.h +++ b/ecmascript/compiler/hcr_circuit_builder.h @@ -17,79 +17,13 @@ #define ECMASCRIPT_COMPILER_HCR_CIRCUIT_BUILDER_H #include "ecmascript/compiler/circuit_builder_helper.h" +#include "ecmascript/compiler/lcr_circuit_builder.h" +#include "ecmascript/compiler/mcr_circuit_builder.h" #include "ecmascript/mem/region.h" #include "ecmascript/js_function.h" namespace panda::ecmascript::kungfu { -GateRef CircuitBuilder::IsSpecial(GateRef x, JSTaggedType type) -{ - auto specialValue = circuit_->GetConstantGate( - MachineType::I64, type, GateType::TaggedValue()); - - return Equal(x, specialValue); -} - -inline GateRef CircuitBuilder::IsJSHClass(GateRef glue, GateRef obj) -{ - return Int32Equal(GetObjectType(LoadHClass(glue, obj)), Int32(static_cast(JSType::HCLASS))); -} - -inline GateRef CircuitBuilder::IsJSFunction(GateRef glue, GateRef obj) -{ - GateRef objectType = GetObjectType(LoadHClass(glue, obj)); - GateRef greater = Int32GreaterThanOrEqual(objectType, - Int32(static_cast(JSType::JS_FUNCTION_FIRST))); - GateRef less = Int32LessThanOrEqual(objectType, - Int32(static_cast(JSType::JS_FUNCTION_LAST))); - return BitAnd(greater, less); -} - -GateRef CircuitBuilder::IsJsType(GateRef glue, GateRef obj, JSType type) -{ - GateRef objectType = GetObjectType(LoadHClass(glue, obj)); - return Equal(objectType, Int32(static_cast(type))); -} - -GateRef CircuitBuilder::IsJSObject(GateRef glue, GateRef obj) -{ - Label entryPass(env_); - SubCfgEntry(&entryPass); - DEFVALUE(result, env_, VariableType::BOOL(), False()); - Label heapObj(env_); - Label exit(env_); - GateRef isHeapObject = TaggedIsHeapObject(obj); - BRANCH(isHeapObject, &heapObj, &exit); - Bind(&heapObj); - { - GateRef objectType = GetObjectType(LoadHClass(glue, obj)); - result = BitAnd( - Int32LessThanOrEqual(objectType, Int32(static_cast(JSType::JS_OBJECT_LAST))), - Int32GreaterThanOrEqual(objectType, Int32(static_cast(JSType::JS_OBJECT_FIRST)))); - Jump(&exit); - } - Bind(&exit); - auto ret = *result; - SubCfgExit(); - return ret; -} - -GateRef CircuitBuilder::IsCallableFromBitField(GateRef bitfield) -{ - return NotEqual( - Int32And(Int32LSR(bitfield, Int32(JSHClass::CallableBit::START_BIT)), - Int32((1LU << JSHClass::CallableBit::SIZE) - 1)), - Int32(0)); -} - -GateRef CircuitBuilder::IsCallable(GateRef glue, GateRef obj) -{ - GateRef hClass = LoadHClass(glue, obj); - GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET); - GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset); - return IsCallableFromBitField(bitfield); -} - GateRef CircuitBuilder::AlreadyDeopt(GateRef method) { GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET); @@ -104,38 +38,6 @@ GateRef CircuitBuilder::AlreadyDeoptFromExtraLiteralInfo(GateRef callfield) Int64(0)); } -GateRef CircuitBuilder::IsPrototypeHClass(GateRef hClass) -{ - GateRef bitfield = LoadConstOffset(VariableType::INT32(), hClass, JSHClass::BIT_FIELD_OFFSET); - return TruncInt32ToInt1(Int32And(Int32LSR(bitfield, - Int32(JSHClass::IsPrototypeBit::START_BIT)), - Int32((1LU << JSHClass::IsPrototypeBit::SIZE) - 1))); -} - -GateRef CircuitBuilder::IsJsProxy(GateRef glue, GateRef obj) -{ - GateRef objectType = GetObjectType(LoadHClass(glue, obj)); - return Int32Equal(objectType, Int32(static_cast(JSType::JS_PROXY))); -} - -GateRef CircuitBuilder::IsTreeString(GateRef glue, GateRef obj) -{ - GateRef objectType = GetObjectType(LoadHClass(glue, obj)); - return Int32Equal(objectType, Int32(static_cast(JSType::TREE_STRING))); -} - -GateRef CircuitBuilder::IsSlicedString(GateRef glue, GateRef obj) -{ - GateRef objectType = GetObjectType(LoadHClass(glue, obj)); - return Int32Equal(objectType, Int32(static_cast(JSType::SLICED_STRING))); -} - -GateRef CircuitBuilder::IsLineString(GateRef glue, GateRef obj) -{ - GateRef objectType = GetObjectType(LoadHClass(glue, obj)); - return Int32Equal(objectType, Int32(static_cast(JSType::LINE_STRING))); -} - GateRef CircuitBuilder::ComputeSizeUtf8(GateRef length) { return PtrAdd(IntPtr(LineEcmaString::DATA_OFFSET), length); @@ -158,22 +60,6 @@ inline GateRef CircuitBuilder::IsDictionaryMode(GateRef glue, GateRef object) return Int32Equal(type, Int32(static_cast(JSType::TAGGED_DICTIONARY))); } -GateRef CircuitBuilder::IsStableArguments(GateRef hClass) -{ - GateRef objectType = GetObjectType(hClass); - GateRef isJsArguments = Int32Equal(objectType, Int32(static_cast(JSType::JS_ARGUMENTS))); - GateRef isStableElements = IsStableElements(hClass); - return BitAnd(isStableElements, isJsArguments); -} - -GateRef CircuitBuilder::IsStableArray(GateRef hClass) -{ - GateRef objectType = GetObjectType(hClass); - GateRef isJsArray = Int32Equal(objectType, Int32(static_cast(JSType::JS_ARRAY))); - GateRef isStableElements = IsStableElements(hClass); - return BitAnd(isStableElements, isJsArray); -} - GateRef CircuitBuilder::IsAOTLiteralInfo(GateRef glue, GateRef x) { GateRef objType = GetObjectType(LoadHClass(glue, x)); @@ -182,59 +68,6 @@ GateRef CircuitBuilder::IsAOTLiteralInfo(GateRef glue, GateRef x) return isAOTLiteralInfoObj; } -#ifdef USE_CMC_GC -#ifndef NDEBUG -GateRef CircuitBuilder::LoadHClassWithLineASM(GateRef glue, GateRef object, [[maybe_unused]] int line) -{ - // ReadBarrier is not need for loading hClass as long as it is non-movable - // now temporarily add RB for hClass - GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET); - GateRef lowAddress = Load(VariableType::INT32(), glue, object, offset); - GateRef baseAddressOffset = IntPtr(JSThread::GlueData::GetBaseAddressOffset(env_->Is32Bit())); - GateRef baseAddress = Load(VariableType::INT64(), glue, glue, baseAddressOffset); - return Int64ToTaggedPtr(Int64Add(baseAddress, ZExtInt32ToInt64(lowAddress))); -} -#else -GateRef CircuitBuilder::LoadHClass(GateRef glue, GateRef object) -{ - // ReadBarrier is not need for loading hClass as long as it is non-movable - // now temporarily add RB for hClass - GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET); - GateRef lowAddress = Load(VariableType::INT32(), glue, object, offset); - GateRef baseAddressOffset = IntPtr(JSThread::GlueData::GetBaseAddressOffset(env_->Is32Bit())); - GateRef baseAddress = Load(VariableType::INT64(), glue, glue, baseAddressOffset); - return Int64ToTaggedPtr(Int64Add(baseAddress, ZExtInt32ToInt64(lowAddress))); -} -#endif - -GateRef CircuitBuilder::LoadHClassByConstOffset(GateRef glue, GateRef object) -{ - GateRef lowAddress = LoadConstOffset(VariableType::INT32(), object, TaggedObject::HCLASS_OFFSET); - GateRef baseAddressOffset = IntPtr(JSThread::GlueData::GetBaseAddressOffset(env_->Is32Bit())); - GateRef baseAddress = Load(VariableType::INT64(), glue, glue, baseAddressOffset); - return Int64ToTaggedPtr(Int64Add(baseAddress, ZExtInt32ToInt64(lowAddress))); -} -#else - -#ifndef NDEBUG -GateRef CircuitBuilder::LoadHClassWithLineASM(GateRef glue, GateRef object, [[maybe_unused]] int line) -{ - GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET); - return Load(VariableType::JS_POINTER(), glue, object, offset); -} -#else -GateRef CircuitBuilder::LoadHClass(GateRef glue, GateRef object) -{ - GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET); - return Load(VariableType::JS_POINTER(), glue, object, offset); -} -#endif - -GateRef CircuitBuilder::LoadHClassByConstOffset(GateRef glue, GateRef object) -{ - return LoadConstOffset(VariableType::JS_POINTER(), object, TaggedObject::HCLASS_OFFSET); -} -#endif GateRef CircuitBuilder::LoadPrototype(GateRef hclass) { return LoadConstOffset(VariableType::JS_POINTER(), hclass, JSHClass::PROTOTYPE_OFFSET); @@ -302,43 +135,6 @@ GateRef CircuitBuilder::IsDictionaryModeByHClass(GateRef hClass) Int32(0)); } -#ifdef USE_CMC_GC -void CircuitBuilder::StoreHClass(GateRef glue, GateRef object, GateRef hClass, MemoryAttribute mAttr) -{ - Store(VariableType::INT32(), glue, object, IntPtr(TaggedStateWord::STATE_WORD_OFFSET), Int32(0)); - TransitionHClass(glue, object, hClass, mAttr); -} - -void CircuitBuilder::TransitionHClass(GateRef glue, GateRef object, GateRef hClass, MemoryAttribute mAttr) -{ - GateRef compValue = TruncInt64ToInt32(TaggedPointerToInt64(hClass)); - StoreHClass(VariableType::JS_POINTER(), glue, object, IntPtr(TaggedObject::HCLASS_OFFSET), hClass, - compValue, mAttr); -} -#else -void CircuitBuilder::StoreHClass(GateRef glue, GateRef object, GateRef hClass, MemoryAttribute mAttr) -{ - TransitionHClass(glue, object, hClass, mAttr); -} - -void CircuitBuilder::TransitionHClass(GateRef glue, GateRef object, GateRef hClass, MemoryAttribute mAttr) -{ - Store(VariableType::JS_POINTER(), glue, object, IntPtr(TaggedObject::HCLASS_OFFSET), hClass, mAttr); -} -#endif - -void CircuitBuilder::StorePrototype(GateRef glue, GateRef hclass, GateRef prototype) -{ - Store(VariableType::JS_POINTER(), glue, hclass, IntPtr(JSHClass::PROTOTYPE_OFFSET), prototype); -} - -GateRef CircuitBuilder::GetObjectType(GateRef hClass) -{ - GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET); - GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset); - return Int32And(bitfield, Int32((1LU << JSHClass::ObjectTypeBits::SIZE) - 1)); -} - inline GateRef CircuitBuilder::CanFastCall(GateRef jsFunc) { GateRef bitFieldOffset = IntPtr(JSFunctionBase::BIT_FIELD_OFFSET); @@ -379,16 +175,6 @@ GateRef CircuitBuilder::IsDictionaryElement(GateRef hClass) Int32(0)); } -GateRef CircuitBuilder::IsStableElements(GateRef hClass) -{ - GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET); - GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset); - return NotEqual(Int32And(Int32LSR(bitfield, - Int32(JSHClass::IsStableElementsBit::START_BIT)), - Int32((1LU << JSHClass::IsStableElementsBit::SIZE) - 1)), - Int32(0)); -} - GateRef CircuitBuilder::IsJSArrayPrototypeModified(GateRef hClass) { GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET); diff --git a/ecmascript/compiler/lcr_circuit_builder.cpp b/ecmascript/compiler/lcr_circuit_builder.cpp index ec3f939a0d..b034a1649b 100644 --- a/ecmascript/compiler/lcr_circuit_builder.cpp +++ b/ecmascript/compiler/lcr_circuit_builder.cpp @@ -210,31 +210,6 @@ GateRef CircuitBuilder::DoubleTrunc(GateRef gate, GateRef value, const char* com return CallNGCRuntime(glue, RTSTUB_ID(FloatTrunc), Gate::InvalidGateRef, {value}, gate, comment); } -GateRef CircuitBuilder::GetDoubleOfTNumber(GateRef x) -{ - Label subentry(env_); - SubCfgEntry(&subentry); - Label isInt(env_); - Label isDouble(env_); - Label exit(env_); - DEFVALUE(result, env_, VariableType::FLOAT64(), Double(0)); - BRANCH(TaggedIsInt(x), &isInt, &isDouble); - Bind(&isInt); - { - result = ChangeInt32ToFloat64(GetInt32OfTInt(x)); - Jump(&exit); - } - Bind(&isDouble); - { - result = GetDoubleOfTDouble(x); - Jump(&exit); - } - Bind(&exit); - GateRef ret = *result; - SubCfgExit(); - return ret; -} - GateRef CircuitBuilder::DoubleToIntOverflowCheck(GateRef x, size_t typeBits) { GateRef xInt64 = CastDoubleToInt64(x); diff --git a/ecmascript/compiler/lcr_circuit_builder.h b/ecmascript/compiler/lcr_circuit_builder.h index b9c2bf3b2c..331af7c8d8 100644 --- a/ecmascript/compiler/lcr_circuit_builder.h +++ b/ecmascript/compiler/lcr_circuit_builder.h @@ -17,6 +17,7 @@ #define ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H #include "ecmascript/compiler/circuit_builder.h" +#include "ecmascript/compiler/circuit_builder-inl.h" #include "ecmascript/compiler/circuit_builder_helper.h" #include "ecmascript/compiler/share_gate_meta_data.h" @@ -177,31 +178,6 @@ GateRef CircuitBuilder::GetInt32OfTInt(GateRef x) return TruncInt64ToInt32(tagged); } -GateRef CircuitBuilder::GetInt32OfTNumber(GateRef x) -{ - Label subentry(env_); - SubCfgEntry(&subentry); - Label isInt(env_); - Label isDouble(env_); - Label exit(env_); - DEFVALUE(result, env_, VariableType::INT32(), Int32(0)); - BRANCH(TaggedIsInt(x), &isInt, &isDouble); - Bind(&isInt); - { - result = GetInt32OfTInt(x); - Jump(&exit); - } - Bind(&isDouble); - { - result = DoubleCheckINFInRangeInt32(GetDoubleOfTDouble(x)); - Jump(&exit); - } - Bind(&exit); - GateRef ret = *result; - SubCfgExit(); - return ret; -} - GateRef CircuitBuilder::TaggedCastToIntPtr(GateRef x) { return env_->Is32Bit() ? GetInt32OfTInt(x) : GetInt64OfTInt(x); @@ -312,6 +288,11 @@ GateRef CircuitBuilder::DoubleIsNAN(GateRef x) return Equal(SExtInt1ToInt32(diff), Int32(0)); } +GateRef CircuitBuilder::DoubleIsNanOrInf(GateRef x) +{ + return BitOr(DoubleIsNAN(x), DoubleIsINF(x)); +} + GateRef CircuitBuilder::DoubleToTagged(GateRef x) { GateRef val = CastDoubleToInt64(x); @@ -389,6 +370,22 @@ GateRef CircuitBuilder::NotEqual(GateRef x, GateRef y, const char* comment) } } +void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit) +{ + BRANCH(Equal(result, ExceptionConstant()), fail, success); + Bind(fail); + { + Jump(exit); + } } +void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal) +{ + BRANCH(Equal(result, exceptionVal), fail, success); + Bind(fail); + { + Jump(exit); + } +} +} #endif // ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H diff --git a/ecmascript/compiler/mcr_circuit_builder.cpp b/ecmascript/compiler/mcr_circuit_builder.cpp index c4b8491596..8f5f73b81e 100644 --- a/ecmascript/compiler/mcr_circuit_builder.cpp +++ b/ecmascript/compiler/mcr_circuit_builder.cpp @@ -662,6 +662,31 @@ GateRef CircuitBuilder::CheckHoleDoubleAndConvertToFloat64(GateRef gate) return CheckAndConvert(gate, ValueType::HOLE_DOUBLE, ValueType::FLOAT64); } +GateRef CircuitBuilder::GetDoubleOfTNumber(GateRef x) +{ + Label subentry(env_); + SubCfgEntry(&subentry); + Label isInt(env_); + Label isDouble(env_); + Label exit(env_); + DEFVALUE(result, env_, VariableType::FLOAT64(), Double(0)); + BRANCH(TaggedIsInt(x), &isInt, &isDouble); + Bind(&isInt); + { + result = ChangeInt32ToFloat64(GetInt32OfTInt(x)); + Jump(&exit); + } + Bind(&isDouble); + { + result = GetDoubleOfTDouble(x); + Jump(&exit); + } + Bind(&exit); + GateRef ret = *result; + SubCfgExit(); + return ret; +} + GateRef CircuitBuilder::TryPrimitiveTypeCheck(GateType type, GateRef gate) { if (acc_.GetOpCode(gate) == OpCode::CONSTANT) { @@ -1481,57 +1506,6 @@ GateRef CircuitBuilder::ComputeTaggedArraySize(GateRef length) PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), length)); } -GateRef CircuitBuilder::IsEnumCacheValid(GateRef glue, GateRef receiver, GateRef cachedHclass, GateRef kind) -{ - Label entry(env_); - SubCfgEntry(&entry); - Label exit(env_); - DEFVALUE(result, env_, VariableType::BOOL(), False()); - - Label isSameHclass(env_); - Label isSimpleEnumCache(env_); - Label notSimpleEnumCache(env_); - Label isEnumCache(env_); - Label isProtoChainEnumCache(env_); - Label prototypeIsHeapObj(env_); - Label protoChainNotChanged(env_); - - GateRef hclass = LoadHClass(glue, receiver); - BRANCH(Int64Equal(hclass, cachedHclass), &isSameHclass, &exit); - Bind(&isSameHclass); - BRANCH(Int32Equal(kind, Int32(static_cast(EnumCacheKind::SIMPLE))), - &isSimpleEnumCache, ¬SimpleEnumCache); - Bind(&isSimpleEnumCache); - { - result = True(); - Jump(&exit); - } - Bind(¬SimpleEnumCache); - BRANCH(Int32Equal(kind, Int32(static_cast(EnumCacheKind::NONE))), - &exit, &isProtoChainEnumCache); - Bind(&isProtoChainEnumCache); - GateRef prototype = GetPrototypeFromHClass(glue, hclass); - BRANCH(TaggedIsHeapObject(prototype), &prototypeIsHeapObj, &protoChainNotChanged); - Bind(&prototypeIsHeapObj); - GateRef protoHClass = LoadHClass(glue, prototype); - GateRef enumCache = GetEnumCacheFromHClass(glue, protoHClass); - BRANCH(TaggedIsEnumCache(glue, enumCache), &isEnumCache, &exit); - Bind(&isEnumCache); - GateRef protoEnumCacheAll = GetEnumCacheAllFromEnumCache(glue, enumCache); - BRANCH(TaggedIsNull(protoEnumCacheAll), &exit, &protoChainNotChanged); - - Bind(&protoChainNotChanged); - { - result = True(); - Jump(&exit); - } - - Bind(&exit); - auto ret = *result; - SubCfgExit(); - return ret; -} - GateRef CircuitBuilder::NeedCheckProperty(GateRef glue, GateRef receiver) { Label entry(env_); diff --git a/ecmascript/compiler/mcr_circuit_builder.h b/ecmascript/compiler/mcr_circuit_builder.h index ba75ee9ac6..14f19ba095 100644 --- a/ecmascript/compiler/mcr_circuit_builder.h +++ b/ecmascript/compiler/mcr_circuit_builder.h @@ -18,12 +18,181 @@ #include "ecmascript/compiler/circuit_builder.h" #include "ecmascript/compiler/circuit_builder_helper.h" +#include "ecmascript/compiler/lcr_circuit_builder.h" #include "ecmascript/global_env.h" #include "ecmascript/mem/region.h" #include "ecmascript/method.h" #include "ecmascript/js_function.h" namespace panda::ecmascript::kungfu { +GateRef CircuitBuilder::IsJSObject(GateRef glue, GateRef obj) +{ + Label entryPass(env_); + SubCfgEntry(&entryPass); + DEFVALUE(result, env_, VariableType::BOOL(), False()); + Label heapObj(env_); + Label exit(env_); + GateRef isHeapObject = TaggedIsHeapObject(obj); + BRANCH(isHeapObject, &heapObj, &exit); + Bind(&heapObj); + { + GateRef objectType = GetObjectType(LoadHClass(glue, obj)); + result = BitAnd( + Int32LessThanOrEqual(objectType, Int32(static_cast(JSType::JS_OBJECT_LAST))), + Int32GreaterThanOrEqual(objectType, Int32(static_cast(JSType::JS_OBJECT_FIRST)))); + Jump(&exit); + } + Bind(&exit); + auto ret = *result; + SubCfgExit(); + return ret; +} + +GateRef CircuitBuilder::IsCallableFromBitField(GateRef bitfield) +{ + return NotEqual( + Int32And(Int32LSR(bitfield, Int32(JSHClass::CallableBit::START_BIT)), + Int32((1LU << JSHClass::CallableBit::SIZE) - 1)), Int32(0)); +} + +GateRef CircuitBuilder::IsCallable(GateRef glue, GateRef obj) +{ + GateRef hClass = LoadHClass(glue, obj); + GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET); + GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset); + return IsCallableFromBitField(bitfield); +} + +GateRef CircuitBuilder::GetObjectType(GateRef hClass) +{ + GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET); + GateRef bitfield = + LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset); + return Int32And(bitfield, Int32((1LU << JSHClass::ObjectTypeBits::SIZE) - 1)); +} + +GateRef CircuitBuilder::IsJsType(GateRef glue, GateRef obj, JSType type) +{ + GateRef objectType = GetObjectType(LoadHClass(glue, obj)); + return Equal(objectType, Int32(static_cast(type))); +} + +GateRef CircuitBuilder::IsPrototypeHClass(GateRef hClass) +{ + GateRef bitfield = LoadConstOffset(VariableType::INT32(), hClass, + JSHClass::BIT_FIELD_OFFSET); + return TruncInt32ToInt1( + Int32And(Int32LSR(bitfield, Int32(JSHClass::IsPrototypeBit::START_BIT)), + Int32((1LU << JSHClass::IsPrototypeBit::SIZE) - 1))); +} + +GateRef CircuitBuilder::IsSpecial(GateRef x, JSTaggedType type) +{ + auto specialValue = circuit_->GetConstantGate(MachineType::I64, type, GateType::TaggedValue()); + return Equal(x, specialValue); +} + +inline GateRef CircuitBuilder::IsJSHClass(GateRef glue, GateRef obj) +{ + return Int32Equal(GetObjectType(LoadHClass(glue, obj)), Int32(static_cast(JSType::HCLASS))); +} + +inline GateRef CircuitBuilder::IsJSFunction(GateRef glue, GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(glue, obj)); + GateRef greater = Int32GreaterThanOrEqual(objectType, Int32(static_cast(JSType::JS_FUNCTION_FIRST))); + GateRef less = Int32LessThanOrEqual(objectType, Int32(static_cast(JSType::JS_FUNCTION_LAST))); + return BitAnd(greater, less); +} + +#ifdef USE_CMC_GC +#ifndef NDEBUG +GateRef CircuitBuilder::LoadHClassWithLineASM(GateRef glue, GateRef object, [[maybe_unused]] int line) +{ + // ReadBarrier is not need for loading hClass as long as it is non-movable + // now temporarily add RB for hClass + GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET); + GateRef lowAddress = Load(VariableType::INT32(), glue, object, offset); + GateRef baseAddressOffset = IntPtr(JSThread::GlueData::GetBaseAddressOffset(env_->Is32Bit())); + GateRef baseAddress = Load(VariableType::INT64(), glue, glue, baseAddressOffset); + return Int64ToTaggedPtr(Int64Add(baseAddress, ZExtInt32ToInt64(lowAddress))); +} +#else +GateRef CircuitBuilder::LoadHClass(GateRef glue, GateRef object) +{ + // ReadBarrier is not need for loading hClass as long as it is non-movable + // now temporarily add RB for hClass + GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET); + GateRef lowAddress = Load(VariableType::INT32(), glue, object, offset); + GateRef baseAddressOffset = IntPtr(JSThread::GlueData::GetBaseAddressOffset(env_->Is32Bit())); + GateRef baseAddress = Load(VariableType::INT64(), glue, glue, baseAddressOffset); + return Int64ToTaggedPtr(Int64Add(baseAddress, ZExtInt32ToInt64(lowAddress))); +} +#endif + +GateRef CircuitBuilder::LoadHClassByConstOffset(GateRef glue, GateRef object) +{ + GateRef lowAddress = LoadConstOffset(VariableType::INT32(), object, TaggedObject::HCLASS_OFFSET); + GateRef baseAddressOffset = IntPtr(JSThread::GlueData::GetBaseAddressOffset(env_->Is32Bit())); + GateRef baseAddress = Load(VariableType::INT64(), glue, glue, baseAddressOffset); + return Int64ToTaggedPtr(Int64Add(baseAddress, ZExtInt32ToInt64(lowAddress))); +} +#else + +#ifndef NDEBUG +GateRef CircuitBuilder::LoadHClassWithLineASM(GateRef glue, GateRef object, [[maybe_unused]] int line) +{ + GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET); + return Load(VariableType::JS_POINTER(), glue, object, offset); +} +#else +GateRef CircuitBuilder::LoadHClass(GateRef glue, GateRef object) +{ + GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET); + return Load(VariableType::JS_POINTER(), glue, object, offset); +} +#endif + +GateRef CircuitBuilder::LoadHClassByConstOffset(GateRef glue, GateRef object) +{ + return LoadConstOffset(VariableType::JS_POINTER(), object, TaggedObject::HCLASS_OFFSET); +} +#endif + +#ifdef USE_CMC_GC +void CircuitBuilder::StoreHClass(GateRef glue, GateRef object, GateRef hClass, + MemoryAttribute mAttr) +{ + Store(VariableType::INT32(), glue, object, + IntPtr(TaggedStateWord::STATE_WORD_OFFSET), Int32(0)); + TransitionHClass(glue, object, hClass, mAttr); +} + +void CircuitBuilder::TransitionHClass(GateRef glue, GateRef object, + GateRef hClass, MemoryAttribute mAttr) +{ + GateRef compValue = TruncInt64ToInt32(TaggedPointerToInt64(hClass)); + StoreHClass(VariableType::JS_POINTER(), glue, object, + IntPtr(TaggedObject::HCLASS_OFFSET), hClass, compValue, mAttr); +} +#else +void CircuitBuilder::StoreHClass(GateRef glue, GateRef object, GateRef hClass, MemoryAttribute mAttr) +{ + TransitionHClass(glue, object, hClass, mAttr); +} + +void CircuitBuilder::TransitionHClass(GateRef glue, GateRef object, GateRef hClass, MemoryAttribute mAttr) +{ + Store(VariableType::JS_POINTER(), glue, object, + IntPtr(TaggedObject::HCLASS_OFFSET), hClass, mAttr); +} +#endif + +void CircuitBuilder::StorePrototype(GateRef glue, GateRef hclass, GateRef prototype) +{ + Store(VariableType::JS_POINTER(), glue, hclass, + IntPtr(JSHClass::PROTOTYPE_OFFSET), prototype); +} // bit operation @@ -185,6 +354,64 @@ GateRef CircuitBuilder::TaggedIsString(GateRef glue, GateRef obj) return ret; } +GateRef CircuitBuilder::IsStableElements(GateRef hClass) +{ + GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET); + GateRef bitfield = + LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset); + return NotEqual( + Int32And( + Int32LSR(bitfield, Int32(JSHClass::IsStableElementsBit::START_BIT)), + Int32((1LU << JSHClass::IsStableElementsBit::SIZE) - 1)), + Int32(0)); +} + +GateRef CircuitBuilder::IsStableArguments(GateRef hClass) +{ + GateRef objectType = GetObjectType(hClass); + GateRef isJsArguments = Int32Equal( + objectType, Int32(static_cast(JSType::JS_ARGUMENTS))); + GateRef isStableElements = IsStableElements(hClass); + return BitAnd(isStableElements, isJsArguments); +} + +GateRef CircuitBuilder::IsStableArray(GateRef hClass) +{ + GateRef objectType = GetObjectType(hClass); + GateRef isJsArray = + Int32Equal(objectType, Int32(static_cast(JSType::JS_ARRAY))); + GateRef isStableElements = IsStableElements(hClass); + return BitAnd(isStableElements, isJsArray); +} + +GateRef CircuitBuilder::IsJsProxy(GateRef glue, GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(glue, obj)); + return Int32Equal(objectType, + Int32(static_cast(JSType::JS_PROXY))); +} + +GateRef CircuitBuilder::IsTreeString(GateRef glue, GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(glue, obj)); + return Int32Equal(objectType, + Int32(static_cast(JSType::TREE_STRING))); +} + +GateRef CircuitBuilder::IsSlicedString(GateRef glue, GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(glue, obj)); + return Int32Equal(objectType, + Int32(static_cast(JSType::SLICED_STRING))); +} + +GateRef CircuitBuilder::IsLineString(GateRef glue, GateRef obj) +{ + GateRef objectType = GetObjectType(LoadHClass(glue, obj)); + return Int32Equal(objectType, + Int32(static_cast(JSType::LINE_STRING))); +} + GateRef CircuitBuilder::TaggedIsLineUtf8String(GateRef glue, GateRef obj) { return LogicAndBuilder(env_).And(TaggedIsString(glue, obj)) @@ -611,6 +838,31 @@ GateRef CircuitBuilder::TaggedGetInt(GateRef x) return TruncInt64ToInt32(Int64And(x, Int64(~JSTaggedValue::TAG_MARK))); } +GateRef CircuitBuilder::GetInt32OfTNumber(GateRef x) +{ + Label subentry(env_); + SubCfgEntry(&subentry); + Label isInt(env_); + Label isDouble(env_); + Label exit(env_); + DEFVALUE(result, env_, VariableType::INT32(), Int32(0)); + BRANCH(TaggedIsInt(x), &isInt, &isDouble); + Bind(&isInt); + { + result = GetInt32OfTInt(x); + Jump(&exit); + } + Bind(&isDouble); + { + result = DoubleCheckINFInRangeInt32(GetDoubleOfTDouble(x)); + Jump(&exit); + } + Bind(&exit); + GateRef ret = *result; + SubCfgExit(); + return ret; +} + inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef hirGate, const std::vector &args, BuiltinsStubCSigns::ID id, bool isSideEffect) { diff --git a/ecmascript/compiler/mcr_lowering.cpp b/ecmascript/compiler/mcr_lowering.cpp index 45cca920cc..bbfc1c6d5a 100644 --- a/ecmascript/compiler/mcr_lowering.cpp +++ b/ecmascript/compiler/mcr_lowering.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "ecmascript/compiler/mcr_lowering.h" +#include "ecmascript/compiler/mcr_circuit_builder.h" #include "ecmascript/compiler/pgo_type/pgo_type_manager.h" #include "ecmascript/global_env.h" #include "ecmascript/jspandafile/program_object.h" diff --git a/ecmascript/compiler/number_speculative_lowering.h b/ecmascript/compiler/number_speculative_lowering.h index f4b64ed22f..40d8ac29f9 100644 --- a/ecmascript/compiler/number_speculative_lowering.h +++ b/ecmascript/compiler/number_speculative_lowering.h @@ -18,6 +18,8 @@ #include "ecmascript/compiler/circuit_builder-inl.h" #include "ecmascript/compiler/gate_accessor.h" +#include "ecmascript/compiler/lcr_circuit_builder.h" +#include "ecmascript/compiler/mcr_circuit_builder.h" #include "ecmascript/compiler/share_gate_meta_data.h" #include "ecmascript/compiler/number_gate_info.h" #include "ecmascript/compiler/type.h" diff --git a/ecmascript/compiler/number_speculative_retype.h b/ecmascript/compiler/number_speculative_retype.h index b9a3a5c718..e770c052dc 100644 --- a/ecmascript/compiler/number_speculative_retype.h +++ b/ecmascript/compiler/number_speculative_retype.h @@ -19,6 +19,7 @@ #include "ecmascript/compiler/circuit_builder.h" #include "ecmascript/compiler/combined_pass_visitor.h" #include "ecmascript/compiler/gate_accessor.h" +#include "ecmascript/compiler/lcr_circuit_builder.h" #include "ecmascript/compiler/share_gate_meta_data.h" #include "ecmascript/compiler/number_gate_info.h" #include "ecmascript/compiler/type.h" diff --git a/ecmascript/compiler/post_schedule.h b/ecmascript/compiler/post_schedule.h index 148c9c173c..8a80208231 100644 --- a/ecmascript/compiler/post_schedule.h +++ b/ecmascript/compiler/post_schedule.h @@ -18,6 +18,7 @@ #include "ecmascript/compiler/circuit.h" #include "ecmascript/compiler/circuit_builder.h" +#include "ecmascript/compiler/lcr_circuit_builder.h" #include "ecmascript/compiler/gate_accessor.h" #include "ecmascript/mem/chunk_containers.h" diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index 10352e2951..94de5a526d 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -19,6 +19,9 @@ #include "ecmascript/base/config.h" #include "ecmascript/compiler/call_signature.h" #include "ecmascript/compiler/circuit_builder.h" +#include "ecmascript/compiler/lcr_circuit_builder.h" +#include "ecmascript/compiler/mcr_circuit_builder.h" +#include "ecmascript/compiler/hcr_circuit_builder.h" #include "ecmascript/compiler/lcr_gate_meta_data.h" #include "ecmascript/compiler/profiler_operation.h" #include "ecmascript/compiler/share_gate_meta_data.h" diff --git a/ecmascript/compiler/typed_bytecode_lowering.cpp b/ecmascript/compiler/typed_bytecode_lowering.cpp index f4e8a67e3f..4d7988d127 100644 --- a/ecmascript/compiler/typed_bytecode_lowering.cpp +++ b/ecmascript/compiler/typed_bytecode_lowering.cpp @@ -17,6 +17,7 @@ #include "ecmascript/compiler/typed_bytecode_lowering.h" #include "ecmascript/compiler/circuit_builder_helper.h" +#include "ecmascript/compiler/mcr_circuit_builder.h" #include "ecmascript/compiler/variable_type.h" #include "ecmascript/dfx/vmstat/opt_code_profiler.h" #include "ecmascript/jit/jit.h" diff --git a/ecmascript/compiler/typed_hcr_lowering.cpp b/ecmascript/compiler/typed_hcr_lowering.cpp index edeb887f4b..3b57820e03 100644 --- a/ecmascript/compiler/typed_hcr_lowering.cpp +++ b/ecmascript/compiler/typed_hcr_lowering.cpp @@ -16,6 +16,7 @@ #include "ecmascript/compiler/typed_hcr_lowering.h" #include "ecmascript/compiler/builtins_lowering.h" +#include "ecmascript/compiler/hcr_circuit_builder.h" #include "ecmascript/compiler/new_object_stub_builder.h" #include "ecmascript/js_map.h" #include "ecmascript/js_primitive_ref.h" diff --git a/ecmascript/compiler/typed_native_inline_lowering.cpp b/ecmascript/compiler/typed_native_inline_lowering.cpp index d70f139b19..1ec2d167e0 100644 --- a/ecmascript/compiler/typed_native_inline_lowering.cpp +++ b/ecmascript/compiler/typed_native_inline_lowering.cpp @@ -16,6 +16,7 @@ #include "ecmascript/compiler/builtins/builtins_array_stub_builder.h" #include "ecmascript/compiler/builtins/builtins_object_stub_builder.h" #include "ecmascript/compiler/circuit_arg_indices.h" +#include "ecmascript/compiler/hcr_circuit_builder.h" #include "ecmascript/compiler/new_object_stub_builder.h" #include "ecmascript/compiler/type_info_accessors.h" #include "ecmascript/global_env.h" -- Gitee