mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 12:10:47 +00:00
!3592 AOT VTable Part2 && Part3
Merge pull request !3592 from dingding/vtable
This commit is contained in:
commit
4e19bae5bc
@ -715,7 +715,6 @@ bool JsonStringifier::SerializeKeys(const JSHandle<JSObject> &obj, const JSHandl
|
||||
JSHandle<JSHClass> jsHclass(thread_, obj->GetJSHClass());
|
||||
JSTaggedValue enumCache = jsHclass->GetEnumCache();
|
||||
if (!enumCache.IsNull()) {
|
||||
int propsNumber = static_cast<int>(jsHclass->NumberOfProps());
|
||||
JSHandle<TaggedArray> cache(thread_, enumCache);
|
||||
uint32_t length = cache->GetLength();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
@ -726,7 +725,7 @@ bool JsonStringifier::SerializeKeys(const JSHandle<JSObject> &obj, const JSHandl
|
||||
handleKey_.Update(key);
|
||||
JSTaggedValue value;
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject());
|
||||
int index = layoutInfo->FindElementWithCache(thread_, *jsHclass, key, propsNumber);
|
||||
int index = JSHClass::FindPropertyEntry(thread_, *jsHclass, key);
|
||||
PropertyAttributes attr(layoutInfo->GetAttr(index));
|
||||
ASSERT(static_cast<int>(attr.GetOffset()) == index);
|
||||
value = attr.IsInlinedProps()
|
||||
@ -746,14 +745,13 @@ bool JsonStringifier::SerializeKeys(const JSHandle<JSObject> &obj, const JSHandl
|
||||
if (end <= 0) {
|
||||
return hasContent;
|
||||
}
|
||||
int propsNumber = static_cast<int>(jsHclass->NumberOfProps());
|
||||
for (int i = 0; i < end; i++) {
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject());
|
||||
JSTaggedValue key = layoutInfo->GetKey(i);
|
||||
if (key.IsString() && layoutInfo->GetAttr(i).IsEnumerable()) {
|
||||
handleKey_.Update(key);
|
||||
JSTaggedValue value;
|
||||
int index = layoutInfo->FindElementWithCache(thread_, *jsHclass, key, propsNumber);
|
||||
int index = JSHClass::FindPropertyEntry(thread_, *jsHclass, key);
|
||||
PropertyAttributes attr(layoutInfo->GetAttr(index));
|
||||
ASSERT(static_cast<int>(attr.GetOffset()) == index);
|
||||
value = attr.IsInlinedProps()
|
||||
|
@ -3443,6 +3443,7 @@ JSHandle<JSObject> Builtins::InitializeArkTools(const JSHandle<GlobalEnv> &env)
|
||||
SetFunction(env, tools, "dumpHClass", builtins::BuiltinsArkTools::DumpHClass, FunctionLength::ONE);
|
||||
SetFunction(env, tools, "isTSHClass", builtins::BuiltinsArkTools::IsTSHClass, FunctionLength::ONE);
|
||||
SetFunction(env, tools, "getHClass", builtins::BuiltinsArkTools::GetHClass, FunctionLength::ONE);
|
||||
SetFunction(env, tools, "hasTSSubtyping", builtins::BuiltinsArkTools::HasTSSubtyping, FunctionLength::ONE);
|
||||
SetFunction(env, tools, "forceFullGC", builtins::BuiltinsArkTools::ForceFullGC, FunctionLength::ZERO);
|
||||
SetFunction(env, tools, "removeAOTFlag", builtins::BuiltinsArkTools::RemoveAOTFlag, FunctionLength::ONE);
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
|
@ -61,8 +61,8 @@ JSTaggedValue BuiltinsArkTools::CompareHClass(EcmaRuntimeCallInfo *info)
|
||||
|
||||
JSHandle<JSTaggedValue> obj1 = GetCallArg(info, 0);
|
||||
JSHandle<JSTaggedValue> obj2 = GetCallArg(info, 1);
|
||||
JSHClass* obj1Hclass = obj1->GetTaggedObject()->GetClass();
|
||||
JSHClass* obj2Hclass = obj2->GetTaggedObject()->GetClass();
|
||||
JSHClass *obj1Hclass = obj1->GetTaggedObject()->GetClass();
|
||||
JSHClass *obj2Hclass = obj2->GetTaggedObject()->GetClass();
|
||||
std::ostringstream oss;
|
||||
obj1Hclass->Dump(oss);
|
||||
obj2Hclass->Dump(oss);
|
||||
@ -80,7 +80,7 @@ JSTaggedValue BuiltinsArkTools::DumpHClass(EcmaRuntimeCallInfo *info)
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
|
||||
JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
|
||||
JSHClass* objHclass = obj->GetTaggedObject()->GetClass();
|
||||
JSHClass *objHclass = obj->GetTaggedObject()->GetClass();
|
||||
std::ostringstream oss;
|
||||
objHclass->Dump(oss);
|
||||
|
||||
@ -96,7 +96,7 @@ JSTaggedValue BuiltinsArkTools::IsTSHClass(EcmaRuntimeCallInfo *info)
|
||||
|
||||
ASSERT(info->GetArgsNumber() == 1);
|
||||
JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
|
||||
JSHClass* hclass = object->GetTaggedObject()->GetClass();
|
||||
JSHClass *hclass = object->GetTaggedObject()->GetClass();
|
||||
bool isTSHClass = hclass->IsTS();
|
||||
return GetTaggedBoolean(isTSHClass);
|
||||
}
|
||||
@ -109,10 +109,22 @@ JSTaggedValue BuiltinsArkTools::GetHClass(EcmaRuntimeCallInfo *info)
|
||||
|
||||
ASSERT(info->GetArgsNumber() == 1);
|
||||
JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
|
||||
JSHClass* hclass = object->GetTaggedObject()->GetClass();
|
||||
JSHClass *hclass = object->GetTaggedObject()->GetClass();
|
||||
return JSTaggedValue(hclass);
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::HasTSSubtyping(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
JSThread *thread = info->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
|
||||
ASSERT(info->GetArgsNumber() == 1);
|
||||
JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
|
||||
JSHClass *hclass = object->GetTaggedObject()->GetClass();
|
||||
return GetTaggedBoolean(hclass->HasTSSubtyping());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::ForceFullGC(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
|
@ -35,6 +35,8 @@ public:
|
||||
|
||||
static JSTaggedValue GetHClass(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue HasTSSubtyping(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue ForceFullGC(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue RemoveAOTFlag(EcmaRuntimeCallInfo *info);
|
||||
|
@ -123,6 +123,14 @@ public:
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_META)
|
||||
#undef DECLARE_GATE_META
|
||||
|
||||
#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
|
||||
const GateMetaData* NAME(uint64_t pcOffset) const \
|
||||
{ \
|
||||
return metaBuilder_.NAME(pcOffset); \
|
||||
}
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_META)
|
||||
#undef DECLARE_GATE_META
|
||||
|
||||
const GateMetaData* Nop()
|
||||
{
|
||||
return metaBuilder_.Nop();
|
||||
|
@ -510,6 +510,11 @@ GateRef CircuitBuilder::GetGlobalConstantString(ConstantIndex index)
|
||||
return PtrMul(IntPtr(sizeof(JSTaggedValue)), IntPtr(static_cast<int>(index)));
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::LoadObjectFromWeakRef(GateRef x)
|
||||
{
|
||||
return PtrAdd(x, IntPtr(-JSTaggedValue::TAG_WEAK));
|
||||
}
|
||||
|
||||
// object operation
|
||||
GateRef CircuitBuilder::LoadHClass(GateRef object)
|
||||
{
|
||||
@ -1074,4 +1079,4 @@ GateRef CircuitBuilder::Int32OverflowCheck(GateRef gate)
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -635,25 +635,27 @@ GateRef CircuitBuilder::HeapAlloc(GateRef initialHClass, GateType type, RegionSp
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::LoadProperty(GateRef receiver, GateRef offset)
|
||||
GateRef CircuitBuilder::LoadProperty(GateRef receiver, GateRef propertyLookupResult)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto ret = GetCircuit()->NewGate(circuit_->LoadProperty(), MachineType::I64,
|
||||
{ currentControl, currentDepend, receiver, offset }, GateType::AnyType());
|
||||
{ currentControl, currentDepend, receiver, propertyLookupResult },
|
||||
GateType::AnyType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::StoreProperty(GateRef receiver, GateRef offset, GateRef value)
|
||||
GateRef CircuitBuilder::StoreProperty(GateRef receiver, GateRef propertyLookupResult, GateRef value)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto ret = GetCircuit()->NewGate(circuit_->StoreProperty(), MachineType::I64,
|
||||
{ currentControl, currentDepend, receiver, offset, value }, GateType::AnyType());
|
||||
{ currentControl, currentDepend, receiver, propertyLookupResult, value },
|
||||
GateType::AnyType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
@ -705,6 +707,38 @@ GateRef CircuitBuilder::TypedAotCall(GateRef hirGate, std::vector<GateRef> args)
|
||||
return callGate;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CallGetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
|
||||
uint64_t pcOffset = acc_.GetPcOffset(hirGate);
|
||||
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->CallGetter(pcOffset), MachineType::I64,
|
||||
{ currentControl, currentDepend, receiver, propertyLookupResult },
|
||||
GateType::AnyType());
|
||||
currentLabel->SetControl(callGate);
|
||||
currentLabel->SetDepend(callGate);
|
||||
return callGate;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CallSetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult, GateRef value)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
|
||||
uint64_t pcOffset = acc_.GetPcOffset(hirGate);
|
||||
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->CallSetter(pcOffset), MachineType::I64,
|
||||
{ currentControl, currentDepend, receiver, propertyLookupResult, value },
|
||||
GateType::AnyType());
|
||||
currentLabel->SetControl(callGate);
|
||||
currentLabel->SetDepend(callGate);
|
||||
return callGate;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::HasPendingException(GateRef glue)
|
||||
{
|
||||
GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env_->IsArch32Bit()));
|
||||
|
@ -412,6 +412,7 @@ public:
|
||||
GateRef TaggedIsString(GateRef obj);
|
||||
GateRef TaggedIsStringOrSymbol(GateRef obj);
|
||||
inline GateRef GetGlobalConstantString(ConstantIndex index);
|
||||
inline GateRef LoadObjectFromWeakRef(GateRef x);
|
||||
|
||||
GateRef IsJSHClass(GateRef obj);
|
||||
GateRef HasPendingException(GateRef glue);
|
||||
@ -432,12 +433,14 @@ public:
|
||||
GateRef LoadElement(GateRef receiver, GateRef index);
|
||||
template<TypedStoreOp Op>
|
||||
GateRef StoreElement(GateRef receiver, GateRef index, GateRef value);
|
||||
GateRef LoadProperty(GateRef receiver, GateRef offset);
|
||||
GateRef StoreProperty(GateRef receiver, GateRef offset, GateRef value);
|
||||
GateRef LoadProperty(GateRef receiver, GateRef propertyLookupResult);
|
||||
GateRef StoreProperty(GateRef receiver, GateRef propertyLookupResult, GateRef value);
|
||||
GateRef LoadArrayLength(GateRef array);
|
||||
GateRef HeapAlloc(GateRef initialHClass, GateType type, RegionSpaceFlag flag);
|
||||
GateRef Construct(GateRef hirGate, std::vector<GateRef> args);
|
||||
GateRef TypedAotCall(GateRef hirGate, std::vector<GateRef> args);
|
||||
GateRef CallGetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult);
|
||||
GateRef CallSetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult, GateRef value);
|
||||
|
||||
// Object Operations
|
||||
inline GateRef LoadHClass(GateRef object);
|
||||
@ -484,6 +487,7 @@ public:
|
||||
GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef jsFunc, GateRef index, ConstPoolType type);
|
||||
GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module, GateRef index,
|
||||
ConstPoolType type);
|
||||
|
||||
void SetEnvironment(Environment *env)
|
||||
{
|
||||
env_ = env;
|
||||
|
@ -186,6 +186,8 @@ uint32_t GateAccessor::GetPcOffset(GateRef gate) const
|
||||
case OpCode::TYPED_CALL:
|
||||
case OpCode::CONSTRUCT:
|
||||
case OpCode::TYPEDAOTCALL:
|
||||
case OpCode::CALL_GETTER:
|
||||
case OpCode::CALL_SETTER:
|
||||
return static_cast<uint32_t>(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
default:
|
||||
break;
|
||||
@ -761,6 +763,13 @@ void GateAccessor::DeleteStateSplitAndFrameState(GateRef gate)
|
||||
|
||||
void GateAccessor::ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value)
|
||||
{
|
||||
if (value != Circuit::NullGate()) {
|
||||
GateType type = GetGateType(gate);
|
||||
if (!type.IsAnyType()) {
|
||||
SetGateType(value, type);
|
||||
}
|
||||
}
|
||||
|
||||
auto uses = Uses(gate);
|
||||
for (auto useIt = uses.begin(); useIt != uses.end();) {
|
||||
if (IsStateIn(useIt)) {
|
||||
|
@ -52,6 +52,7 @@ std::string GateMetaData::Str(OpCode opcode)
|
||||
GATE_META_DATA_LIST_WITH_SIZE(GATE_NAME_MAP)
|
||||
GATE_META_DATA_LIST_WITH_ONE_PARAMETER(GATE_NAME_MAP)
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET(GATE_NAME_MAP)
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(GATE_NAME_MAP)
|
||||
#undef GATE_NAME_MAP
|
||||
#define GATE_NAME_MAP(OP) { OpCode::OP, #OP },
|
||||
GATE_OPCODE_LIST(GATE_NAME_MAP)
|
||||
@ -281,6 +282,16 @@ const GateMetaData* GateMetaBuilder::NAME(uint64_t value, uint64_t pcOffset)
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_META)
|
||||
#undef DECLARE_GATE_META
|
||||
|
||||
#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
|
||||
const GateMetaData* GateMetaBuilder::NAME(uint64_t pcOffset) const \
|
||||
{ \
|
||||
auto meta = new (chunk_) OneParameterMetaData(OpCode::OP, R, S, D, V, pcOffset); \
|
||||
meta->SetKind(GateMetaData::Kind::MUTABLE_ONE_PARAMETER); \
|
||||
return meta; \
|
||||
}
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_META)
|
||||
#undef DECLARE_GATE_META
|
||||
|
||||
const GateMetaData* GateMetaBuilder::Arg(uint64_t value)
|
||||
{
|
||||
switch (value) {
|
||||
|
@ -81,7 +81,7 @@ enum class DeoptType : uint8_t {
|
||||
NOTARRAY,
|
||||
NOTSARRAY,
|
||||
NOTF32ARRAY,
|
||||
WRONGHCLASS,
|
||||
INCONSISTENTHCLASS,
|
||||
NOTNEWOBJ,
|
||||
NOTARRAYIDX,
|
||||
NOTF32ARRAYIDX,
|
||||
@ -222,12 +222,16 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(DebuggerBytecodeCall, DEBUGGER_BYTECODE_CALL, GateFlags::NONE_FLAG, 0, 1, value) \
|
||||
V(BuiltinsCallWithArgv, BUILTINS_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value) \
|
||||
V(BuiltinsCall, BUILTINS_CALL, GateFlags::NONE_FLAG, 0, 1, value) \
|
||||
V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value) \
|
||||
V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \
|
||||
V(TypedCall, TYPED_CALL, GateFlags::NONE_FLAG, 1, 1, value) \
|
||||
V(Construct, CONSTRUCT, GateFlags::NONE_FLAG, 1, 1, value) \
|
||||
V(TypedAotCall, TYPEDAOTCALL, GateFlags::NONE_FLAG, 1, 1, value) \
|
||||
V(TypedAotCall, TYPEDAOTCALL, GateFlags::NONE_FLAG, 1, 1, value)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(V) \
|
||||
V(CallGetter, CALL_GETTER, GateFlags::NONE_FLAG, 1, 1, 2) \
|
||||
V(CallSetter, CALL_SETTER, GateFlags::NONE_FLAG, 1, 1, 3)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_SIZE(V) \
|
||||
V(Merge, MERGE, GateFlags::CONTROL, value, 0, 0) \
|
||||
@ -242,7 +246,7 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(Int32OverflowCheck, INT32_OVERFLOW_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_VALUE(V) \
|
||||
V(Icmp, ICMP, GateFlags::NONE_FLAG, 0, 0, 2) \
|
||||
@ -275,6 +279,7 @@ enum class OpCode : uint8_t {
|
||||
GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_OPCODE)
|
||||
GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_OPCODE)
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_OPCODE)
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_OPCODE)
|
||||
#undef DECLARE_GATE_OPCODE
|
||||
#define DECLARE_GATE_OPCODE(NAME) NAME,
|
||||
GATE_OPCODE_LIST(DECLARE_GATE_OPCODE)
|
||||
|
@ -112,6 +112,11 @@ public:
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_META)
|
||||
#undef DECLARE_GATE_META
|
||||
|
||||
#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
|
||||
const GateMetaData* NAME(uint64_t pcOffset) const;
|
||||
GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_META)
|
||||
#undef DECLARE_GATE_META
|
||||
|
||||
explicit GateMetaBuilder(Chunk* chunk);
|
||||
const GateMetaData* JSBytecode(size_t valuesIn, EcmaOpcode opcode, uint32_t pcOffset, GateFlags flags)
|
||||
{
|
||||
@ -146,4 +151,4 @@ private:
|
||||
Chunk* chunk_;
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_GATE_META_DATA_CACHE_H
|
||||
#endif // ECMASCRIPT_COMPILER_GATE_META_DATA_CACHE_H
|
||||
|
@ -1683,7 +1683,7 @@ inline GateRef StubBuilder::GetDoubleOfTNumber(GateRef x)
|
||||
|
||||
inline GateRef StubBuilder::LoadObjectFromWeakRef(GateRef x)
|
||||
{
|
||||
return env_->GetBuilder()->PtrAdd(x, IntPtr(-JSTaggedValue::TAG_WEAK));
|
||||
return env_->GetBuilder()->LoadObjectFromWeakRef(x);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::ExtFloat32ToDouble(GateRef x)
|
||||
|
@ -648,10 +648,14 @@ void TSTypeLowering::LowerTypedLdObjByName(GateRef gate)
|
||||
acc_.DeleteStateSplitAndFrameState(gate);
|
||||
return;
|
||||
}
|
||||
JSTaggedValue hclass = tsManager_->GetHClassFromCache(hclassIndex);
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager_->GetHClassFromCache(hclassIndex).GetTaggedObject());
|
||||
if (!hclass->HasTSSubtyping()) { // slowpath
|
||||
acc_.DeleteStateSplitAndFrameState(gate);
|
||||
return;
|
||||
}
|
||||
|
||||
auto propertyOffset = tsManager_->GetPropertyOffset(hclass, prop);
|
||||
if (propertyOffset == -1) { // slowpath
|
||||
PropertyLookupResult plr = JSHClass::LookupProperty(thread, hclass, prop);
|
||||
if (!plr.IsFound()) { // slowpath
|
||||
acc_.DeleteStateSplitAndFrameState(gate);
|
||||
return;
|
||||
}
|
||||
@ -659,11 +663,16 @@ void TSTypeLowering::LowerTypedLdObjByName(GateRef gate)
|
||||
AddProfiling(gate);
|
||||
|
||||
GateRef hclassIndexGate = builder_.IntPtr(hclassIndex);
|
||||
GateRef propertyOffsetGate = builder_.IntPtr(propertyOffset);
|
||||
builder_.ObjectTypeCheck(receiverType, receiver, hclassIndexGate);
|
||||
|
||||
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
|
||||
GateRef result = builder_.LoadProperty(receiver, propertyOffsetGate);
|
||||
GateRef pfrGate = builder_.Int32(plr.GetData());
|
||||
GateRef result = Circuit::NullGate();
|
||||
if (LIKELY(!plr.IsAccessor())) {
|
||||
result = builder_.LoadProperty(receiver, pfrGate);
|
||||
} else {
|
||||
result = builder_.CallGetter(gate, receiver, pfrGate);
|
||||
}
|
||||
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
|
||||
}
|
||||
@ -695,10 +704,14 @@ void TSTypeLowering::LowerTypedStObjByName(GateRef gate, bool isThis)
|
||||
acc_.DeleteStateSplitAndFrameState(gate);
|
||||
return;
|
||||
}
|
||||
JSTaggedValue hclass = tsManager_->GetHClassFromCache(hclassIndex);
|
||||
JSHClass *hclass = JSHClass::Cast(tsManager_->GetHClassFromCache(hclassIndex).GetTaggedObject());
|
||||
if (!hclass->HasTSSubtyping()) { // slowpath
|
||||
acc_.DeleteStateSplitAndFrameState(gate);
|
||||
return;
|
||||
}
|
||||
|
||||
auto propertyOffset = tsManager_->GetPropertyOffset(hclass, prop);
|
||||
if (propertyOffset == -1) { // slowpath
|
||||
PropertyLookupResult plr = JSHClass::LookupProperty(thread, hclass, prop);
|
||||
if (!plr.IsFound() || plr.IsFunction()) { // slowpath
|
||||
acc_.DeleteStateSplitAndFrameState(gate);
|
||||
return;
|
||||
}
|
||||
@ -706,11 +719,15 @@ void TSTypeLowering::LowerTypedStObjByName(GateRef gate, bool isThis)
|
||||
AddProfiling(gate);
|
||||
|
||||
GateRef hclassIndexGate = builder_.IntPtr(hclassIndex);
|
||||
GateRef propertyOffsetGate = builder_.IntPtr(propertyOffset);
|
||||
builder_.ObjectTypeCheck(receiverType, receiver, hclassIndexGate);
|
||||
|
||||
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
|
||||
builder_.StoreProperty(receiver, propertyOffsetGate, value);
|
||||
GateRef pfrGate = builder_.Int32(plr.GetData());
|
||||
if (LIKELY(plr.IsLocal())) {
|
||||
builder_.StoreProperty(receiver, pfrGate, value);
|
||||
} else {
|
||||
builder_.CallSetter(gate, receiver, pfrGate, value);
|
||||
}
|
||||
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
|
||||
}
|
||||
@ -1076,7 +1093,7 @@ void TSTypeLowering::LowerTypedCallrange(GateRef gate)
|
||||
const size_t callTargetIndex = 1; // acc
|
||||
size_t argc = numArgs - callTargetIndex;
|
||||
GateRef func = acc_.GetValueIn(gate, argc);
|
||||
|
||||
|
||||
GateType funcType = acc_.GetGateType(func);
|
||||
if (!tsManager_->IsFunctionTypeKind(funcType)) {
|
||||
acc_.DeleteStateSplitAndFrameState(gate);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "ecmascript/deoptimizer/deoptimizer.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_native_pointer.h"
|
||||
#include "ecmascript/vtable.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void TypeLowering::RunTypeLowering()
|
||||
@ -82,11 +83,17 @@ void TypeLowering::LowerType(GateRef gate)
|
||||
LowerTypedUnaryOp(gate);
|
||||
break;
|
||||
case OpCode::LOAD_PROPERTY:
|
||||
LowerLoadProperty(gate, glue);
|
||||
LowerLoadProperty(gate);
|
||||
break;
|
||||
case OpCode::CALL_GETTER:
|
||||
LowerCallGetter(gate, glue);
|
||||
break;
|
||||
case OpCode::STORE_PROPERTY:
|
||||
LowerStoreProperty(gate, glue);
|
||||
break;
|
||||
case OpCode::CALL_SETTER:
|
||||
LowerCallSetter(gate, glue);
|
||||
break;
|
||||
case OpCode::LOAD_ARRAY_LENGTH:
|
||||
LowerLoadArrayLength(gate);
|
||||
break;
|
||||
@ -258,25 +265,53 @@ void TypeLowering::LowerObjectTypeCheck(GateRef gate)
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
auto type = acc_.GetParamGateType(gate);
|
||||
if (tsManager_->IsClassInstanceTypeKind(type)) {
|
||||
LowerClassInstanceCheck(gate);
|
||||
LowerTSSubtypingCheck(gate);
|
||||
} else {
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void TypeLowering::LowerClassInstanceCheck(GateRef gate)
|
||||
void TypeLowering::LowerTSSubtypingCheck(GateRef gate)
|
||||
{
|
||||
GateRef frameState = GetFrameState(gate);
|
||||
|
||||
ArgumentAccessor argAcc(circuit_);
|
||||
GateRef jsFunc = argAcc.GetCommonArgGate(CommonArgIdx::FUNC);
|
||||
auto receiver = acc_.GetValueIn(gate, 0);
|
||||
auto receiverHClass = builder_.LoadHClass(receiver);
|
||||
auto hclassOffset = acc_.GetValueIn(gate, 1);
|
||||
GateRef hclass = GetObjectFromConstPool(jsFunc, hclassOffset);
|
||||
GateRef check = builder_.Equal(receiverHClass, hclass);
|
||||
builder_.DeoptCheck(check, frameState, DeoptType::WRONGHCLASS);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef aotHCIndex = acc_.GetValueIn(gate, 1);
|
||||
|
||||
Label receiverIsHeapObject(&builder_);
|
||||
Label exit(&builder_);
|
||||
|
||||
DEFVAlUE(check, (&builder_), VariableType::BOOL(), builder_.False());
|
||||
builder_.Branch(builder_.TaggedIsHeapObject(receiver), &receiverIsHeapObject, &exit);
|
||||
|
||||
builder_.Bind(&receiverIsHeapObject);
|
||||
{
|
||||
JSTaggedValue aotHC = tsManager_->GetHClassFromCache(acc_.TryGetValue(aotHCIndex));
|
||||
ASSERT(aotHC.IsJSHClass());
|
||||
|
||||
int32_t level = JSHClass::Cast(aotHC.GetTaggedObject())->GetLevel();
|
||||
ASSERT(level >= 0);
|
||||
GateRef levelGate = builder_.Int32(level);
|
||||
|
||||
GateRef receiverHC = builder_.LoadHClass(receiver);
|
||||
GateRef supers = LoadSupers(receiverHC);
|
||||
GateRef length = GetLengthFromSupers(supers);
|
||||
|
||||
// Nextly, consider remove level check by guaranteeing not read illegal addresses.
|
||||
Label levelValid(&builder_);
|
||||
builder_.Branch(builder_.Int32LessThan(levelGate, length), &levelValid, &exit);
|
||||
builder_.Bind(&levelValid);
|
||||
{
|
||||
GateRef aotHCGate = GetObjectFromConstPool(jsFunc, aotHCIndex);
|
||||
check = builder_.Equal(aotHCGate, GetValueFromSupers(supers, levelGate));
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
}
|
||||
builder_.Bind(&exit);
|
||||
builder_.DeoptCheck(*check, frameState, DeoptType::INCONSISTENTHCLASS);
|
||||
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
@ -466,36 +501,111 @@ GateRef TypeLowering::GetObjectFromConstPool(GateRef jsFunc, GateRef index)
|
||||
return builder_.GetValueFromTaggedArray(constPool, index);
|
||||
}
|
||||
|
||||
void TypeLowering::LowerLoadProperty(GateRef gate, [[maybe_unused]] GateRef glue)
|
||||
void TypeLowering::LowerLoadProperty(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
Label hole(&builder_);
|
||||
Label exit(&builder_);
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: receiver, plr
|
||||
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef offset = acc_.GetValueIn(gate, 1);
|
||||
result = builder_.Load(VariableType::JS_ANY(), receiver, offset);
|
||||
// simplify the process, need to query the vtable to complete the whole process later
|
||||
builder_.Branch(builder_.IsSpecial(*result, JSTaggedValue::VALUE_HOLE), &hole, &exit);
|
||||
builder_.Bind(&hole);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
ASSERT(plr.IsLocal() || plr.IsFunction());
|
||||
GateRef offset = builder_.IntPtr(plr.GetOffset());
|
||||
|
||||
if (plr.IsLocal()) {
|
||||
Label returnUndefined(&builder_);
|
||||
Label exit(&builder_);
|
||||
result = builder_.Load(VariableType::JS_ANY(), receiver, offset);
|
||||
builder_.Branch(builder_.IsSpecial(*result, JSTaggedValue::VALUE_HOLE), &returnUndefined, &exit);
|
||||
builder_.Bind(&returnUndefined);
|
||||
{
|
||||
result = builder_.UndefineConstant();
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(&exit);
|
||||
} else {
|
||||
GateRef vtable = LoadVTable(receiver);
|
||||
GateRef itemOwner = GetOwnerFromVTable(vtable, offset);
|
||||
GateRef itemOffset = GetOffsetFromVTable(vtable, offset);
|
||||
result = builder_.Load(VariableType::JS_ANY(), itemOwner, itemOffset);
|
||||
}
|
||||
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
|
||||
}
|
||||
|
||||
void TypeLowering::LowerCallGetter(GateRef gate, GateRef glue)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: receiver, plr
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
|
||||
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
ASSERT(plr.IsAccessor());
|
||||
GateRef offset = builder_.IntPtr(plr.GetOffset());
|
||||
GateRef vtable = LoadVTable(receiver);
|
||||
GateRef itemOwner = GetOwnerFromVTable(vtable, offset);
|
||||
GateRef itemOffset = GetOffsetFromVTable(vtable, offset);
|
||||
|
||||
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
|
||||
Label callGetter(&builder_);
|
||||
Label exit(&builder_);
|
||||
GateRef accessor = builder_.Load(VariableType::JS_ANY(), itemOwner, itemOffset);
|
||||
GateRef getter = builder_.Load(VariableType::JS_ANY(), accessor,
|
||||
builder_.IntPtr(AccessorData::GETTER_OFFSET));
|
||||
builder_.Branch(builder_.IsSpecial(getter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callGetter);
|
||||
builder_.Bind(&callGetter);
|
||||
{
|
||||
result = builder_.UndefineConstant();
|
||||
result = CallAccessor(glue, gate, getter, receiver, AccessorMode::GETTER);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(&exit);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
|
||||
ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
|
||||
}
|
||||
|
||||
void TypeLowering::LowerStoreProperty(GateRef gate, GateRef glue)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: receiver, plr, value
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef offset = acc_.GetValueIn(gate, 1);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
|
||||
GateRef value = acc_.GetValueIn(gate, 2);
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
ASSERT(plr.IsLocal());
|
||||
GateRef offset = builder_.IntPtr(plr.GetOffset());
|
||||
builder_.Store(VariableType::JS_ANY(), glue, receiver, offset, value);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void TypeLowering::LowerCallSetter(GateRef gate, GateRef glue)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: receiver, plr, value
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
|
||||
GateRef value = acc_.GetValueIn(gate, 2);
|
||||
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
ASSERT(plr.IsAccessor());
|
||||
GateRef offset = builder_.IntPtr(plr.GetOffset());
|
||||
GateRef vtable = LoadVTable(receiver);
|
||||
GateRef itemOwner = GetOwnerFromVTable(vtable, offset);
|
||||
GateRef itemOffset = GetOffsetFromVTable(vtable, offset);
|
||||
|
||||
Label callSetter(&builder_);
|
||||
Label exit(&builder_);
|
||||
GateRef accessor = builder_.Load(VariableType::JS_ANY(), itemOwner, itemOffset);
|
||||
GateRef setter = builder_.Load(VariableType::JS_ANY(), accessor, builder_.IntPtr(AccessorData::SETTER_OFFSET));
|
||||
builder_.Branch(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
|
||||
builder_.Bind(&callSetter);
|
||||
{
|
||||
CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(&exit);
|
||||
ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void TypeLowering::LowerLoadArrayLength(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
@ -2972,4 +3082,71 @@ void TypeLowering::LowerGetSuperConstructor(GateRef gate)
|
||||
GateRef superCtor = builder_.Load(VariableType::JS_ANY(), hclass, protoOffset);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), superCtor);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::LoadVTable(GateRef object)
|
||||
{
|
||||
GateRef hclass = builder_.LoadHClass(object);
|
||||
return builder_.Load(VariableType::JS_ANY(), hclass, builder_.IntPtr(JSHClass::VTABLE_OFFSET));
|
||||
}
|
||||
|
||||
GateRef TypeLowering::GetOwnerFromVTable(GateRef vtable, GateRef offset)
|
||||
{
|
||||
GateRef dataOffset = builder_.PtrAdd(offset, builder_.IntPtr(VTable::TupleItem::OWNER));
|
||||
return builder_.GetValueFromTaggedArray(vtable, dataOffset);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::GetOffsetFromVTable(GateRef vtable, GateRef offset)
|
||||
{
|
||||
GateRef dataOffset = builder_.PtrAdd(offset, builder_.IntPtr(VTable::TupleItem::OFFSET));
|
||||
return builder_.TaggedGetInt(builder_.GetValueFromTaggedArray(vtable, dataOffset));
|
||||
}
|
||||
|
||||
GateRef TypeLowering::LoadSupers(GateRef hclass)
|
||||
{
|
||||
return builder_.Load(VariableType::JS_ANY(), hclass, builder_.IntPtr(JSHClass::SUPERS_OFFSET));
|
||||
}
|
||||
|
||||
GateRef TypeLowering::GetLengthFromSupers(GateRef supers)
|
||||
{
|
||||
GateRef length = builder_.GetValueFromTaggedArray(supers, builder_.Int32(WeakVector::END_INDEX));
|
||||
return builder_.TaggedGetInt(length);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::GetValueFromSupers(GateRef supers, GateRef index)
|
||||
{
|
||||
GateRef val = builder_.GetValueFromTaggedArray(supers,
|
||||
builder_.Int32Add(index, builder_.Int32(WeakVector::ELEMENTS_START_INDEX)));
|
||||
return builder_.LoadObjectFromWeakRef(val);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::CallAccessor(GateRef glue, GateRef gate, GateRef function, GateRef receiver, AccessorMode mode,
|
||||
GateRef value)
|
||||
{
|
||||
const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCall));
|
||||
GateRef target = builder_.IntPtr(RTSTUB_ID(JSCall));
|
||||
GateRef envArg = builder_.Undefined();
|
||||
GateRef newTarget = builder_.Undefined();
|
||||
GateRef argc = builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS + (mode == AccessorMode::SETTER ? 1 : 0)); // 1: value
|
||||
std::vector<GateRef> args { glue, envArg, argc, function, newTarget, receiver };
|
||||
if (mode == AccessorMode::SETTER) {
|
||||
args.emplace_back(value);
|
||||
}
|
||||
|
||||
return builder_.Call(cs, glue, target, builder_.GetDepend(), args, gate);
|
||||
}
|
||||
|
||||
void TypeLowering::ReplaceHirWithPendingException(GateRef hirGate, GateRef glue, GateRef state, GateRef depend,
|
||||
GateRef value)
|
||||
{
|
||||
auto condition = builder_.HasPendingException(glue);
|
||||
GateRef ifBranch = builder_.Branch(state, condition);
|
||||
GateRef ifTrue = builder_.IfTrue(ifBranch);
|
||||
GateRef ifFalse = builder_.IfFalse(ifBranch);
|
||||
GateRef eDepend = builder_.DependRelay(ifTrue, depend);
|
||||
GateRef sDepend = builder_.DependRelay(ifFalse, depend);
|
||||
|
||||
StateDepend success(ifFalse, sDepend);
|
||||
StateDepend exception(ifTrue, eDepend);
|
||||
acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -179,15 +179,17 @@ private:
|
||||
void LowerTypedDecOverflowCheck(GateRef gate);
|
||||
void LowerTypedNegOverflowCheck(GateRef gate);
|
||||
void LowerObjectTypeCheck(GateRef gate);
|
||||
void LowerClassInstanceCheck(GateRef gate);
|
||||
void LowerTSSubtypingCheck(GateRef gate);
|
||||
void LowerFloat32ArrayCheck(GateRef gate, GateRef glue);
|
||||
void LowerArrayCheck(GateRef gate, GateRef glue);
|
||||
void LowerStableArrayCheck(GateRef gate, GateRef glue);
|
||||
void LowerTypedArrayCheck(GateRef gate, GateRef glue);
|
||||
void LowerFloat32ArrayIndexCheck(GateRef gate);
|
||||
void LowerArrayIndexCheck(GateRef gate);
|
||||
void LowerLoadProperty(GateRef gate, GateRef glue);
|
||||
void LowerLoadProperty(GateRef gate);
|
||||
void LowerCallGetter(GateRef gate, GateRef glue);
|
||||
void LowerStoreProperty(GateRef gate, GateRef glue);
|
||||
void LowerCallSetter(GateRef gate, GateRef glue);
|
||||
void LowerLoadArrayLength(GateRef gate);
|
||||
void LowerStoreElement(GateRef gate, GateRef glue);
|
||||
void LowerLoadElement(GateRef gate);
|
||||
@ -208,6 +210,15 @@ private:
|
||||
GateRef LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
|
||||
bool useLabel = false);
|
||||
|
||||
enum AccessorMode {
|
||||
GETTER,
|
||||
SETTER,
|
||||
};
|
||||
|
||||
GateRef CallAccessor(GateRef glue, GateRef gate, GateRef function, GateRef receiver, AccessorMode mode,
|
||||
GateRef value = Circuit::NullGate());
|
||||
void ReplaceHirWithPendingException(GateRef hirGate, GateRef glue, GateRef state, GateRef depend, GateRef value);
|
||||
|
||||
template<OpCode Op>
|
||||
GateRef CalculateNumbers(GateRef left, GateRef right, GateType leftType, GateType rightType);
|
||||
template<OpCode Op>
|
||||
@ -247,6 +258,13 @@ private:
|
||||
return acc_.GetFrameState(gate);
|
||||
}
|
||||
|
||||
GateRef LoadVTable(GateRef object);
|
||||
GateRef GetOwnerFromVTable(GateRef vtable, GateRef offset);
|
||||
GateRef GetOffsetFromVTable(GateRef vtable, GateRef offset);
|
||||
GateRef LoadSupers(GateRef hclass);
|
||||
GateRef GetLengthFromSupers(GateRef supers);
|
||||
GateRef GetValueFromSupers(GateRef supers, GateRef index);
|
||||
|
||||
Circuit *circuit_;
|
||||
GateAccessor acc_;
|
||||
CircuitBuilder builder_;
|
||||
|
@ -262,8 +262,8 @@ std::string Deoptimizier::DisplayItems(kungfu::DeoptType type)
|
||||
return "NOT SARRAY";
|
||||
case kungfu::DeoptType::NOTF32ARRAY:
|
||||
return "NOT F32ARRAY";
|
||||
case kungfu::DeoptType::WRONGHCLASS:
|
||||
return "WRONG HCLASS";
|
||||
case kungfu::DeoptType::INCONSISTENTHCLASS:
|
||||
return "INCONSISTENT HCLASS";
|
||||
case kungfu::DeoptType::NOTNEWOBJ:
|
||||
return "NOT NEWOBJ TYPE";
|
||||
case kungfu::DeoptType::NOTARRAYIDX:
|
||||
@ -335,4 +335,4 @@ JSTaggedType Deoptimizier::ConstructAsmInterpretFrame(kungfu::DeoptType type)
|
||||
frameWriter.PushRawValue(outputCount);
|
||||
return reinterpret_cast<JSTaggedType>(frameWriter.GetTop());
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -224,6 +224,15 @@ inline void JSHClass::Copy(const JSThread *thread, const JSHClass *jshclass)
|
||||
SetBitField(jshclass->GetBitField());
|
||||
SetNumberOfProps(jshclass->NumberOfProps());
|
||||
}
|
||||
|
||||
inline int JSHClass::FindPropertyEntry(const JSThread *thread, JSHClass *hclass, JSTaggedValue key)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
LayoutInfo *layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
|
||||
uint32_t propsNumber = hclass->NumberOfProps();
|
||||
int entry = layout->FindElementWithCache(thread, hclass, key, propsNumber);
|
||||
return entry;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_JS_HCLASS_INL_H
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "ecmascript/js_object-inl.h"
|
||||
#include "ecmascript/js_symbol.h"
|
||||
#include "ecmascript/mem/c_containers.h"
|
||||
#include "ecmascript/subtyping_operator.h"
|
||||
#include "ecmascript/tagged_array-inl.h"
|
||||
#include "ecmascript/weak_vector.h"
|
||||
|
||||
@ -273,6 +274,11 @@ void JSHClass::AddProperty(const JSThread *thread, const JSHandle<JSObject> &obj
|
||||
JSHClass::NotifyHclassChanged(thread, jshclass, newJsHClass);
|
||||
#endif
|
||||
obj->SetClass(*newJsHClass);
|
||||
|
||||
// Maintaining subtyping is no longer required when transition succeeds.
|
||||
if (jshclass->HasTSSubtyping()) {
|
||||
SubtypingOperator::TryMaintainTSSubtyping(thread, jshclass, newJsHClass, key);
|
||||
}
|
||||
}
|
||||
|
||||
JSHandle<JSHClass> JSHClass::TransitionExtension(const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||
@ -522,14 +528,18 @@ JSHandle<ProtoChangeDetails> JSHClass::GetProtoChangeDetails(const JSThread *thr
|
||||
return GetProtoChangeDetails(thread, jshclass);
|
||||
}
|
||||
|
||||
void JSHClass::MarkProtoChanged([[maybe_unused]] const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||
void JSHClass::MarkProtoChanged(const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||
{
|
||||
ASSERT(jshclass->IsPrototype() || jshclass->HasTSInheritInfo());
|
||||
ASSERT(jshclass->IsPrototype() || jshclass->HasTSSubtyping());
|
||||
JSTaggedValue markerValue = jshclass->GetProtoChangeMarker();
|
||||
if (markerValue.IsProtoChangeMarker()) {
|
||||
ProtoChangeMarker *protoChangeMarker = ProtoChangeMarker::Cast(markerValue.GetTaggedObject());
|
||||
protoChangeMarker->SetHasChanged(true);
|
||||
}
|
||||
|
||||
if (jshclass->HasTSSubtyping()) {
|
||||
jshclass->InitTSInheritInfo(thread);
|
||||
}
|
||||
}
|
||||
|
||||
void JSHClass::NoticeThroughChain(const JSThread *thread, const JSHandle<JSHClass> &jshclass)
|
||||
@ -570,7 +580,7 @@ void JSHClass::RefreshUsers(const JSThread *thread, const JSHandle<JSHClass> &ol
|
||||
}
|
||||
}
|
||||
|
||||
bool JSHClass::HasTSInheritInfo() const
|
||||
bool JSHClass::HasTSSubtyping() const
|
||||
{
|
||||
// if fill TS inherit info, supers must not be empty
|
||||
WeakVector *supers = WeakVector::Cast(GetSupers().GetTaggedObject());
|
||||
@ -579,6 +589,56 @@ bool JSHClass::HasTSInheritInfo() const
|
||||
|
||||
bool JSHClass::IsTSIHCWithInheritInfo() const
|
||||
{
|
||||
return IsTS() && !IsPrototype() && HasTSInheritInfo();
|
||||
return IsTS() && !IsPrototype() && HasTSSubtyping();
|
||||
}
|
||||
|
||||
PropertyLookupResult JSHClass::LookupProperty(const JSThread *thread, JSHClass *hclass, JSTaggedValue key)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
ASSERT(hclass->IsTS());
|
||||
|
||||
PropertyLookupResult result;
|
||||
int entry = JSHClass::FindPropertyEntry(thread, hclass, key);
|
||||
|
||||
// found in local
|
||||
if (entry != -1) {
|
||||
result.SetIsFound(true);
|
||||
result.SetIsLocal(true);
|
||||
uint32_t offset = hclass->GetInlinedPropertiesOffset(entry);
|
||||
result.SetOffset(offset);
|
||||
return result;
|
||||
}
|
||||
|
||||
// found in vtable
|
||||
JSHandle<VTable> vtable(thread, hclass->GetVTable());
|
||||
entry = vtable->GetTupleIndexByName(key);
|
||||
if (entry != -1) {
|
||||
result.SetIsVtable();
|
||||
uint32_t offset = entry * VTable::TUPLE_SIZE;
|
||||
result.SetOffset(offset);
|
||||
if (vtable->IsAccessor(entry)) {
|
||||
result.SetIsAccessor(true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// not fuond
|
||||
result.SetIsFound(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
void JSHClass::CopyTSInheritInfo(const JSThread *thread, const JSHandle<JSHClass> &oldHClass,
|
||||
JSHandle<JSHClass> &newHClass)
|
||||
{
|
||||
JSHandle<WeakVector> supers(thread, oldHClass->GetSupers());
|
||||
JSHandle<WeakVector> copySupers = WeakVector::Copy(thread, supers);
|
||||
newHClass->SetSupers(thread, copySupers);
|
||||
|
||||
uint8_t level = oldHClass->GetLevel();
|
||||
newHClass->SetLevel(level);
|
||||
|
||||
JSHandle<VTable> vtable(thread, oldHClass->GetVTable());
|
||||
JSHandle<VTable> copyVtable = VTable::Copy(thread, vtable);
|
||||
newHClass->SetVTable(thread, copyVtable);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -60,6 +60,7 @@
|
||||
*/
|
||||
namespace panda::ecmascript {
|
||||
class ProtoChangeDetails;
|
||||
class PropertyLookupResult;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define JSTYPE_DECL /* //////////////////////////////////////////////////////////////////////////////-PADDING */ \
|
||||
@ -369,10 +370,13 @@ public:
|
||||
|
||||
void InitTSInheritInfo(const JSThread *thread);
|
||||
|
||||
bool HasTSInheritInfo() const;
|
||||
bool HasTSSubtyping() const;
|
||||
|
||||
bool IsTSIHCWithInheritInfo() const;
|
||||
|
||||
static void CopyTSInheritInfo(const JSThread *thread, const JSHandle<JSHClass> &oldHClass,
|
||||
JSHandle<JSHClass> &newHClass);
|
||||
|
||||
inline void ClearBitField()
|
||||
{
|
||||
SetBitField(0UL);
|
||||
@ -1577,6 +1581,11 @@ public:
|
||||
uint32_t bits = GetBitField1();
|
||||
return HasDeletePropertyBit::Decode(bits);
|
||||
}
|
||||
|
||||
inline static int FindPropertyEntry(const JSThread *thread, JSHClass *hclass, JSTaggedValue key);
|
||||
|
||||
static PropertyLookupResult LookupProperty(const JSThread *thread, JSHClass *hclass, JSTaggedValue key);
|
||||
|
||||
static constexpr size_t PROTOTYPE_OFFSET = TaggedObjectSize();
|
||||
ACCESSORS(Proto, PROTOTYPE_OFFSET, LAYOUT_OFFSET);
|
||||
ACCESSORS(Layout, LAYOUT_OFFSET, TRANSTIONS_OFFSET);
|
||||
@ -1630,6 +1639,84 @@ private:
|
||||
friend class RuntimeStubs;
|
||||
};
|
||||
static_assert(JSHClass::BIT_FIELD_OFFSET % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT) == 0);
|
||||
|
||||
// record property look up info in local and vtable
|
||||
class PropertyLookupResult {
|
||||
public:
|
||||
using IsFoundBit = BitField<bool, 0, 1>;
|
||||
using IsLocalBit = IsFoundBit::NextFlag;
|
||||
using IsAccessorBit = IsLocalBit::NextFlag;
|
||||
using OffsetBits = IsAccessorBit::NextField<uint32_t, PropertyAttributes::OFFSET_BITFIELD_NUM>;
|
||||
|
||||
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 IsLocal() const
|
||||
{
|
||||
return IsLocalBit::Get(data_);
|
||||
}
|
||||
|
||||
inline void SetIsLocal(bool flag)
|
||||
{
|
||||
IsLocalBit::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 uint32_t GetData() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t data_ {0};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_JS_HCLASS_H
|
||||
|
@ -162,6 +162,11 @@ JSHandle<NameDictionary> JSObject::TransitionToDictionary(const JSThread *thread
|
||||
|
||||
if (i < numberInlinedProps) {
|
||||
value = receiver->GetPropertyInlinedProps(i);
|
||||
// If delete a property in hclass which has subtyping info and not prototype, only set value as hole and
|
||||
// not remove. When transition to dictionary, exclude it.
|
||||
if (value.IsHole()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
value = array->Get(i - numberInlinedProps);
|
||||
}
|
||||
@ -282,7 +287,9 @@ void JSObject::DeletePropertyInternal(JSThread *thread, const JSHandle<JSObject>
|
||||
}
|
||||
|
||||
if (!array->IsDictionaryMode()) {
|
||||
if (obj->GetJSHClass()->IsTS()) {
|
||||
JSHClass *hclass = obj->GetJSHClass();
|
||||
// To maintain TS inherit info, not change hclass, just set hole.
|
||||
if (hclass->HasTSSubtyping() && !hclass->IsPrototype()) {
|
||||
obj->SetPropertyInlinedProps(thread, index, JSTaggedValue::Hole());
|
||||
return;
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ JSHandle<JSTaggedValue> SourceTextModule::ResolveCjsExport(JSThread *thread, con
|
||||
// Get layoutInfo and compare the input and output names of files
|
||||
JSHandle<LayoutInfo> layoutInfo(thread, jsHclass->GetLayout());
|
||||
if (layoutInfo->NumberOfElements() != 0) {
|
||||
JSHandle<JSTaggedValue> resolution = ResolveCjsLocalExport(thread, layoutInfo, exportName, module);
|
||||
JSHandle<JSTaggedValue> resolution = ResolveCjsLocalExport(thread, jsHclass, exportName, module);
|
||||
if (!resolution->IsUndefined()) {
|
||||
return resolution;
|
||||
}
|
||||
@ -393,7 +393,7 @@ int SourceTextModule::InnerModuleInstantiation(JSThread *thread, const JSHandle<
|
||||
ASSERT(moduleRecordName.IsString());
|
||||
JSHandle<JSTaggedValue> requiredVal =
|
||||
SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX);
|
||||
requiredModule.Update(JSHandle<SourceTextModule>::Cast(requiredVal));
|
||||
requestedModules->Set(thread, idx, requiredModule->GetEcmaModuleRecordName());
|
||||
}
|
||||
@ -1215,13 +1215,12 @@ void SourceTextModule::AddExportName(JSThread *thread, const JSTaggedValue &expo
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> SourceTextModule::ResolveCjsLocalExport(JSThread *thread,
|
||||
JSHandle<LayoutInfo> layoutInfo,
|
||||
const JSHandle<JSHClass> &hclass,
|
||||
const JSHandle<JSTaggedValue> &exportName,
|
||||
const JSHandle<SourceTextModule> &module)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
int propertiesNumber = layoutInfo->NumberOfElements();
|
||||
int idx = layoutInfo->FindElementWithCache(thread, nullptr, exportName.GetTaggedValue(), propertiesNumber);
|
||||
int idx = JSHClass::FindPropertyEntry(thread, *hclass, exportName.GetTaggedValue());
|
||||
if (idx != -1) {
|
||||
return JSHandle<JSTaggedValue>::Cast(factory->NewResolvedIndexBindingRecord(module, idx));
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ private:
|
||||
const JSHandle<JSTaggedValue> &exportName,
|
||||
const JSHandle<SourceTextModule> &module);
|
||||
static JSHandle<JSTaggedValue> ResolveCjsLocalExport(JSThread *thread,
|
||||
JSHandle<LayoutInfo> layoutInfo,
|
||||
const JSHandle<JSHClass> &hclass,
|
||||
const JSHandle<JSTaggedValue> &exportName,
|
||||
const JSHandle<SourceTextModule> &module);
|
||||
static bool CheckCircularImport(const JSHandle<SourceTextModule> &module,
|
||||
|
@ -67,10 +67,9 @@ JSTaggedValue ObjectFastOperator::GetPropertyByName(JSThread *thread, JSTaggedVa
|
||||
if (LIKELY(!hclass->IsDictionaryMode())) {
|
||||
ASSERT(!TaggedArray::Cast(JSObject::Cast(holder)->GetProperties().GetTaggedObject())->IsDictionaryMode());
|
||||
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
|
||||
uint32_t propsNumber = hclass->NumberOfProps();
|
||||
int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber);
|
||||
int entry = JSHClass::FindPropertyEntry(thread, hclass, key);
|
||||
if (entry != -1) {
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
|
||||
PropertyAttributes attr(layoutInfo->GetAttr(entry));
|
||||
ASSERT(static_cast<int>(attr.GetOffset()) == entry);
|
||||
auto value = JSObject::Cast(holder)->GetProperty(hclass, attr);
|
||||
@ -138,11 +137,10 @@ JSTaggedValue ObjectFastOperator::SetPropertyByName(JSThread *thread, JSTaggedVa
|
||||
if (LIKELY(!hclass->IsDictionaryMode())) {
|
||||
ASSERT(!TaggedArray::Cast(JSObject::Cast(holder)->GetProperties().GetTaggedObject())->IsDictionaryMode());
|
||||
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
|
||||
|
||||
uint32_t propsNumber = hclass->NumberOfProps();
|
||||
int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber);
|
||||
int entry = JSHClass::FindPropertyEntry(thread, hclass, key);
|
||||
if (entry != -1) {
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
|
||||
PropertyAttributes attr(layoutInfo->GetAttr(entry));
|
||||
ASSERT(static_cast<int>(attr.GetOffset()) == entry);
|
||||
if (UNLIKELY(attr.IsAccessor())) {
|
||||
@ -798,4 +796,4 @@ bool ObjectFastOperator::GetNumFromString(const char *str, int len, int *index,
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif // ECMASCRIPT_OBJECT_FAST_OPERATOR_INL_H
|
||||
#endif // ECMASCRIPT_OBJECT_FAST_OPERATOR_INL_H
|
||||
|
@ -335,13 +335,12 @@ void ObjectOperator::LookupPropertyInlinedProps(const JSHandle<JSObject> &obj)
|
||||
TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
|
||||
if (!array->IsDictionaryMode()) {
|
||||
JSHClass *jshclass = obj->GetJSHClass();
|
||||
JSTaggedValue attrs = jshclass->GetLayout();
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(attrs.GetTaggedObject());
|
||||
uint32_t propsNumber = jshclass->NumberOfProps();
|
||||
int entry = layoutInfo->FindElementWithCache(thread_, jshclass, key_.GetTaggedValue(), propsNumber);
|
||||
int entry = JSHClass::FindPropertyEntry(thread_, jshclass, key_.GetTaggedValue());
|
||||
if (entry == -1) {
|
||||
return;
|
||||
}
|
||||
JSTaggedValue attrs = jshclass->GetLayout();
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(attrs.GetTaggedObject());
|
||||
PropertyAttributes attr(layoutInfo->GetAttr(entry));
|
||||
ASSERT(entry == static_cast<int>(attr.GetOffset()));
|
||||
JSTaggedValue value;
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "ecmascript/message_string.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler.h"
|
||||
#include "ecmascript/subtyping_operator.h"
|
||||
#include "ecmascript/tagged_dictionary.h"
|
||||
#include "ecmascript/tagged_node.h"
|
||||
#include "ecmascript/ts_types/ts_manager.h"
|
||||
@ -345,6 +346,10 @@ DEF_RUNTIME_STUBS(UpdateLayOutAndAddTransition)
|
||||
|
||||
// 5. Add newClass to old hclass's transitions.
|
||||
JSHClass::AddTransitions(thread, oldHClassHandle, newHClassHandle, keyHandle, attrValue);
|
||||
|
||||
if (oldHClassHandle->HasTSSubtyping()) {
|
||||
SubtypingOperator::TryMaintainTSSubtyping(thread, oldHClassHandle, newHClassHandle, keyHandle);
|
||||
}
|
||||
return JSTaggedValue::Hole().GetRawData();
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/ic/proto_change_details.h"
|
||||
#include "ecmascript/subtyping_operator-inl.h"
|
||||
#include "ecmascript/vtable.h"
|
||||
|
||||
@ -196,4 +197,41 @@ void SubtypingOperator::AddSuper(const JSThread *thread, const JSHandle<JSHClass
|
||||
iHClassVal, WeakVector::ElementType::WEAK);
|
||||
iHClass->SetSupers(thread, newSupers);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
// when add property in local, try maintain.
|
||||
void SubtypingOperator::TryMaintainTSSubtyping(const JSThread *thread, const JSHandle<JSHClass> &oldHClass,
|
||||
JSHandle<JSHClass> &newHClass, const JSHandle<JSTaggedValue> &key)
|
||||
{
|
||||
if (!key->IsString()) { // symbol
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(!oldHClass->IsPrototype()); // normal object hclass
|
||||
JSHandle<VTable> vtable(thread, oldHClass->GetVTable());
|
||||
ASSERT(vtable->GetNumberOfTuples() > 0); // there have default key 'constructor' at least
|
||||
|
||||
if (vtable->Find(key.GetTaggedValue())) { // new key shadows vtable property
|
||||
LOG_ECMA(DEBUG) << "TryMaintainTSSubtyping failed, key: "
|
||||
<< ConvertToString(EcmaString::Cast(key->GetTaggedObject()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Add newHClass to phc's listeners
|
||||
JSHandle<JSTaggedValue> prototype(thread, oldHClass->GetPrototype());
|
||||
ASSERT(prototype->IsClassPrototype());
|
||||
JSHandle<JSHClass> phc(thread, prototype->GetTaggedObject()->GetClass());
|
||||
// If hclass has inherit info, it had been registered on proto chain, details and listeners must not be Undefined.
|
||||
JSHandle<ProtoChangeDetails> details(thread, phc->GetProtoChangeDetails());
|
||||
JSHandle<ChangeListener> listeners(thread, details->GetChangeListener());
|
||||
uint32_t registerIndex = 0;
|
||||
JSHandle<ChangeListener> newListeners = ChangeListener::Add(thread, listeners, newHClass, ®isterIndex);
|
||||
if (UNLIKELY(registerIndex == TaggedArray::MAX_ARRAY_INDEX)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// maintaining succeeds
|
||||
details->SetChangeListener(thread, newListeners);
|
||||
|
||||
JSHClass::CopyTSInheritInfo(thread, oldHClass, newHClass);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -32,6 +32,9 @@ public:
|
||||
|
||||
static void GenVTable(const JSThread *thread, const JSHandle<JSHClass> &ihcHandle,
|
||||
const JSHandle<JSHClass> &phcHandle, const JSHandle<JSHClass> &eIhcHandle);
|
||||
|
||||
static void TryMaintainTSSubtyping(const JSThread *thread, const JSHandle<JSHClass> &oldHClass,
|
||||
JSHandle<JSHClass> &newHClass, const JSHandle<JSTaggedValue> &key);
|
||||
private:
|
||||
static constexpr uint8_t MAX_LEVEL = 1 << JSHClass::LEVEL_BTTFIELD_NUM;
|
||||
|
||||
@ -80,4 +83,4 @@ private:
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
#endif // ECMASCRIPT_SUBTYPING_OPERATOR_H
|
||||
#endif // ECMASCRIPT_SUBTYPING_OPERATOR_H
|
||||
|
@ -142,21 +142,6 @@ JSTaggedValue TSManager::GetHClassFromCache(uint32_t index)
|
||||
return JSTaggedValue(hcVec[index - constantPool->GetCacheLength()]);
|
||||
}
|
||||
|
||||
int TSManager::GetPropertyOffset(JSTaggedValue hclass, JSTaggedValue key)
|
||||
{
|
||||
JSHClass *hc = JSHClass::Cast(hclass.GetTaggedObject());
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(hc->GetLayout().GetTaggedObject());
|
||||
uint32_t propsNumber = hc->NumberOfProps();
|
||||
int entry = layoutInfo->FindElementWithCache(thread_, hc, key, propsNumber);
|
||||
if (entry == -1) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
int offset = hc->GetInlinedPropertiesOffset(entry);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
JSHandle<TSClassType> TSManager::GetExtendedClassType(JSHandle<TSClassType> classType) const
|
||||
{
|
||||
ASSERT(classType.GetTaggedValue().IsTSClassType());
|
||||
|
@ -522,9 +522,6 @@ public:
|
||||
(l == static_cast<uint32_t>(TSRuntimeType::ITERATOR_RESULT));
|
||||
}
|
||||
|
||||
// not consider [[prototype]] properties and accessor, -1: not find
|
||||
int PUBLIC_API GetPropertyOffset(JSTaggedValue hclass, JSTaggedValue key);
|
||||
|
||||
void PUBLIC_API SetCurConstantPool(const JSPandaFile *jsPandaFile, uint32_t methodOffset);
|
||||
|
||||
JSHandle<JSTaggedValue> PUBLIC_API GetConstantPool() const
|
||||
|
@ -35,6 +35,8 @@ public:
|
||||
|
||||
static constexpr uint32_t DEFAULT_CAPACITY = 4;
|
||||
static constexpr uint32_t DEFAULT_GROW_SIZE = 5;
|
||||
static constexpr uint32_t END_INDEX = 0;
|
||||
static constexpr uint32_t ELEMENTS_START_INDEX = 1;
|
||||
static JSHandle<WeakVector> Create(const JSThread *thread, uint32_t capacity = DEFAULT_CAPACITY);
|
||||
static JSHandle<WeakVector> Grow(const JSThread *thread, const JSHandle<WeakVector> &old, uint32_t newCapacity);
|
||||
static JSHandle<WeakVector> Append(const JSThread *thread, const JSHandle<WeakVector> &vec,
|
||||
@ -89,8 +91,6 @@ public:
|
||||
|
||||
private:
|
||||
static const uint32_t MIN_CAPACITY = 2;
|
||||
static const uint32_t END_INDEX = 0;
|
||||
static const uint32_t ELEMENTS_START_INDEX = 1;
|
||||
static const uint32_t MAX_VECTOR_INDEX = TaggedArray::MAX_ARRAY_INDEX - ELEMENTS_START_INDEX;
|
||||
|
||||
inline static constexpr uint32_t VectorToArrayIndex(uint32_t index)
|
||||
|
@ -16,11 +16,10 @@ group("aot_compatibility_test") {
|
||||
|
||||
test_list = [
|
||||
"base_verification",
|
||||
"builtins_api",
|
||||
"property_operation",
|
||||
"prototype_accessor",
|
||||
"prototype_base_verification",
|
||||
|
||||
#"builtins_api",
|
||||
#"property_operation",
|
||||
]
|
||||
|
||||
deps = []
|
||||
|
@ -26,4 +26,4 @@ true
|
||||
true
|
||||
true
|
||||
xxxx
|
||||
TypeError: CallObj is NonCallable
|
||||
true
|
||||
|
@ -77,6 +77,6 @@ declare function print(arg:any):string;
|
||||
try {
|
||||
b5.foo();
|
||||
} catch(e) {
|
||||
print(e);
|
||||
print(e instanceof TypeError);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user