!3740 add aot callthis calltarget check

Merge pull request !3740 from wpy111/master
This commit is contained in:
openharmony_ci 2023-03-28 09:59:16 +00:00 committed by Gitee
commit 0667273bf7
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
16 changed files with 407 additions and 82 deletions

View File

@ -170,6 +170,10 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
case EcmaOpcode::CALLTHIS0_IMM8_V8:
case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
flags |= BytecodeFlags::SUPPORT_DEOPT;
break;
case EcmaOpcode::RETURNUNDEFINED:

View File

@ -115,6 +115,14 @@ public:
GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_META)
#undef DECLARE_GATE_META
#define DECLARE_LOAD_PROPERTY_GATE_META(NAME, OP, R, S, D, V) \
const GateMetaData* NAME(bool isFunction) \
{ \
return metaBuilder_.NAME(isFunction); \
}
LOAD_PROPERTY_LIST(DECLARE_LOAD_PROPERTY_GATE_META)
#undef DECLARE_LOAD_PROPERTY_GATE_META
#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
const GateMetaData* NAME(uint64_t value, uint64_t pcOffset) \
{ \

View File

@ -367,6 +367,20 @@ GateRef CircuitBuilder::JSCallTargetTypeCheck(GateType type, GateRef func, GateR
return ret;
}
GateRef CircuitBuilder::JSCallThisTargetTypeCheck(GateType type, GateRef func)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
ASSERT(acc_.HasFrameState(currentDepend));
auto frameState = acc_.GetFrameState(currentDepend);
GateRef ret = GetCircuit()->NewGate(circuit_->JSCallThisTargetTypeCheck(static_cast<size_t>(type.Value())),
MachineType::I1, {currentControl, currentDepend, func, frameState}, GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::DeoptCheck(GateRef condition, GateRef frameState, DeoptType type)
{
auto currentLabel = env_->GetCurrentLabel();
@ -755,12 +769,12 @@ GateRef CircuitBuilder::HeapAlloc(GateRef initialHClass, GateType type, RegionSp
return ret;
}
GateRef CircuitBuilder::LoadProperty(GateRef receiver, GateRef propertyLookupResult)
GateRef CircuitBuilder::LoadProperty(GateRef receiver, GateRef propertyLookupResult, bool isFunction)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto ret = GetCircuit()->NewGate(circuit_->LoadProperty(), MachineType::I64,
auto ret = GetCircuit()->NewGate(circuit_->LoadProperty(isFunction), MachineType::I64,
{ currentControl, currentDepend, receiver, propertyLookupResult },
GateType::AnyType());
currentLabel->SetControl(ret);

View File

@ -237,6 +237,7 @@ public:
GateRef TryPrimitiveTypeCheck(GateType type, GateRef gate);
GateRef CallTargetCheck(GateRef function, GateRef id, GateRef param);
GateRef JSCallTargetTypeCheck(GateType type, GateRef func, GateRef methodIndex);
GateRef JSCallThisTargetTypeCheck(GateType type, GateRef func);
GateRef DeoptCheck(GateRef condition, GateRef frameState, DeoptType type = DeoptType::NOTCHECK);
GateRef TypedBinaryOperator(MachineType type, TypedBinOp binOp, GateType typeLeft, GateType typeRight,
std::vector<GateRef> inList, GateType gateType);
@ -450,7 +451,7 @@ public:
GateRef LoadElement(GateRef receiver, GateRef index);
template<TypedStoreOp Op>
GateRef StoreElement(GateRef receiver, GateRef index, GateRef value);
GateRef LoadProperty(GateRef receiver, GateRef propertyLookupResult);
GateRef LoadProperty(GateRef receiver, GateRef propertyLookupResult, bool isFunction);
GateRef StoreProperty(GateRef receiver, GateRef propertyLookupResult, GateRef value);
GateRef LoadArrayLength(GateRef array);
GateRef HeapAlloc(GateRef initialHClass, GateType type, RegionSpaceFlag flag);

View File

@ -238,6 +238,11 @@ public:
return JSBytecodeMetaData::Cast(meta_);
}
LoadPropertyMetaDate* GetLoadPropertyMetaDate()
{
return LoadPropertyMetaDate::Cast(meta_);
}
std::string MachineTypeStr(MachineType machineType) const;
std::string GateTypeStr(GateType gateType) const;
~Gate() = default;

View File

@ -130,7 +130,8 @@ GateType GateAccessor::GetParamGateType(GateRef gate) const
GetOpCode(gate) == OpCode::OBJECT_TYPE_CHECK ||
GetOpCode(gate) == OpCode::TYPED_ARRAY_CHECK ||
GetOpCode(gate) == OpCode::INDEX_CHECK ||
GetOpCode(gate) == OpCode::JSCALLTARGET_TYPE_CHECK);
GetOpCode(gate) == OpCode::JSCALLTARGET_TYPE_CHECK ||
GetOpCode(gate) == OpCode::JSCALLTHISTARGET_TYPE_CHECK);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
GateTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
return accessor.GetGateType();
@ -195,6 +196,13 @@ const ChunkVector<char>& GateAccessor::GetConstantString(GateRef gate) const
return gatePtr->GetStringMetaData()->GetString();
}
bool GateAccessor::IsVtable(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::LOAD_PROPERTY);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
return gatePtr->GetLoadPropertyMetaDate()->IsVtable();
}
uint32_t GateAccessor::TryGetPcOffset(GateRef gate) const
{
Gate *gatePtr = circuit_->LoadGatePtr(gate);

View File

@ -381,6 +381,7 @@ public:
TypedUnaryAccessor GetTypedUnOp(GateRef gate) const;
uint64_t GetConstantValue(GateRef gate) const;
const ChunkVector<char>& GetConstantString(GateRef gate) const;
bool IsVtable(GateRef gate) const;
uint32_t TryGetPcOffset(GateRef gate) const;
EcmaOpcode GetByteCodeOpcode(GateRef gate) const;
void Print(GateRef gate) const;

View File

@ -49,6 +49,7 @@ std::string GateMetaData::Str(OpCode opcode)
const std::map<OpCode, const char *> strMap = {
#define GATE_NAME_MAP(NAME, OP, R, S, D, V) { OpCode::OP, #OP },
IMMUTABLE_META_DATA_CACHE_LIST(GATE_NAME_MAP)
LOAD_PROPERTY_LIST(GATE_NAME_MAP)
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)
@ -214,6 +215,15 @@ const GateMetaData* GateMetaBuilder::NAME() \
IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_META)
#undef DECLARE_GATE_META
#define DECLARE_LOAD_PROPERTY_GATE_META(NAME, OP, R, S, D, V) \
const GateMetaData* GateMetaBuilder::NAME(bool isFunction) \
{ \
auto meta = new (chunk_) LoadPropertyMetaDate(OpCode::OP, R, S, D, V, isFunction); \
return meta; \
}
LOAD_PROPERTY_LIST(DECLARE_LOAD_PROPERTY_GATE_META)
#undef DECLARE_LOAD_PROPERTY_GATE_META
#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \
const GateMetaData* GateMetaBuilder::NAME(size_t value) \
{ \

View File

@ -199,7 +199,6 @@ std::string MachineTypeToStr(MachineType machineType);
V(ArrayCheck, ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(StableArrayCheck, STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(DeoptCheck, DEOPT_CHECK, GateFlags::NONE_FLAG, 1, 1, 3) \
V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2) \
V(StoreProperty, STORE_PROPERTY, GateFlags::NONE_FLAG, 1, 1, 3) \
V(ToLength, TO_LENGTH, GateFlags::NONE_FLAG, 1, 1, 1) \
V(DefaultCase, DEFAULT_CASE, GateFlags::CONTROL, 1, 0, 0) \
@ -240,17 +239,18 @@ std::string MachineTypeToStr(MachineType machineType);
V(DependSelector, DEPEND_SELECTOR, GateFlags::FIXED, 1, value, 0) \
GATE_META_DATA_LIST_WITH_VALUE_IN(V)
#define GATE_META_DATA_LIST_WITH_GATE_TYPE(V) \
V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(ObjectTypeCheck, OBJECT_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(JSCallTargetTypeCheck, JSCALLTARGET_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
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(CheckAndConvert, CHECK_AND_CONVERT, GateFlags::CHECKABLE, 1, 1, 1) \
V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1) \
#define GATE_META_DATA_LIST_WITH_GATE_TYPE(V) \
V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(ObjectTypeCheck, OBJECT_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(JSCallTargetTypeCheck, JSCALLTARGET_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(JSCallThisTargetTypeCheck, JSCALLTHISTARGET_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
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(CheckAndConvert, CHECK_AND_CONVERT, GateFlags::CHECKABLE, 1, 1, 1) \
V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1) \
#define GATE_META_DATA_LIST_WITH_VALUE(V) \
V(Icmp, ICMP, GateFlags::NONE_FLAG, 0, 0, 2) \
@ -276,6 +276,9 @@ std::string MachineTypeToStr(MachineType machineType);
V(TYPED_BINARY_OP) \
V(CONSTSTRING)
#define LOAD_PROPERTY_LIST(V) \
V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2) \
enum class OpCode : uint8_t {
NOP = 0,
#define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) OP,
@ -284,6 +287,7 @@ enum class OpCode : uint8_t {
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)
LOAD_PROPERTY_LIST(DECLARE_GATE_OPCODE)
#undef DECLARE_GATE_OPCODE
#define DECLARE_GATE_OPCODE(NAME) NAME,
GATE_OPCODE_LIST(DECLARE_GATE_OPCODE)
@ -474,6 +478,27 @@ inline std::ostream& operator<<(std::ostream& os, OpCode opcode)
return os << GateMetaData::Str(opcode);
}
class LoadPropertyMetaDate : public GateMetaData {
public:
LoadPropertyMetaDate(OpCode opcode, GateFlags flags, uint32_t statesIn,
uint16_t dependsIn, uint32_t valuesIn, bool isVtable)
: GateMetaData(opcode, flags, statesIn, dependsIn, valuesIn), isVtable_(isVtable) {}
static LoadPropertyMetaDate* Cast(const GateMetaData* meta)
{
ASSERT(meta->GetOpCode() == OpCode::LOAD_PROPERTY);
return static_cast<LoadPropertyMetaDate*>(const_cast<GateMetaData*>(meta));
}
bool IsVtable() const
{
return isVtable_;
}
private:
bool isVtable_ { false };
};
class JSBytecodeMetaData : public GateMetaData {
public:
explicit JSBytecodeMetaData(size_t valuesIn, EcmaOpcode opcode, uint32_t pcOffset, GateFlags flags)

View File

@ -60,6 +60,10 @@ static constexpr size_t FIVE_VALUE = 5;
IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_CACHED_GATE_META)
#undef DECLARE_CACHED_GATE_META
#define DECLARE_LOAD_PROPERTY_META(NAME, OP, R, S, D, V) \
LoadPropertyMetaDate cached##NAME##_ { OpCode::OP, R, S, D, V };
#undef DECLARE_LOAD_PROPERTY_META
#define DECLARE_CACHED_VALUE_META(VALUE) \
GateMetaData cachedMerge##VALUE##_ { OpCode::MERGE, GateFlags::CONTROL, VALUE, 0, 0 }; \
GateMetaData cachedDependSelector##VALUE##_ { OpCode::DEPEND_SELECTOR, GateFlags::FIXED, 1, VALUE, 0 };
@ -118,6 +122,7 @@ public:
#undef DECLARE_GATE_META
explicit GateMetaBuilder(Chunk* chunk);
const GateMetaData* LoadProperty(bool isFunction);
const GateMetaData* JSBytecode(size_t valuesIn, EcmaOpcode opcode, uint32_t pcOffset, GateFlags flags)
{
return new (chunk_) JSBytecodeMetaData(valuesIn, opcode, pcOffset, flags);

View File

@ -182,7 +182,7 @@ HWTEST_F_L0(LoweringRelateGateTests, HeapAllocTest)
builder.StoreElement<ecmascript::kungfu::TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT>(array, builder.IntPtr(1),
builder.ToTaggedInt(builder.Int64(1)));
builder.StoreProperty(array, lengthString, builder.ToTaggedInt(builder.Int64(2)));
auto length = builder.LoadProperty(array, lengthString);
auto length = builder.LoadProperty(array, lengthString, false);
Label less2(&builder);
Label notLess2(&builder);
auto condtion = builder.TaggedIsTrue(builder.NumberBinaryOp<TypedBinOp::TYPED_LESS>(length,

View File

@ -235,9 +235,6 @@ void TSTypeLowering::Lower(GateRef gate)
case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
LowerTypedSuperCall(gate, jsFunc, newTarget);
break;
case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
LowerCallThis1Imm8V8V8(gate);
break;
case EcmaOpcode::CALLARG0_IMM8:
LowerTypedCallArg0(gate);
break;
@ -253,6 +250,21 @@ void TSTypeLowering::Lower(GateRef gate)
case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
LowerTypedCallrange(gate);
break;
case EcmaOpcode::CALLTHIS0_IMM8_V8:
LowerTypedCallthis0(gate);
break;
case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
LowerTypedCallthis1(gate);
break;
case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
LowerTypedCallthis2(gate);
break;
case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
LowerTypedCallthis3(gate);
break;
case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
LowerTypedCallthisrange(gate);
break;
default:
break;
}
@ -663,7 +675,7 @@ void TSTypeLowering::LowerTypedLdObjByName(GateRef gate)
GateRef pfrGate = builder_.Int32(plr.GetData());
GateRef result = Circuit::NullGate();
if (LIKELY(!plr.IsAccessor())) {
result = builder_.LoadProperty(receiver, pfrGate);
result = builder_.LoadProperty(receiver, pfrGate, plr.IsVtable());
} else {
result = builder_.CallGetter(gate, receiver, pfrGate);
}
@ -940,25 +952,9 @@ BuiltinsStubCSigns::ID TSTypeLowering::GetBuiltinId(GateRef func, GateRef receiv
return id;
}
void TSTypeLowering::LowerCallThis1Imm8V8V8(GateRef gate)
{
GateRef thisObj = acc_.GetValueIn(gate, 0);
GateRef a0 = acc_.GetValueIn(gate, 1); // 1:parameter index
GateType a0Type = acc_.GetGateType(a0);
GateRef func = acc_.GetValueIn(gate, 2); // 2:function
BuiltinsStubCSigns::ID id = GetBuiltinId(func, thisObj);
if (id != BuiltinsStubCSigns::ID::NONE && a0Type.IsNumberType()) {
AddProfiling(gate);
SpeculateCallBuiltin(gate, id);
} else {
acc_.DeleteStateSplitAndFrameState(gate);
}
}
void TSTypeLowering::LowerTypedCallArg0(GateRef gate)
{
GateRef func = acc_.GetValueIn(gate, 0);
GateType funcType = acc_.GetGateType(func);
if (!tsManager_->IsFunctionTypeKind(funcType)) {
acc_.DeleteStateSplitAndFrameState(gate);
@ -970,25 +966,35 @@ void TSTypeLowering::LowerTypedCallArg0(GateRef gate)
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
int methodIndex = tsManager_->GetMethodIndex(funcGt);
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef env = builder_.GetFunctionLexicalEnv(func);
GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
EcmaOpcode::CALLARG0_IMM8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj };
if (IsLoadVtable(func)) {
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
} else {
int methodIndex = tsManager_->GetMethodIndex(funcGt);
if (methodIndex == -1) {
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
}
void TSTypeLowering::LowerTypedCallArg1(GateRef gate)
{
GateRef a0Value = acc_.GetValueIn(gate, 0);
GateRef func = acc_.GetValueIn(gate, 1);
GateType funcType = acc_.GetGateType(func);
if (!tsManager_->IsFunctionTypeKind(funcType)) {
acc_.DeleteStateSplitAndFrameState(gate);
@ -1000,25 +1006,34 @@ void TSTypeLowering::LowerTypedCallArg1(GateRef gate)
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
int methodIndex = tsManager_->GetMethodIndex(funcGt);
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef env = builder_.GetFunctionLexicalEnv(func);
GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
EcmaOpcode::CALLARG1_IMM8_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0Value };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
GateRef a0Value = acc_.GetValueIn(gate, 0);
if (IsLoadVtable(func)) {
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0Value };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
} else {
int methodIndex = tsManager_->GetMethodIndex(funcGt);
if (methodIndex == -1) {
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0Value };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
}
void TSTypeLowering::LowerTypedCallArg2(GateRef gate)
{
GateRef a0 = acc_.GetValueIn(gate, 0);
GateRef a1 = acc_.GetValueIn(gate, 1); // 1:first parameter
GateRef func = acc_.GetValueIn(gate, 2); // 2:function
GateType funcType = acc_.GetGateType(func);
if (!tsManager_->IsFunctionTypeKind(funcType)) {
acc_.DeleteStateSplitAndFrameState(gate);
@ -1030,24 +1045,34 @@ void TSTypeLowering::LowerTypedCallArg2(GateRef gate)
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
int methodIndex = tsManager_->GetMethodIndex(funcGt);
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef env = builder_.GetFunctionLexicalEnv(func);
GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
EcmaOpcode::CALLARGS2_IMM8_V8_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0, a1 };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
GateRef a0 = acc_.GetValueIn(gate, 0);
GateRef a1 = acc_.GetValueIn(gate, 1); // 1:first parameter
if (IsLoadVtable(func)) {
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0, a1 };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
} else {
int methodIndex = tsManager_->GetMethodIndex(funcGt);
if (methodIndex == -1) {
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0, a1 };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
}
void TSTypeLowering::LowerTypedCallArg3(GateRef gate)
{
GateRef a0 = acc_.GetValueIn(gate, 0);
GateRef a1 = acc_.GetValueIn(gate, 1);
GateRef a2 = acc_.GetValueIn(gate, 2);
GateRef func = acc_.GetValueIn(gate, 3); // 3:function
GateType funcType = acc_.GetGateType(func);
if (!tsManager_->IsFunctionTypeKind(funcType)) {
@ -1060,17 +1085,31 @@ void TSTypeLowering::LowerTypedCallArg3(GateRef gate)
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
int methodIndex = tsManager_->GetMethodIndex(funcGt);
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef env = builder_.GetFunctionLexicalEnv(func);
GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0, a1, a2 };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
GateRef a0 = acc_.GetValueIn(gate, 0);
GateRef a1 = acc_.GetValueIn(gate, 1);
GateRef a2 = acc_.GetValueIn(gate, 2);
if (IsLoadVtable(func)) {
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0, a1, a2 };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
} else {
int methodIndex = tsManager_->GetMethodIndex(funcGt);
if (methodIndex == -1) {
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0, a1, a2 };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
}
void TSTypeLowering::LowerTypedCallrange(GateRef gate)
@ -1082,7 +1121,6 @@ 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);
@ -1094,14 +1132,9 @@ void TSTypeLowering::LowerTypedCallrange(GateRef gate)
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
int methodIndex = tsManager_->GetMethodIndex(funcGt);
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
GateRef env = builder_.GetFunctionLexicalEnv(func);
vec.emplace_back(glue_);
vec.emplace_back(env);
vec.emplace_back(actualArgc);
vec.emplace_back(func);
vec.emplace_back(newTarget);
@ -1109,7 +1142,187 @@ void TSTypeLowering::LowerTypedCallrange(GateRef gate)
for (size_t i = 0; i < argc; i++) {
vec.emplace_back(acc_.GetValueIn(gate, i));
}
if (IsLoadVtable(func)) {
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef newEnv = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef>::iterator pos = vec.begin();
vec.insert(++pos, newEnv);
GateRef result = builder_.TypedAotCall(gate, vec);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
} else {
int methodIndex = tsManager_->GetMethodIndex(funcGt);
if (methodIndex == -1) {
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
builder_.JSCallTargetTypeCheck(funcType, func, builder_.IntPtr(methodIndex));
GateRef newEnv = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef>::iterator pos = vec.begin();
vec.insert(++pos, newEnv);
GateRef result = builder_.TypedAotCall(gate, vec);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
}
bool TSTypeLowering::IsLoadVtable(GateRef func)
{
auto op = acc_.GetOpCode(func);
if (op != OpCode::LOAD_PROPERTY || !acc_.IsVtable(func)) {
return false;
}
return true;
}
bool TSTypeLowering::CanOptimizeAsFastCall(GateRef func, uint32_t len)
{
GateType funcType = acc_.GetGateType(func);
if (!tsManager_->IsFunctionTypeKind(funcType)) {
return false;
}
GlobalTSTypeRef funcGt = funcType.GetGTRef();
uint32_t length = tsManager_->GetFunctionTypeLength(funcGt);
if (len != length) {
return false;
}
auto op = acc_.GetOpCode(func);
if (op != OpCode::LOAD_PROPERTY || !acc_.IsVtable(func)) {
return false;
}
return true;
}
void TSTypeLowering::LowerTypedCallthis0(GateRef gate)
{
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef func = acc_.GetValueIn(gate, 1);
if (!CanOptimizeAsFastCall(func, 0)) {
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
GateType funcType = acc_.GetGateType(func);
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
EcmaOpcode::CALLTHIS0_IMM8_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = acc_.GetValueIn(gate, 0);
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
void TSTypeLowering::LowerTypedCallthis1(GateRef gate)
{
// 3: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 3);
GateRef thisObj = acc_.GetValueIn(gate, 0);
GateRef a0 = acc_.GetValueIn(gate, 1); // 1:parameter index
GateType a0Type = acc_.GetGateType(a0);
GateRef func = acc_.GetValueIn(gate, 2); // 2:function
BuiltinsStubCSigns::ID id = GetBuiltinId(func, thisObj);
if (id != BuiltinsStubCSigns::ID::NONE && a0Type.IsNumberType()) {
AddProfiling(gate);
SpeculateCallBuiltin(gate, id);
} else {
if (!CanOptimizeAsFastCall(func, 1)) {
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
GateType funcType = acc_.GetGateType(func);
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
EcmaOpcode::CALLTHIS1_IMM8_V8_V8));
GateRef newTarget = builder_.Undefined();
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0 };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
}
void TSTypeLowering::LowerTypedCallthis2(GateRef gate)
{
// 4: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 4);
GateRef func = acc_.GetValueIn(gate, 3); // 3: func
if (!CanOptimizeAsFastCall(func, 2)) { // 2: 2 params
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
GateType funcType = acc_.GetGateType(func);
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = acc_.GetValueIn(gate, 0);
GateRef a0Value = acc_.GetValueIn(gate, 1);
GateRef a1Value = acc_.GetValueIn(gate, 2);
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0Value, a1Value };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
void TSTypeLowering::LowerTypedCallthis3(GateRef gate)
{
// 5: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 5);
GateRef func = acc_.GetValueIn(gate, 4); // 4: func
if (!CanOptimizeAsFastCall(func, 3)) { // 3: 3 params
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
GateType funcType = acc_.GetGateType(func);
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = acc_.GetValueIn(gate, 0);
GateRef a0Value = acc_.GetValueIn(gate, 1);
GateRef a1Value = acc_.GetValueIn(gate, 2);
GateRef a2Value = acc_.GetValueIn(gate, 3);
GateRef env = builder_.GetFunctionLexicalEnv(func);
std::vector<GateRef> args { glue_, env, actualArgc, func, newTarget, thisObj, a0Value, a1Value, a2Value };
GateRef result = builder_.TypedAotCall(gate, args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
void TSTypeLowering::LowerTypedCallthisrange(GateRef gate)
{
std::vector<GateRef> vec;
// this
size_t fixedInputsNum = 1;
ASSERT(acc_.GetNumValueIn(gate) - fixedInputsNum >= 0);
size_t numIns = acc_.GetNumValueIn(gate);
GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8));
const size_t callTargetIndex = 1; // 1: acc
GateRef func = acc_.GetValueIn(gate, numIns - callTargetIndex); // acc
if (!CanOptimizeAsFastCall(func, numIns - 2)) { // 2 :func and thisobj
acc_.DeleteStateSplitAndFrameState(gate);
return;
}
GateType funcType = acc_.GetGateType(func);
builder_.JSCallThisTargetTypeCheck(funcType, func);
GateRef thisObj = acc_.GetValueIn(gate, 0);
GateRef newTarget = builder_.Undefined();
GateRef env = builder_.GetFunctionLexicalEnv(func);
vec.emplace_back(glue_);
vec.emplace_back(env);
vec.emplace_back(actualArgc);
vec.emplace_back(func);
vec.emplace_back(newTarget);
vec.emplace_back(thisObj);
// add common args
for (size_t i = fixedInputsNum; i < numIns - callTargetIndex; i++) {
vec.emplace_back(acc_.GetValueIn(gate, i));
}
GateRef result = builder_.TypedAotCall(gate, vec);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}

View File

@ -90,12 +90,19 @@ private:
void LowerTypedNewObjRange(GateRef gate);
void LowerTypedSuperCall(GateRef gate, GateRef ctor, GateRef newTarget);
void LowerCallThis1Imm8V8V8(GateRef gate);
void LowerTypedCallArg0(GateRef gate);
void LowerTypedCallArg1(GateRef gate);
void LowerTypedCallArg2(GateRef gate);
void LowerTypedCallArg3(GateRef gate);
void LowerTypedCallrange(GateRef gate);
void LowerTypedCallthis0(GateRef gate);
void LowerTypedCallthis1(GateRef gate);
void LowerTypedCallthis2(GateRef gate);
void LowerTypedCallthis3(GateRef gate);
void LowerTypedCallthisrange(GateRef gate);
bool IsLoadVtable(GateRef func);
bool CanOptimizeAsFastCall(GateRef func, uint32_t len);
bool CheckParam(GateRef gate, bool isCallThis, MethodLiteral* method);
// TypeTrusted means the type of gate is already PrimitiveTypeCheck-passed,

View File

@ -70,6 +70,9 @@ void TypeLowering::LowerType(GateRef gate)
case OpCode::JSCALLTARGET_TYPE_CHECK:
LowerJSCallTargetTypeCheck(gate);
break;
case OpCode::JSCALLTHISTARGET_TYPE_CHECK:
LowerJSCallThisTargetTypeCheck(gate);
break;
case OpCode::TYPED_CALL_CHECK:
LowerCallTargetCheck(gate);
break;
@ -3019,6 +3022,27 @@ void TypeLowering::LowerJSCallTargetTypeCheck(GateRef gate)
}
}
void TypeLowering::LowerJSCallThisTargetTypeCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
auto type = acc_.GetParamGateType(gate);
if (tsManager_->IsFunctionTypeKind(type)) {
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef isJsFunc = builder_.IsJSFunction(func);
GateRef checkFunc = builder_.BoolAnd(isObj, isJsFunc);
GateRef funcMethodTarget = builder_.GetMethodFromFunction(func);
GateRef isAot = builder_.HasAotCode(funcMethodTarget);
GateRef check = builder_.BoolAnd(checkFunc, isAot);
builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
} else {
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
}
void TypeLowering::LowerCallTargetCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);

View File

@ -203,6 +203,7 @@ private:
void LowerTypedCallBuitin(GateRef gate);
void LowerCallTargetCheck(GateRef gate);
void LowerJSCallTargetTypeCheck(GateRef gate);
void LowerJSCallThisTargetTypeCheck(GateRef gate);
void LowerTypedNewAllocateThis(GateRef gate, GateRef glue);
void LowerTypedSuperAllocateThis(GateRef gate, GateRef glue);
void LowerGetSuperConstructor(GateRef gate);

View File

@ -121,8 +121,7 @@ public:
return i;
}
}
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
return -1;
}
inline void SetIndexHeader(const panda_file::File::IndexHeader *indexHeader)