* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/arksteed/arksteed_graph_builder.h"
#include "ecmascript/arksteed/arksteed_bytecode_analysis.h"
#include "ecmascript/arksteed/arksteed_bytecode_analysis_new.h"
#include "ecmascript/arksteed/arksteed_bytecode_iterator.h"
#include "ecmascript/arksteed/arksteed_bytecode_preprocessor_new.h"
#include "ecmascript/arksteed/arksteed_opcode.h"
#include "ecmascript/compiler/bytecodes.h"
#include "ecmascript/global_env.h"
namespace panda::ecmascript::arksteed {
namespace kungfu = panda::ecmascript::kungfu;
namespace {
VRegIDType CheckedSubGraphVariableCount(int variableCount)
{
ASSERT(variableCount >= 0);
return static_cast<VRegIDType>(variableCount);
}
const char *ValueRepresentationName(ValueRepresentation repr)
{
switch (repr) {
case ValueRepresentation::TAGGED:
return "tagged";
case ValueRepresentation::INT32:
return "int32";
case ValueRepresentation::UINT32:
return "uint32";
case ValueRepresentation::FLOAT64:
return "float64";
case ValueRepresentation::HOLEY_FLOAT64:
return "holey_float64";
case ValueRepresentation::INT_PTR:
return "intptr";
case ValueRepresentation::NONE:
return "none";
}
return "unknown";
}
const char *MachineTypeName(kungfu::MachineType machineType)
{
switch (machineType) {
case kungfu::MachineType::NOVALUE:
return "novalue";
case kungfu::MachineType::ANYVALUE:
return "anyvalue";
case kungfu::MachineType::ARCH:
return "arch";
case kungfu::MachineType::FLEX:
return "flex";
case kungfu::MachineType::I1:
return "i1";
case kungfu::MachineType::I8:
return "i8";
case kungfu::MachineType::I16:
return "i16";
case kungfu::MachineType::I32:
return "i32";
case kungfu::MachineType::I64:
return "i64";
case kungfu::MachineType::F32:
return "f32";
case kungfu::MachineType::F64:
return "f64";
}
return "unknown";
}
bool IsTaggedCallType(kungfu::VariableType type)
{
kungfu::GateType gateType = type.GetGateType();
return gateType == kungfu::GateType::TaggedValue() || gateType == kungfu::GateType::TaggedPointer() ||
gateType == kungfu::GateType::TaggedNPointer();
}
bool MatchesCallSignatureType(const ValueVertex *value, kungfu::VariableType type)
{
if (IsTaggedCallType(type)) {
return value->IsTagged();
}
switch (type.GetMachineType()) {
case kungfu::MachineType::NOVALUE:
case kungfu::MachineType::ANYVALUE:
case kungfu::MachineType::FLEX:
return true;
case kungfu::MachineType::ARCH:
case kungfu::MachineType::I64:
return value->IsIntPtr();
case kungfu::MachineType::I1:
case kungfu::MachineType::I8:
case kungfu::MachineType::I16:
case kungfu::MachineType::I32:
return value->IsInt32() || value->IsUint32() || value->IsIntPtr();
case kungfu::MachineType::F32:
case kungfu::MachineType::F64:
return value->IsAnyFloat64();
}
return true;
}
}
const LivenessBitSet *ArkSteedGraphBuilder::GetInLivenessFor(uint32_t index) const
{
ASSERT(bytecodeAnalysis_ != nullptr);
return &bytecodeAnalysis_->GetInLiveness(index);
}
bool ArkSteedGraphBuilder::Build()
{
InitializeGraph();
startBlock_ = BB::New(GetChunk());
SetCurrentBlock(startBlock_);
InitializeGlobalsAndParameters();
InitializeCurrentFrameState();
BuildMergeStates();
if (options_.printMethodName) {
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
NewVertex<CallRuntimeVertex>({jsFunc}, RTSTUB_ID(PrintMethodName));
}
MergeCurrentFrameStateTo(FinishBlock<JumpVertex>({}, &jumpTargets_[entryPoint_]), entryPoint_);
BuildBody();
#ifndef NDEBUG
ValidateAfterBuilding();
#endif
return true;
}
void ArkSteedGraphBuilder::InitializeGraph()
{
method_ = env_->GetMethodLiteral();
const char *recordName = method_->GetRecordNameWithSymbol(env_->GetJSPandaFile(), method_->GetMethodId());
const char *methodName = method_->GetMethodName(env_->GetJSPandaFile(), method_->GetMethodId());
#ifndef NDEBUG
LOG_COMPILER(DEBUG) << "Starts compiling " << recordName << " :: " << methodName;
#endif
options_ = ArkSteedCompilationOptions(env_->GetJSOptions());
bytecodeContext_.Initialize(method_, env_, &options_);
iterator_ = BytecodeIterator(&bytecodeContext_);
jumpTargets_.resize(bytecodeContext_.GetBytecodeCount());
numParams_ = method_->GetNumArgsForArkSteed();
numLocal_ = method_->GetNumVregsWithCallField();
bytecodeAnalysis_ = GetChunk()->New<BytecodeAnalysis>(GetChunk(), bytecodeContext_, numLocal_, numParams_);
bytecodeAnalysis_->AnalyzeLivenessAndAssignments(&bytecodeContext_, &options_);
}
void ArkSteedGraphBuilder::InitializeGlobalsAndParameters()
{
ASSERT(glueAddr_ != 0);
glue_ = GetIntPtrConstant(static_cast<intptr_t>(glueAddr_));
const int32_t kCallTargetFpSlotIndex = 3;
for (uint32_t i = 0; i < numParams_; i++) {
ValueVertex *v = NewVertexNoInput<InitialValueVertex>(static_cast<int32_t>(i + kCallTargetFpSlotIndex));
GetGraph()->AddParameter(v);
}
}
void ArkSteedGraphBuilder::InitializeCurrentFrameState()
{
currentFrameState_ = GetChunk()->New<InterpreterFrameState>(numLocal_, numParams_, GetChunk());
for (VRegIDType i = 0; i < numParams_; i++) {
currentFrameState_->SetParam(i, GetGraph()->GetParameter(i));
}
ValueVertex *undefinedValue = GetRootConstant(RootConstantVertex::RootIndex::UNDEFINED);
for (VRegIDType i = 0; i < numLocal_; i++) {
currentFrameState_->SetLocal(i, undefinedValue);
}
currentFrameState_->SetEnv(NewVertexNoInput<InitialValueVertex>(-3));
currentFrameState_->SetAcc(undefinedValue);
}
ValueVertex *ArkSteedGraphBuilder::NewCallStubWithIC(const CommonStubCSigns::ID stubId,
const std::vector<ValueVertex *> &args)
{
std::vector<ValueVertex *> allArgs;
allArgs.reserve(args.size() + 3);
allArgs.push_back(GetGlue());
allArgs.insert(allArgs.end(), args.begin(), args.end());
allArgs.push_back(currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX));
allArgs.push_back(GetInt32Constant(static_cast<int>(GetICSlotId(0))));
ValidateCommonStubCallArgs(stubId, allArgs);
return NewVertex<CallCommonStubVertex>(allArgs, stubId);
}
void ArkSteedGraphBuilder::LowerCallStubWithIC(const CommonStubCSigns::ID stubId,
const std::vector<ValueVertex *> &args)
{
currentFrameState_->SetAcc(NewCallStubWithIC(stubId, args));
}
void ArkSteedGraphBuilder::LowerCallStubWithICPreserveAcc(const CommonStubCSigns::ID stubId,
const std::vector<ValueVertex *> &args)
{
NewCallStubWithIC(stubId, args);
}
ValueVertex *ArkSteedGraphBuilder::NewCommonStubCall(std::initializer_list<ValueVertex *> args,
const CommonStubCSigns::ID stubId)
{
std::vector<ValueVertex *> allArgs(args);
ValidateCommonStubCallArgs(stubId, allArgs);
return NewVertex<CallCommonStubVertex>(allArgs, stubId);
}
void ArkSteedGraphBuilder::ValidateCommonStubCallArgs(const CommonStubCSigns::ID stubId,
const std::vector<ValueVertex *> &args) const
{
const CallSignature *signature = CommonStubCSigns::Get(stubId);
size_t actualCount = args.size();
size_t expectedCount = signature->GetParametersCount();
if (actualCount != expectedCount) {
LOG_ECMA(FATAL) << "ArkSteed CommonStub argument count mismatch, stub: " << signature->GetName()
<< ", expected: " << expectedCount << ", actual: " << actualCount;
UNREACHABLE();
}
kungfu::VariableType *params = signature->GetParametersType();
if (params == nullptr) {
return;
}
for (size_t i = 0; i < expectedCount; ++i) {
if (!MatchesCallSignatureType(args[i], params[i])) {
LOG_ECMA(FATAL) << "ArkSteed CommonStub argument type mismatch, stub: " << signature->GetName()
<< ", index: " << i
<< ", expected machine type: " << MachineTypeName(params[i].GetMachineType())
<< ", actual representation: "
<< ValueRepresentationName(args[i]->GetValueRepresentation());
UNREACHABLE();
}
}
}
void ArkSteedGraphBuilder::BuildMergeStates()
{
auto &jumpLoop = bytecodeContext_.GetJumpLoop();
size_t n = bytecodeContext_.GetBytecodeCount();
mergeStates_.assign(n, nullptr);
predecessorCountReductions_.assign(n, 0);
for (iterator_.GotoStart(); !iterator_.Done(); ++iterator_) {
auto curIndex = iterator_.Index();
if (!jumpLoop[curIndex]) {
continue;
}
auto targetIndex = iterator_.GetJumpTargetBcIndex();
ASSERT(mergeStates_[targetIndex] == nullptr && "Unexpected assignment before.");
mergeStates_[targetIndex] =
MergePointFrameState::NewForLoop(targetIndex,
bytecodeContext_.GetPredecessorCount()[targetIndex],
&bytecodeAnalysis_->GetInLiveness(targetIndex),
&bytecodeAnalysis_->GetLoopInfo(targetIndex),
chunk_);
}
}
void ArkSteedGraphBuilder::BuildBody()
{
auto bytecodeCount = bytecodeContext_.GetBytecodeCount();
for (iterator_.GotoStart(); !iterator_.Done(); ++iterator_) {
uint32_t index = iterator_.Index();
auto bytecodeInfo = iterator_.GetCurrentBytecodeInfo();
if (mergeStates_[index] != nullptr) {
if (mergeStates_[index]->PredecessorCount() == 0) {
ASSERT(CurrentBlock() == nullptr);
MarkDeadPredecessorsForSuccessors(index, bytecodeInfo);
continue;
}
if (CurrentBlock() != nullptr) {
MergeCurrentFrameStateTo(FinishBlock<JumpVertex>({}, &jumpTargets_[index]), index);
}
if (mergeStates_[index]->IsUnmergedUnreachableLoop()) {
ASSERT(CurrentBlock() == nullptr);
MarkDeadPredecessorsForSuccessors(index, bytecodeInfo);
continue;
}
StartNewBlockWithMergeState(index);
} else {
if (CurrentBlock() == nullptr) {
MarkDeadPredecessorsForSuccessors(index, bytecodeInfo);
continue;
}
}
ProcessBytecode();
if (bytecodeInfo.needFallThrough()) {
uint32_t fallThroughIndex = iterator_.NextIndex();
if (fallThroughIndex >= bytecodeCount) {
LOG_COMPILER(WARN) << "Malformed bytecode #" << index << ": the last bytecode goes fallthrough.";
continue;
}
uint32_t nextRPOIndex = iterator_.NextRPOIndex();
if (fallThroughIndex != nextRPOIndex) {
BB *block = FinishBlock<JumpVertex>({}, &jumpTargets_[fallThroughIndex]);
MergeCurrentFrameStateTo(block, fallThroughIndex);
}
}
}
ASSERT(currentBlock_ == nullptr);
}
void ArkSteedGraphBuilder::ValidateAfterBuilding()
{
for (iterator_.GotoStart(); !iterator_.Done(); ++iterator_) {
uint32_t index = iterator_.Index();
MergePointFrameState *mergeState = mergeStates_[index];
if (mergeState == nullptr) {
continue;
}
ValidateMergeStateAfterBuilding(index, mergeState);
}
}
void ArkSteedGraphBuilder::ValidateMergeStateAfterBuilding(uint32_t index, MergePointFrameState *mergeState)
{
if (mergeState->PredecessorCount() == 0) {
if (mergeState->PredecessorsSoFar() != 0) {
LOG_COMPILER(FATAL) << "INVALID merge state for bytecode #" << index << ": unreachable merge point has "
<< mergeState->PredecessorsSoFar() << " predecessors merged.";
}
return;
}
if (mergeState->PredecessorsSoFar() != mergeState->PredecessorCount()) {
LOG_COMPILER(FATAL) << "INVALID merge state for bytecode #" << index << ": PredecessorsSoFar() which is "
<< mergeState->PredecessorsSoFar() << " does not match PredecessorCount() which is "
<< mergeState->PredecessorCount();
}
LOG_COMPILER(DEBUG) << "OK: merge state for bytecode #" << index;
}
ArkSteedGraphBuilder::BranchResult ArkSteedGraphBuilder::BuildBranchIfTrue(BranchBuilder &builder, ValueVertex *vertex)
{
auto emitUnconditionalBytecodeBranch = [this, &builder](bool conditionTrue) {
bool takeJumpTarget =
builder.GetCurrentBranchType() == BranchType::TRUE_BRANCH ? conditionTrue : !conditionTrue;
ASSERT(builder.GetMode() == BranchBuilder::JUMP_BYTECODE_TARGET);
uint32_t destIndex = takeJumpTarget ? builder.JumpTargetBcIndex() : builder.FallthroughBcIndex();
uint32_t trimmedIndex = takeJumpTarget ? builder.FallthroughBcIndex() : builder.JumpTargetBcIndex();
if (trimmedIndex != destIndex) {
ReduceBytecodePredecessorCount(trimmedIndex);
}
BB *block = FinishBlock<JumpVertex>({}, &jumpTargets_[destIndex]);
MergeCurrentFrameStateTo(block, destIndex);
};
if (RootConstantVertex *root = vertex->TryCast<RootConstantVertex>()) {
switch (root->GetIndex()) {
case RootConstantVertex::RootIndex::TRUE_VALUE:
if (builder.GetMode() == BranchBuilder::JUMP_LABEL_TARGET) {
return BranchResult::ALWAYS_TRUE;
}
emitUnconditionalBytecodeBranch(true);
return BranchResult::ALWAYS_TRUE;
case RootConstantVertex::RootIndex::FALSE_VALUE:
case RootConstantVertex::RootIndex::NULL_VALUE:
case RootConstantVertex::RootIndex::UNDEFINED:
if (builder.GetMode() == BranchBuilder::JUMP_LABEL_TARGET) {
return BranchResult::ALWAYS_FALSE;
}
emitUnconditionalBytecodeBranch(false);
return BranchResult::ALWAYS_FALSE;
default:
break;
}
}
builder.Build<BranchIfTrueVertex>({vertex});
return BranchResult::DEFAULT;
}
void ArkSteedGraphBuilder::ProcessBytecode()
{
auto info = iterator_.GetCurrentBytecodeInfo();
auto opcode = info.GetOpcode();
#ifndef NDEBUG
LOG_COMPILER(DEBUG) << "Processing bytecode #" << iterator_.Index() << ": " << GetEcmaOpcodeStr(opcode);
#endif
ASSERT(kungfu::IsArkSteedSupportedOpcode(opcode));
switch (opcode) {
case kungfu::EcmaOpcode::NOP:
break;
case kungfu::EcmaOpcode::CALLARG0_IMM8:
LowerCallArg0();
break;
case kungfu::EcmaOpcode::CALLARG1_IMM8_V8:
LowerCallArg1();
break;
case kungfu::EcmaOpcode::CALLARGS2_IMM8_V8_V8:
LowerCallArgs2();
break;
case kungfu::EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
LowerCallArgs3();
break;
case kungfu::EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8:
LowerCallThis0();
break;
case kungfu::EcmaOpcode::CALLTHIS0_IMM8_V8:
LowerCallThis0();
break;
case kungfu::EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
LowerCallThis1();
break;
case kungfu::EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
LowerCallThis2();
break;
case kungfu::EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
LowerCallThis3();
break;
case kungfu::EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
case kungfu::EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
LowerCallRange();
break;
case kungfu::EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
case kungfu::EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
LowerCallThisRange();
break;
case kungfu::EcmaOpcode::APPLY_IMM8_V8_V8:
LowerCallSpread();
break;
case kungfu::EcmaOpcode::GETUNMAPPEDARGS:
LowerGetUnmappedArgs();
break;
case kungfu::EcmaOpcode::INC_IMM8:
LowerInc();
break;
case kungfu::EcmaOpcode::DEC_IMM8:
LowerDec();
break;
case kungfu::EcmaOpcode::GETPROPITERATOR:
LowerGetPropIterator();
break;
case kungfu::EcmaOpcode::CLOSEITERATOR_IMM8_V8:
case kungfu::EcmaOpcode::CLOSEITERATOR_IMM16_V8:
LowerCloseIterator();
break;
case kungfu::EcmaOpcode::ADD2_IMM8_V8:
LowerAdd2();
break;
case kungfu::EcmaOpcode::SUB2_IMM8_V8:
LowerSub2();
break;
case kungfu::EcmaOpcode::MUL2_IMM8_V8:
LowerMul2();
break;
case kungfu::EcmaOpcode::DIV2_IMM8_V8:
LowerDiv2();
break;
case kungfu::EcmaOpcode::MOD2_IMM8_V8:
LowerMod2();
break;
case kungfu::EcmaOpcode::EQ_IMM8_V8:
LowerEq();
break;
case kungfu::EcmaOpcode::NOTEQ_IMM8_V8:
LowerNotEq();
break;
case kungfu::EcmaOpcode::LESS_IMM8_V8:
LowerLess();
break;
case kungfu::EcmaOpcode::LESSEQ_IMM8_V8:
LowerLessEq();
break;
case kungfu::EcmaOpcode::GREATER_IMM8_V8:
LowerGreater();
break;
case kungfu::EcmaOpcode::GREATEREQ_IMM8_V8:
LowerGreaterEq();
break;
case kungfu::EcmaOpcode::CREATEITERRESULTOBJ_V8_V8:
LowerCreateIterResultObj();
break;
case kungfu::EcmaOpcode::TRYLDGLOBALBYNAME_IMM8_ID16:
case kungfu::EcmaOpcode::TRYLDGLOBALBYNAME_IMM16_ID16:
LowerTryLdGlobalByName();
break;
case kungfu::EcmaOpcode::STGLOBALVAR_IMM16_ID16:
LowerStGlobalVar();
break;
case kungfu::EcmaOpcode::GETITERATOR_IMM8:
case kungfu::EcmaOpcode::GETITERATOR_IMM16:
LowerGetIterator();
break;
case kungfu::EcmaOpcode::NEWOBJAPPLY_IMM8_V8:
case kungfu::EcmaOpcode::NEWOBJAPPLY_IMM16_V8:
LowerNewObjApply();
break;
case kungfu::EcmaOpcode::THROW_PREF_NONE:
LowerThrow();
break;
case kungfu::EcmaOpcode::TYPEOF_IMM8:
case kungfu::EcmaOpcode::TYPEOF_IMM16:
LowerTypeOf();
break;
case kungfu::EcmaOpcode::THROW_CONSTASSIGNMENT_PREF_V8:
LowerThrowConstAssignment();
break;
case kungfu::EcmaOpcode::THROW_NOTEXISTS_PREF_NONE:
LowerThrowNotExists();
break;
case kungfu::EcmaOpcode::THROW_PATTERNNONCOERCIBLE_PREF_NONE:
LowerThrowPatternNonCoercible();
break;
case kungfu::EcmaOpcode::THROW_IFNOTOBJECT_PREF_V8:
LowerThrowIfNotObject();
break;
case kungfu::EcmaOpcode::THROW_UNDEFINEDIFHOLE_PREF_V8_V8:
LowerThrowUndefinedIfHole();
break;
case kungfu::EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16:
LowerThrowUndefinedIfHoleWithName();
break;
case kungfu::EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM8:
case kungfu::EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM16:
LowerThrowIfSuperNotCorrectCall();
break;
case kungfu::EcmaOpcode::THROW_DELETESUPERPROPERTY_PREF_NONE:
LowerThrowDeleteSuperProperty();
break;
case kungfu::EcmaOpcode::LDSYMBOL:
LowerLdSymbol();
break;
case kungfu::EcmaOpcode::LDGLOBAL:
LowerLdGlobal();
break;
case kungfu::EcmaOpcode::TONUMBER_IMM8:
LowerToNumber();
break;
case kungfu::EcmaOpcode::NEG_IMM8:
LowerNeg();
break;
case kungfu::EcmaOpcode::NOT_IMM8:
LowerNot();
break;
case kungfu::EcmaOpcode::SHL2_IMM8_V8:
LowerShl2();
break;
case kungfu::EcmaOpcode::SHR2_IMM8_V8:
LowerShr2();
break;
case kungfu::EcmaOpcode::ASHR2_IMM8_V8:
LowerAshr2();
break;
case kungfu::EcmaOpcode::AND2_IMM8_V8:
LowerAnd2();
break;
case kungfu::EcmaOpcode::OR2_IMM8_V8:
LowerOr2();
break;
case kungfu::EcmaOpcode::XOR2_IMM8_V8:
LowerXor2();
break;
case kungfu::EcmaOpcode::DELOBJPROP_V8:
LowerDelObjProp();
break;
case kungfu::EcmaOpcode::DEFINEMETHOD_IMM8_ID16_IMM8:
case kungfu::EcmaOpcode::DEFINEMETHOD_IMM16_ID16_IMM8:
LowerDefineMethod();
break;
case kungfu::EcmaOpcode::EXP_IMM8_V8:
LowerExp();
break;
case kungfu::EcmaOpcode::ISIN_IMM8_V8:
LowerIsIn();
break;
case kungfu::EcmaOpcode::INSTANCEOF_IMM8_V8:
LowerInstanceOf();
break;
case kungfu::EcmaOpcode::STRICTNOTEQ_IMM8_V8:
LowerStrictNotEq();
break;
case kungfu::EcmaOpcode::STRICTEQ_IMM8_V8:
LowerStrictEq();
break;
case kungfu::EcmaOpcode::CREATEEMPTYARRAY_IMM8:
case kungfu::EcmaOpcode::CREATEEMPTYARRAY_IMM16:
LowerCreateEmptyArray();
break;
case kungfu::EcmaOpcode::CREATEEMPTYOBJECT:
LowerCreateEmptyObject();
break;
case kungfu::EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
case kungfu::EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16:
LowerCreateObjectWithBuffer();
break;
case kungfu::EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
case kungfu::EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
LowerCreateArrayWithBuffer();
break;
case kungfu::EcmaOpcode::STMODULEVAR_IMM8:
case kungfu::EcmaOpcode::WIDE_STMODULEVAR_PREF_IMM16:
LowerStModuleVar();
break;
case kungfu::EcmaOpcode::GETTEMPLATEOBJECT_IMM8:
case kungfu::EcmaOpcode::GETTEMPLATEOBJECT_IMM16:
LowerGetTemplateObject();
break;
case kungfu::EcmaOpcode::SETOBJECTWITHPROTO_IMM8_V8:
case kungfu::EcmaOpcode::SETOBJECTWITHPROTO_IMM16_V8:
LowerSetObjectWithProto();
break;
case kungfu::EcmaOpcode::LDBIGINT_ID16:
LowerLoadBigInt();
break;
case kungfu::EcmaOpcode::TONUMERIC_IMM8:
LowerToNumeric();
break;
case kungfu::EcmaOpcode::DYNAMICIMPORT:
LowerDynamicImport();
break;
case kungfu::EcmaOpcode::LDEXTERNALMODULEVAR_IMM8:
case kungfu::EcmaOpcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16:
LowerLdExternalModuleVar();
break;
case kungfu::EcmaOpcode::GETMODULENAMESPACE_IMM8:
case kungfu::EcmaOpcode::WIDE_GETMODULENAMESPACE_PREF_IMM16:
LowerGetModuleNamespace();
break;
case kungfu::EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8:
case kungfu::EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8:
LowerNewObjRange();
break;
case kungfu::EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8:
LowerNewObjRange();
break;
case kungfu::EcmaOpcode::JEQZ_IMM8:
case kungfu::EcmaOpcode::JEQZ_IMM16:
case kungfu::EcmaOpcode::JEQZ_IMM32:
LowerJumpIfFalse();
break;
case kungfu::EcmaOpcode::JNEZ_IMM8:
case kungfu::EcmaOpcode::JNEZ_IMM16:
case kungfu::EcmaOpcode::JNEZ_IMM32:
LowerJumpIfTrue();
break;
case kungfu::EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
case kungfu::EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
LowerSuperCallThisRange();
break;
case kungfu::EcmaOpcode::SUPERCALLARROWRANGE_IMM8_IMM8_V8:
case kungfu::EcmaOpcode::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8:
LowerSuperCallArrowRange();
break;
case kungfu::EcmaOpcode::SUPERCALLSPREAD_IMM8_V8:
LowerSuperCallSpread();
break;
case kungfu::EcmaOpcode::CALLRUNTIME_SUPERCALLFORWARDALLARGS_PREF_V8:
LowerSuperCallForwardAllArgs();
break;
case kungfu::EcmaOpcode::ISTRUE:
case kungfu::EcmaOpcode::CALLRUNTIME_ISTRUE_PREF_IMM8:
LowerIsTrueOrFalse(true);
break;
case kungfu::EcmaOpcode::ISFALSE:
case kungfu::EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8:
LowerIsTrueOrFalse(false);
break;
case kungfu::EcmaOpcode::GETNEXTPROPNAME_V8:
LowerGetNextPropName();
break;
case kungfu::EcmaOpcode::COPYDATAPROPERTIES_V8:
LowerCopyDataProperties();
break;
case kungfu::EcmaOpcode::CREATEOBJECTWITHEXCLUDEDKEYS_IMM8_V8_V8:
case kungfu::EcmaOpcode::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8:
LowerCreateObjectWithExcludedKeys();
break;
case kungfu::EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8:
case kungfu::EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8:
LowerCreateRegExpWithLiteral();
break;
case kungfu::EcmaOpcode::STOWNBYVALUE_IMM8_V8_V8:
case kungfu::EcmaOpcode::STOWNBYVALUE_IMM16_V8_V8:
LowerStOwnByValue();
break;
case kungfu::EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16:
case kungfu::EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16:
case kungfu::EcmaOpcode::WIDE_STOWNBYINDEX_PREF_V8_IMM32:
LowerStOwnByIndex();
break;
case kungfu::EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8:
case kungfu::EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8:
LowerStOwnByName();
break;
case kungfu::EcmaOpcode::NEWLEXENV_IMM8:
case kungfu::EcmaOpcode::WIDE_NEWLEXENV_PREF_IMM16:
LowerNewLexicalEnv();
break;
case kungfu::EcmaOpcode::NEWLEXENVWITHNAME_IMM8_ID16:
case kungfu::EcmaOpcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16:
LowerNewLexicalEnvWithName();
break;
case kungfu::EcmaOpcode::POPLEXENV:
LowerPopLexicalEnv();
break;
case kungfu::EcmaOpcode::LDSUPERBYVALUE_IMM8_V8:
case kungfu::EcmaOpcode::LDSUPERBYVALUE_IMM16_V8:
LowerLdSuperByValue();
break;
case kungfu::EcmaOpcode::STSUPERBYVALUE_IMM16_V8_V8:
case kungfu::EcmaOpcode::STSUPERBYVALUE_IMM8_V8_V8:
LowerStSuperByValue();
break;
case kungfu::EcmaOpcode::TRYSTGLOBALBYNAME_IMM8_ID16:
case kungfu::EcmaOpcode::TRYSTGLOBALBYNAME_IMM16_ID16:
LowerTryStGlobalByName();
break;
case kungfu::EcmaOpcode::STCONSTTOGLOBALRECORD_IMM16_ID16:
LowerStConstToGlobalRecord(true);
break;
case kungfu::EcmaOpcode::STTOGLOBALRECORD_IMM16_ID16:
LowerStConstToGlobalRecord(false);
break;
case kungfu::EcmaOpcode::STOWNBYVALUEWITHNAMESET_IMM8_V8_V8:
case kungfu::EcmaOpcode::STOWNBYVALUEWITHNAMESET_IMM16_V8_V8:
LowerStOwnByValueWithNameSet();
break;
case kungfu::EcmaOpcode::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8:
case kungfu::EcmaOpcode::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8:
LowerStOwnByNameWithNameSet();
break;
case kungfu::EcmaOpcode::LDGLOBALVAR_IMM16_ID16:
LowerLdGlobalVar();
break;
case kungfu::EcmaOpcode::LDOBJBYNAME_IMM8_ID16:
case kungfu::EcmaOpcode::LDOBJBYNAME_IMM16_ID16:
LowerLoadObjByName();
break;
case kungfu::EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
case kungfu::EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
LowerStoreObjByName();
break;
case kungfu::EcmaOpcode::DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8:
LowerDefineGetterSetterByValue();
break;
case kungfu::EcmaOpcode::LDOBJBYINDEX_IMM8_IMM16:
case kungfu::EcmaOpcode::LDOBJBYINDEX_IMM16_IMM16:
LowerLdObjByIndex();
break;
case kungfu::EcmaOpcode::WIDE_LDOBJBYINDEX_PREF_IMM32:
LowerLdObjByIndex();
break;
case kungfu::EcmaOpcode::STOBJBYINDEX_IMM8_V8_IMM16:
case kungfu::EcmaOpcode::STOBJBYINDEX_IMM16_V8_IMM16:
LowerStObjByIndex();
break;
case kungfu::EcmaOpcode::WIDE_STOBJBYINDEX_PREF_V8_IMM32:
LowerStObjByIndex();
break;
case kungfu::EcmaOpcode::LDOBJBYVALUE_IMM8_V8:
case kungfu::EcmaOpcode::LDOBJBYVALUE_IMM16_V8:
LowerLoadObjByValue();
break;
case kungfu::EcmaOpcode::LDTHISBYVALUE_IMM8:
case kungfu::EcmaOpcode::LDTHISBYVALUE_IMM16:
LowerLdThisByValue();
break;
case kungfu::EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8:
case kungfu::EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8:
LowerStoreObjByValue();
break;
case kungfu::EcmaOpcode::STTHISBYVALUE_IMM8_V8:
case kungfu::EcmaOpcode::STTHISBYVALUE_IMM16_V8:
LowerStThisByValue();
break;
case kungfu::EcmaOpcode::LDSUPERBYNAME_IMM8_ID16:
case kungfu::EcmaOpcode::LDSUPERBYNAME_IMM16_ID16:
LowerLdSuperByName();
break;
case kungfu::EcmaOpcode::STSUPERBYNAME_IMM8_ID16_V8:
case kungfu::EcmaOpcode::STSUPERBYNAME_IMM16_ID16_V8:
LowerStSuperByName();
break;
case kungfu::EcmaOpcode::STARRAYSPREAD_V8_V8:
LowerStoreArraySpread();
break;
case kungfu::EcmaOpcode::LDLEXVAR_IMM4_IMM4:
case kungfu::EcmaOpcode::LDLEXVAR_IMM8_IMM8:
case kungfu::EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16:
LowerLdLexVar();
break;
case kungfu::EcmaOpcode::STLEXVAR_IMM4_IMM4:
case kungfu::EcmaOpcode::STLEXVAR_IMM8_IMM8:
case kungfu::EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16:
LowerStLexVar();
break;
case kungfu::EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
case kungfu::EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
LowerDefineClassWithBuffer();
break;
case kungfu::EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8:
case kungfu::EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8:
LowerDefineFunc();
break;
case kungfu::EcmaOpcode::COPYRESTARGS_IMM8:
case kungfu::EcmaOpcode::WIDE_COPYRESTARGS_PREF_IMM16:
LowerCopyRestArgs();
break;
case kungfu::EcmaOpcode::WIDE_LDPATCHVAR_PREF_IMM16:
LowerLdPatchVar();
break;
case kungfu::EcmaOpcode::WIDE_STPATCHVAR_PREF_IMM16:
LowerStPatchVar();
break;
case kungfu::EcmaOpcode::LDLOCALMODULEVAR_IMM8:
case kungfu::EcmaOpcode::WIDE_LDLOCALMODULEVAR_PREF_IMM16:
LowerLdLocalModuleVar();
break;
case kungfu::EcmaOpcode::LDTHISBYNAME_IMM8_ID16:
case kungfu::EcmaOpcode::LDTHISBYNAME_IMM16_ID16:
LowerLdThisByName();
break;
case kungfu::EcmaOpcode::STTHISBYNAME_IMM8_ID16:
case kungfu::EcmaOpcode::STTHISBYNAME_IMM16_ID16:
LowerStThisByName();
break;
case kungfu::EcmaOpcode::LDPRIVATEPROPERTY_IMM8_IMM16_IMM16:
LowerLdPrivateProperty();
break;
case kungfu::EcmaOpcode::STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8:
LowerStPrivateProperty();
break;
case kungfu::EcmaOpcode::TESTIN_IMM8_IMM16_IMM16:
LowerTestIn();
break;
case kungfu::EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE:
LowerNotifyConcurrentResult();
break;
case kungfu::EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8:
LowerDefinePropertyByName();
break;
case kungfu::EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
LowerDefineFieldByName();
break;
case kungfu::EcmaOpcode::CALLRUNTIME_DEFINEFIELDBYVALUE_PREF_IMM8_V8_V8:
LowerDefineFieldByValue();
break;
case kungfu::EcmaOpcode::CALLRUNTIME_DEFINEFIELDBYINDEX_PREF_IMM8_IMM32_V8:
LowerDefineFieldByIndex();
break;
case kungfu::EcmaOpcode::CALLRUNTIME_TOPROPERTYKEY_PREF_NONE:
LowerToPropertyKey();
break;
case kungfu::EcmaOpcode::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16:
LowerCreatePrivateProperty();
break;
case kungfu::EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM8_IMM16_IMM16_V8:
LowerDefinePrivateProperty();
break;
case kungfu::EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8:
case kungfu::EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16:
LowerLdExternalModuleVar();
break;
case kungfu::EcmaOpcode::LDA_STR_ID16:
LowerLoadString();
break;
case kungfu::EcmaOpcode::JMP_IMM8:
case kungfu::EcmaOpcode::JMP_IMM16:
case kungfu::EcmaOpcode::JMP_IMM32:
LowerJumpConstant();
break;
case kungfu::EcmaOpcode::LDNAN:
case kungfu::EcmaOpcode::LDINFINITY:
case kungfu::EcmaOpcode::LDUNDEFINED:
case kungfu::EcmaOpcode::LDNULL:
case kungfu::EcmaOpcode::LDTRUE:
case kungfu::EcmaOpcode::LDFALSE:
case kungfu::EcmaOpcode::LDHOLE:
case kungfu::EcmaOpcode::LDAI_IMM32:
case kungfu::EcmaOpcode::FLDAI_IMM64:
case kungfu::EcmaOpcode::LDFUNCTION:
case kungfu::EcmaOpcode::LDNEWTARGET:
case kungfu::EcmaOpcode::LDTHIS:
LowerLoadConst(info, opcode);
break;
case kungfu::EcmaOpcode::MOV_V4_V4:
case kungfu::EcmaOpcode::MOV_V8_V8:
case kungfu::EcmaOpcode::MOV_V16_V16:
case kungfu::EcmaOpcode::STA_V8:
case kungfu::EcmaOpcode::LDA_V8:
LowerMoveValues(info);
break;
case kungfu::EcmaOpcode::RETURNUNDEFINED:
case kungfu::EcmaOpcode::RETURN:
LowerReturn(opcode);
break;
default:
UNREACHABLE();
}
}
void ArkSteedGraphBuilder::LowerLoadString()
{
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *res = GetStringFromConstPool(stringId);
currentFrameState_->SetAcc(res);
}
void ArkSteedGraphBuilder::LowerLoadBigInt()
{
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *numberBigInt = GetStringFromConstPool(stringId);
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({numberBigInt}, RTSTUB_ID(LdBigInt)));
}
void ArkSteedGraphBuilder::LowerLoadConst(const BytecodeInfo &info, kungfu::EcmaOpcode opcode)
{
ValueVertex *vertex = nullptr;
switch (opcode) {
case EcmaOpcode::LDNAN:
vertex = GetTaggedConstant(base::NumberHelper::GetNaN());
break;
case EcmaOpcode::LDINFINITY:
vertex = GetTaggedConstant(base::NumberHelper::GetPositiveInfinity());
break;
case EcmaOpcode::LDUNDEFINED:
vertex = GetRootConstant(RootConstantVertex::RootIndex::UNDEFINED);
break;
case EcmaOpcode::LDNULL:
vertex = GetRootConstant(RootConstantVertex::RootIndex::NULL_VALUE);
break;
case EcmaOpcode::LDTRUE:
vertex = GetRootConstant(RootConstantVertex::RootIndex::TRUE_VALUE);
break;
case EcmaOpcode::LDFALSE:
vertex = GetRootConstant(RootConstantVertex::RootIndex::FALSE_VALUE);
break;
case EcmaOpcode::LDHOLE:
vertex = GetTaggedConstant(JSTaggedValue::VALUE_HOLE);
break;
case EcmaOpcode::LDAI_IMM32:
vertex = GetTaggedConstant(std::get<Immediate>(info.inputs[0]).ToJSTaggedValueInt());
break;
case EcmaOpcode::FLDAI_IMM64:
vertex = GetTaggedConstant(std::get<Immediate>(info.inputs[0]).ToJSTaggedValueDouble());
break;
case EcmaOpcode::LDFUNCTION:
vertex = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
break;
case EcmaOpcode::LDNEWTARGET:
vertex = currentFrameState_->GetParam(NEW_TARGET_PARAM_INDEX);
break;
case EcmaOpcode::LDTHIS:
vertex = currentFrameState_->GetParam(THIS_OBJECT_PARAM_INDEX);
break;
default:
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
currentFrameState_->SetAcc(vertex);
}
void ArkSteedGraphBuilder::LowerMoveValues(const BytecodeInfo &info)
{
ValueVertex *vertex = nullptr;
if (info.AccIn()) {
vertex = currentFrameState_->GetAcc();
} else if (!info.inputs.empty()) {
vertex = LoadRegister(0);
} else {
UNREACHABLE();
}
if (info.AccOut()) {
currentFrameState_->SetAcc(vertex);
} else if (!info.vregOut.empty()) {
currentFrameState_->Set(VirtualRegister(info.vregOut[0]), vertex);
} else {
UNREACHABLE();
}
}
void ArkSteedGraphBuilder::LowerCreateEmptyObject()
{
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({}, RTSTUB_ID(CreateEmptyObject)));
}
void ArkSteedGraphBuilder::LowerCreateEmptyArray()
{
ValueVertex *glue = GetGlue();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, globalEnv}, CommonStubCSigns::CreateEmptyArray));
}
void ArkSteedGraphBuilder::LowerCreateObjectWithBuffer()
{
ValueVertex *glue = GetGlue();
ValueVertex *index = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *obj = GetObjectFromConstPool(index);
ValueVertex *lexEnv = LoadRegister(1);
currentFrameState_->SetAcc(NewCommonStubCall({glue, obj, lexEnv}, CommonStubCSigns::CreateObjectHavingMethod));
}
void ArkSteedGraphBuilder::LowerCreateArrayWithBuffer()
{
ValueVertex *glue = GetGlue();
ValueVertex *index = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *slotId = GetInt32Constant(static_cast<int>(GetICSlotId(1)));
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(
NewCommonStubCall({glue, index, jsFunc, slotId, globalEnv}, CommonStubCSigns::CreateArrayWithBuffer));
}
void ArkSteedGraphBuilder::LowerCreateObjectWithExcludedKeys()
{
uint32_t inputSize = GetInputSize();
std::vector<ValueVertex *> args;
for (uint32_t idx = 0; idx < inputSize; idx++) {
args.push_back(LoadRegister(idx));
}
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>(args, RTSTUB_ID(OptCreateObjectWithExcludedKeys)));
}
void ArkSteedGraphBuilder::LowerCreateRegExpWithLiteral()
{
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *pattern = GetStringFromConstPool(stringId);
ValueVertex *flags = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(1)));
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({pattern, flags}, RTSTUB_ID(CreateRegExpWithLiteral)));
}
void ArkSteedGraphBuilder::LowerNewObjRange()
{
uint32_t inputSize = GetInputSize();
std::vector<ValueVertex *> args;
for (uint32_t idx = 0; idx < inputSize; idx++) {
args.push_back(LoadRegister(idx));
}
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>(args, RTSTUB_ID(OptNewObjRange)));
}
void ArkSteedGraphBuilder::LowerAdd2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Add));
}
void ArkSteedGraphBuilder::LowerSub2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Sub));
}
void ArkSteedGraphBuilder::LowerMul2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Mul));
}
void ArkSteedGraphBuilder::LowerDiv2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Div));
}
void ArkSteedGraphBuilder::LowerMod2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Mod));
}
void ArkSteedGraphBuilder::LowerExp()
{
ValueVertex *left = LoadRegister(0);
ValueVertex *right = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({left, right}, RTSTUB_ID(Exp)));
}
void ArkSteedGraphBuilder::LowerNeg()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x}, CommonStubCSigns::Neg));
}
void ArkSteedGraphBuilder::LowerInc()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x}, CommonStubCSigns::Inc));
}
void ArkSteedGraphBuilder::LowerDec()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x}, CommonStubCSigns::Dec));
}
void ArkSteedGraphBuilder::LowerShl2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Shl));
}
void ArkSteedGraphBuilder::LowerShr2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Shr));
}
void ArkSteedGraphBuilder::LowerAshr2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Ashr));
}
void ArkSteedGraphBuilder::LowerAnd2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::And));
}
void ArkSteedGraphBuilder::LowerOr2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Or));
}
void ArkSteedGraphBuilder::LowerXor2()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Xor));
}
void ArkSteedGraphBuilder::LowerNot()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x}, CommonStubCSigns::Not));
}
void ArkSteedGraphBuilder::LowerEq()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Equal));
}
void ArkSteedGraphBuilder::LowerNotEq()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::NotEqual));
}
void ArkSteedGraphBuilder::LowerLess()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Less));
}
void ArkSteedGraphBuilder::LowerLessEq()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::LessEq));
}
void ArkSteedGraphBuilder::LowerGreater()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Greater));
}
void ArkSteedGraphBuilder::LowerGreaterEq()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::GreaterEq));
}
void ArkSteedGraphBuilder::LowerStrictEq()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::StrictEqual));
}
void ArkSteedGraphBuilder::LowerStrictNotEq()
{
ValueVertex *glue = GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::StrictNotEqual));
}
void ArkSteedGraphBuilder::LowerTypeOf()
{
ValueVertex *glue = GetGlue();
ValueVertex *obj = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewCommonStubCall({glue, obj}, CommonStubCSigns::TypeOf));
}
void ArkSteedGraphBuilder::LowerToNumber()
{
ValueVertex *value = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({value}, RTSTUB_ID(ToNumber)));
}
void ArkSteedGraphBuilder::LowerToNumeric()
{
ValueVertex *value = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({value}, RTSTUB_ID(ToNumeric)));
}
void ArkSteedGraphBuilder::LowerIsIn()
{
ValueVertex *glue = GetGlue();
ValueVertex *prop = LoadRegister(0);
ValueVertex *obj = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, prop, obj, globalEnv}, CommonStubCSigns::IsIn));
}
void ArkSteedGraphBuilder::LowerInstanceOf()
{
ValueVertex *object = LoadRegister(1);
ValueVertex *target = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithIC(CommonStubCSigns::Instanceof, {object, target, globalEnv});
}
void ArkSteedGraphBuilder::LowerTestIn()
{
ValueVertex *levelIndex = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *slotIndex = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(2)));
ValueVertex *lexicalEnv = LoadRegister(3);
ValueVertex *obj = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(
NewVertex<CallRuntimeVertex>({lexicalEnv, levelIndex, slotIndex, obj}, RTSTUB_ID(TestIn)));
}
void ArkSteedGraphBuilder::LowerLoadObjByName()
{
ValueVertex *receiver = currentFrameState_->GetAcc();
ValueVertex *id = GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithIC(CommonStubCSigns::GetPropertyByName, {receiver, id, globalEnv});
}
void ArkSteedGraphBuilder::LowerCallArg0()
{
ValueVertex *glue = GetGlue();
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *result = NewCommonStubCall({glue, func}, CommonStubCSigns::CallArg0Stub);
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerCallArg1()
{
ValueVertex *glue = GetGlue();
ValueVertex *a0Value = LoadRegister(0);
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *result = NewCommonStubCall({glue, func, a0Value}, CommonStubCSigns::CallArg1Stub);
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerCallArgs2()
{
ValueVertex *glue = GetGlue();
ValueVertex *a0Value = LoadRegister(0);
ValueVertex *a1Value = LoadRegister(1);
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *result = NewCommonStubCall({glue, func, a0Value, a1Value}, CommonStubCSigns::CallArg2Stub);
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerCallArgs3()
{
ValueVertex *glue = GetGlue();
ValueVertex *a0Value = LoadRegister(0);
ValueVertex *a1Value = LoadRegister(1);
ValueVertex *a2Value = LoadRegister(2);
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *result = NewCommonStubCall({glue, func, a0Value, a1Value, a2Value}, CommonStubCSigns::CallArg3Stub);
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerCallRange()
{
uint32_t inputSize = GetInputSize();
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *taggedArray = GetTaggedArrayFromValueIn(inputSize);
ValueVertex *taggedLength = GetTaggedLength(inputSize);
ValueVertex *result = NewVertex<CallRuntimeVertex>({func, taggedArray, taggedLength}, RTSTUB_ID(CallRange));
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerReturn(kungfu::EcmaOpcode opcode)
{
ValueVertex *value = nullptr;
if (opcode == EcmaOpcode::RETURNUNDEFINED) {
value = GetRootConstant(RootConstantVertex::RootIndex::UNDEFINED);
} else {
value = currentFrameState_->GetAcc();
}
FinishBlock<ReturnVertex>({value});
}
void ArkSteedGraphBuilder::LowerThrow()
{
ValueVertex *exception = currentFrameState_->GetAcc();
BuildThrow(RTSTUB_ID(Throw), exception);
}
void ArkSteedGraphBuilder::LowerThrowConstAssignment()
{
ValueVertex *value = LoadRegister(0);
BuildThrow(RTSTUB_ID(ThrowConstAssignment), value);
}
void ArkSteedGraphBuilder::LowerThrowNotExists()
{
BuildThrow(RTSTUB_ID(ThrowThrowNotExists), nullptr);
}
void ArkSteedGraphBuilder::LowerThrowPatternNonCoercible()
{
BuildThrow(RTSTUB_ID(ThrowPatternNonCoercible), nullptr);
}
void ArkSteedGraphBuilder::LowerThrowIfNotObject()
{
}
void ArkSteedGraphBuilder::LowerThrowUndefinedIfHole()
{
}
void ArkSteedGraphBuilder::LowerThrowUndefinedIfHoleWithName()
{
}
void ArkSteedGraphBuilder::LowerThrowIfSuperNotCorrectCall()
{
ValueVertex *index = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *thisValue = currentFrameState_->GetAcc();
NewVertex<ThrowIfSuperNotCorrectCallVertex>({index, thisValue}, RTSTUB_ID(ThrowIfSuperNotCorrectCall));
}
void ArkSteedGraphBuilder::LowerThrowDeleteSuperProperty()
{
BuildThrow(RTSTUB_ID(ThrowDeleteSuperProperty), nullptr);
}
void ArkSteedGraphBuilder::LowerStoreObjByName()
{
ValueVertex *receiver = LoadRegister(2);
ValueVertex *id = GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithICPreserveAcc(CommonStubCSigns::SetPropertyByName, {receiver, id, value, globalEnv});
}
void ArkSteedGraphBuilder::LowerLoadObjByValue()
{
ValueVertex *receiver = LoadRegister(1);
ValueVertex *key = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithIC(CommonStubCSigns::GetPropertyByValue, {receiver, key, globalEnv});
}
void ArkSteedGraphBuilder::LowerStoreObjByValue()
{
ValueVertex *receiver = LoadRegister(1);
ValueVertex *key = LoadRegister(2);
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithICPreserveAcc(CommonStubCSigns::SetPropertyByValue, {receiver, key, value, globalEnv});
}
void ArkSteedGraphBuilder::LowerLdObjByIndex()
{
ValueVertex *glue = GetGlue();
ValueVertex *receiver = LoadRegister(1);
ValueVertex *index = GetInt32Constant(static_cast<int>(GetImmediate(0)));
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, receiver, index, globalEnv}, CommonStubCSigns::LdObjByIndex));
}
void ArkSteedGraphBuilder::LowerStObjByIndex()
{
ValueVertex *glue = GetGlue();
ValueVertex *receiver = LoadRegister(0);
ValueVertex *index = GetInt32Constant(static_cast<int>(GetImmediate(1)));
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, receiver, index, value, globalEnv}, CommonStubCSigns::StObjByIndex);
}
void ArkSteedGraphBuilder::LowerGetIterator()
{
ValueVertex *glue = GetGlue();
ValueVertex *obj = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, obj, globalEnv}, CommonStubCSigns::GetIterator));
}
void ArkSteedGraphBuilder::LowerGetPropIterator()
{
ValueVertex *glue = GetGlue();
ValueVertex *object = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, object, globalEnv}, CommonStubCSigns::Getpropiterator));
}
void ArkSteedGraphBuilder::LowerCloseIterator()
{
ValueVertex *iterator = LoadRegister(0);
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({iterator}, RTSTUB_ID(CloseIterator)));
}
void ArkSteedGraphBuilder::LowerGetNextPropName()
{
ValueVertex *iterator = LoadRegister(0);
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({iterator}, RTSTUB_ID(GetNextPropNameSlowpath)));
}
void ArkSteedGraphBuilder::LowerGetTemplateObject()
{
ValueVertex *value = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({value}, RTSTUB_ID(GetTemplateObject)));
}
void ArkSteedGraphBuilder::LowerStoreArraySpread()
{
ValueVertex *array = LoadRegister(0);
ValueVertex *index = LoadRegister(1);
ValueVertex *value = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({array, index, value}, RTSTUB_ID(StArraySpread)));
}
void ArkSteedGraphBuilder::LowerCallThis0()
{
ValueVertex *glue = GetGlue();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *result = NewCommonStubCall({glue, func, thisObj}, CommonStubCSigns::CallThis0Stub);
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerCallThis1()
{
ValueVertex *glue = GetGlue();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *a0Value = LoadRegister(1);
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *result = NewCommonStubCall({glue, func, thisObj, a0Value}, CommonStubCSigns::CallThis1Stub);
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerCallThis2()
{
ValueVertex *glue = GetGlue();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *a0Value = LoadRegister(1);
ValueVertex *a1Value = LoadRegister(2);
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *result = NewCommonStubCall({glue, func, thisObj, a0Value, a1Value}, CommonStubCSigns::CallThis2Stub);
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerCallThis3()
{
ValueVertex *glue = GetGlue();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *a0Value = LoadRegister(1);
ValueVertex *a1Value = LoadRegister(2);
ValueVertex *a2Value = LoadRegister(3);
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *result =
NewCommonStubCall({glue, func, thisObj, a0Value, a1Value, a2Value}, CommonStubCSigns::CallThis3Stub);
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerCallThisRange()
{
uint32_t inputSize = GetInputSize();
ASSERT(inputSize > 0);
uint32_t argc = inputSize - 1;
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *taggedArray = GetTaggedArrayFromValueIn(argc, 1);
ValueVertex *taggedLength = GetTaggedLength(argc);
ValueVertex *result =
NewVertex<CallRuntimeVertex>({thisObj, func, taggedArray, taggedLength}, RTSTUB_ID(CallThisRange));
currentFrameState_->SetAcc(result);
}
void ArkSteedGraphBuilder::LowerCallSpread()
{
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *thisArg = LoadRegister(0);
ValueVertex *argsArray = LoadRegister(1);
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({func, thisArg, argsArray}, RTSTUB_ID(CallSpread)));
}
void ArkSteedGraphBuilder::LowerGetUnmappedArgs()
{
ValueVertex *glue = GetGlue();
ValueVertex *argv = GetIntPtrConstant(0);
ValueVertex *numArgs = GetActualArgc();
ValueVertex *argvTaggedArray = GetRootConstant(RootConstantVertex::RootIndex::UNDEFINED);
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(
NewCommonStubCall({glue, argv, numArgs, argvTaggedArray, globalEnv}, CommonStubCSigns::GetUnmappedArgs));
}
void ArkSteedGraphBuilder::LowerCreateIterResultObj()
{
ValueVertex *value = LoadRegister(0);
ValueVertex *done = LoadRegister(1);
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({value, done}, RTSTUB_ID(CreateIterResultObj)));
}
void ArkSteedGraphBuilder::LowerTryLdGlobalByName()
{
ValueVertex *id = GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithIC(CommonStubCSigns::TryLdGlobalByName, {id, globalEnv});
}
void ArkSteedGraphBuilder::LowerStGlobalVar()
{
ValueVertex *id = GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithICPreserveAcc(CommonStubCSigns::StGlobalVar, {id, value, globalEnv});
}
void ArkSteedGraphBuilder::LowerNewObjApply()
{
ValueVertex *target = LoadRegister(0);
ValueVertex *args = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({target, args}, RTSTUB_ID(NewObjApply)));
}
void ArkSteedGraphBuilder::LowerLdSymbol()
{
ValueVertex *globalEnv = GetGlobalEnv();
int32_t offset = static_cast<int32_t>(GlobalEnv::HEADER_SIZE +
GlobalEnv::SYMBOL_FUNCTION_INDEX * JSTaggedValue::TaggedTypeSize());
currentFrameState_->SetAcc(NewVertex<LoadTaggedFieldVertex>({globalEnv}, offset));
}
void ArkSteedGraphBuilder::LowerLdGlobal()
{
ValueVertex *globalEnv = GetGlobalEnv();
int32_t offset = static_cast<int32_t>(GlobalEnv::HEADER_SIZE +
GlobalEnv::JS_GLOBAL_OBJECT_INDEX * JSTaggedValue::TaggedTypeSize());
currentFrameState_->SetAcc(NewVertex<LoadTaggedFieldVertex>({globalEnv}, offset));
}
void ArkSteedGraphBuilder::LowerDelObjProp()
{
ValueVertex *glue = GetGlue();
ValueVertex *object = LoadRegister(0);
ValueVertex *prop = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(
NewCommonStubCall({glue, object, prop, globalEnv}, CommonStubCSigns::DeleteObjectProperty));
}
void ArkSteedGraphBuilder::LowerDefineMethod()
{
ValueVertex *glue = GetGlue();
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *methodId = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *taggedMethodId = NewVertex<ToTaggedIntVertex>({methodId});
ValueVertex *length = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *env = LoadRegister(2);
ValueVertex *homeObject = currentFrameState_->GetAcc();
ValueVertex *module = GetModuleFromFunction();
ValueVertex *method = GetMethodFromConstPool(taggedMethodId);
ValueVertex *slotId = NewTaggedVertexFromRawInt32(static_cast<int>(GetICSlotId(3)));
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>(
#if ECMASCRIPT_ENABLE_IC
{method, homeObject, length, env, module, slotId, jsFunc},
#else
{method, homeObject, length, env, module},
#endif
RTSTUB_ID(DefineMethod)));
}
void ArkSteedGraphBuilder::LowerStModuleVar()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *index = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *value = currentFrameState_->GetAcc();
NewVertex<CallRuntimeVertex>({index, value, jsFunc}, RTSTUB_ID(StModuleVarByIndexOnJSFunc));
}
void ArkSteedGraphBuilder::LowerSetObjectWithProto()
{
ValueVertex *proto = LoadRegister(0);
ValueVertex *obj = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({proto, obj}, RTSTUB_ID(SetObjectWithProto)));
}
void ArkSteedGraphBuilder::LowerDynamicImport()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *specifier = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({specifier, jsFunc}, RTSTUB_ID(DynamicImport)));
}
void ArkSteedGraphBuilder::LowerLdExternalModuleVar()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *index = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
currentFrameState_->SetAcc(
NewVertex<CallRuntimeVertex>({index, jsFunc}, RTSTUB_ID(LdExternalModuleVarByIndexOnJSFunc)));
}
void ArkSteedGraphBuilder::LowerGetModuleNamespace()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *index = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
currentFrameState_->SetAcc(
NewVertex<CallRuntimeVertex>({index, jsFunc}, RTSTUB_ID(GetModuleNamespaceByIndexOnJSFunc)));
}
void ArkSteedGraphBuilder::LowerSuperCallThisRange()
{
uint32_t inputSize = GetInputSize();
ValueVertex *thisFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *newTarget = currentFrameState_->GetParam(NEW_TARGET_PARAM_INDEX);
ValueVertex *taggedArray = GetTaggedArrayFromValueIn(inputSize);
ValueVertex *taggedLength = NewTaggedVertexFromRawInt32(static_cast<int>(inputSize));
currentFrameState_->SetAcc(
NewVertex<CallRuntimeVertex>({thisFunc, newTarget, taggedArray, taggedLength}, RTSTUB_ID(OptSuperCall)));
}
void ArkSteedGraphBuilder::LowerSuperCallArrowRange()
{
uint32_t inputSize = GetInputSize();
uint32_t argc = inputSize - 1;
ValueVertex *func = LoadRegister(argc);
ValueVertex *newTarget = currentFrameState_->GetParam(NEW_TARGET_PARAM_INDEX);
ValueVertex *taggedArray = GetTaggedArrayFromValueIn(argc);
ValueVertex *taggedLength = NewTaggedVertexFromRawInt32(static_cast<int>(argc));
currentFrameState_->SetAcc(
NewVertex<CallRuntimeVertex>({func, newTarget, taggedArray, taggedLength}, RTSTUB_ID(OptSuperCall)));
}
void ArkSteedGraphBuilder::LowerSuperCallSpread()
{
ValueVertex *glue = GetGlue();
ValueVertex *globalEnv = GetGlobalEnv();
ValueVertex *array = LoadRegister(0);
ValueVertex *func = currentFrameState_->GetAcc();
ValueVertex *newTarget = currentFrameState_->GetParam(NEW_TARGET_PARAM_INDEX);
ValueVertex *argsArray = NewCommonStubCall({glue, array, globalEnv}, CommonStubCSigns::GetCallSpreadArgs);
currentFrameState_->SetAcc(
NewVertex<CallRuntimeVertex>({func, newTarget, argsArray}, RTSTUB_ID(OptSuperCallSpread)));
}
void ArkSteedGraphBuilder::LowerSuperCallForwardAllArgs()
{
ValueVertex *func = LoadRegister(0);
ValueVertex *superFunc = NewCommonStubCall({GetGlue(), func}, CommonStubCSigns::GetPrototype);
ValueVertex *newTarget = currentFrameState_->GetParam(NEW_TARGET_PARAM_INDEX);
ValueVertex *actualArgc = NewVertex<ToTaggedIntVertex>({GetActualArgc()});
currentFrameState_->SetAcc(
NewVertex<CallRuntimeVertex>({superFunc, newTarget, actualArgc}, RTSTUB_ID(OptSuperCallForwardAllArgs)));
}
void ArkSteedGraphBuilder::LowerJumpConstant()
{
uint32_t index = iterator_.Index();
uint32_t targetBcIndex = iterator_.GetJumpTargetBcIndex();
BB *block = nullptr;
if (bytecodeContext_.GetJumpLoop()[index]) {
block = FinishBlock<JumpLoopVertex>({}, &jumpTargets_[targetBcIndex]);
block->SetPredecessorId(mergeStates_[targetBcIndex]->PredecessorsSoFar());
} else {
block = FinishBlock<JumpVertex>({}, &jumpTargets_[targetBcIndex]);
}
MergeCurrentFrameStateTo(block, targetBcIndex);
}
void ArkSteedGraphBuilder::LowerJumpIfTrue()
{
auto branchBuilder = CreateBranchBuilder(BranchType::TRUE_BRANCH);
BuildBranchIfTrue(branchBuilder, currentFrameState_->GetAcc());
}
void ArkSteedGraphBuilder::LowerJumpIfFalse()
{
auto branchBuilder = CreateBranchBuilder(BranchType::FALSE_BRANCH);
BuildBranchIfTrue(branchBuilder, currentFrameState_->GetAcc());
}
void ArkSteedGraphBuilder::LowerIsTrueOrFalse(bool isTrue)
{
ValueVertex *glue = GetGlue();
ValueVertex *value = currentFrameState_->GetAcc();
if (isTrue) {
currentFrameState_->SetAcc(NewCommonStubCall({glue, value}, CommonStubCSigns::ToBooleanTrue));
} else {
currentFrameState_->SetAcc(NewCommonStubCall({glue, value}, CommonStubCSigns::ToBooleanFalse));
}
}
void ArkSteedGraphBuilder::LowerCopyDataProperties()
{
ValueVertex *target = LoadRegister(0);
ValueVertex *source = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({target, source}, RTSTUB_ID(CopyDataProperties)));
}
void ArkSteedGraphBuilder::LowerStOwnByValue()
{
ValueVertex *glue = GetGlue();
ValueVertex *receiver = LoadRegister(0);
ValueVertex *key = LoadRegister(1);
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, receiver, key, value, globalEnv}, CommonStubCSigns::StOwnByValue);
}
void ArkSteedGraphBuilder::LowerStOwnByIndex()
{
ValueVertex *glue = GetGlue();
ValueVertex *receiver = LoadRegister(0);
ValueVertex *index = GetInt32Constant(static_cast<int>(GetImmediate(1)));
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, receiver, index, value, globalEnv}, CommonStubCSigns::StOwnByIndex);
}
void ArkSteedGraphBuilder::LowerStOwnByName()
{
ValueVertex *glue = GetGlue();
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *propKey = GetStringFromConstPool(stringId);
ValueVertex *receiver = LoadRegister(1);
ValueVertex *accValue = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, receiver, propKey, accValue, globalEnv}, CommonStubCSigns::StOwnByName);
}
void ArkSteedGraphBuilder::LowerNewLexicalEnv()
{
ValueVertex *glue = GetGlue();
ValueVertex *parent = LoadRegister(1);
ValueVertex *scope = GetInt32Constant(static_cast<int>(GetImmediate(0)));
ValueVertex *newEnv = NewCommonStubCall({glue, parent, scope}, CommonStubCSigns::NewLexicalEnv);
currentFrameState_->SetAcc(newEnv);
currentFrameState_->SetEnv(newEnv);
}
void ArkSteedGraphBuilder::LowerNewLexicalEnvWithName()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *level = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *slotId = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *newEnv = NewVertex<CallRuntimeVertex>(
{level, slotId, LoadRegister(2), jsFunc},
RTSTUB_ID(OptNewLexicalEnvWithName));
currentFrameState_->SetAcc(newEnv);
currentFrameState_->SetEnv(newEnv);
}
void ArkSteedGraphBuilder::LowerPopLexicalEnv()
{
ValueVertex *currentEnv = LoadRegister(0);
ValueVertex *parentEnv = GetValueFromTaggedArray(currentEnv, LexicalEnv::PARENT_ENV_INDEX);
currentFrameState_->SetAcc(parentEnv);
currentFrameState_->SetEnv(parentEnv);
}
void ArkSteedGraphBuilder::LowerLdSuperByValue()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *propKey = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({thisObj, propKey, jsFunc}, RTSTUB_ID(OptLdSuperByValue)));
}
void ArkSteedGraphBuilder::LowerStSuperByValue()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *propKey = LoadRegister(1);
ValueVertex *value = currentFrameState_->GetAcc();
NewVertex<CallRuntimeVertex>({thisObj, propKey, value, jsFunc}, RTSTUB_ID(OptStSuperByValue));
}
void ArkSteedGraphBuilder::LowerTryStGlobalByName()
{
ValueVertex *id = GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithICPreserveAcc(CommonStubCSigns::TryStGlobalByName, {id, value, globalEnv});
}
void ArkSteedGraphBuilder::LowerStConstToGlobalRecord(bool isConst)
{
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *propKey = GetStringFromConstPool(stringId);
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *isConstGate = isConst ? GetTaggedConstant(JSTaggedValue::True().GetRawData())
: GetTaggedConstant(JSTaggedValue::False().GetRawData());
NewVertex<CallRuntimeVertex>({propKey, value, isConstGate}, RTSTUB_ID(StGlobalRecord));
}
void ArkSteedGraphBuilder::LowerStOwnByValueWithNameSet()
{
ValueVertex *glue = GetGlue();
ValueVertex *receiver = LoadRegister(0);
ValueVertex *propKey = LoadRegister(1);
ValueVertex *accValue = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, receiver, propKey, accValue, globalEnv}, CommonStubCSigns::StOwnByValueWithNameSet);
}
void ArkSteedGraphBuilder::LowerStOwnByNameWithNameSet()
{
ValueVertex *glue = GetGlue();
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *propKey = GetStringFromConstPool(stringId);
ValueVertex *receiver = LoadRegister(1);
ValueVertex *accValue = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, receiver, propKey, accValue, globalEnv}, CommonStubCSigns::StOwnByNameWithNameSet);
}
void ArkSteedGraphBuilder::LowerLdGlobalVar()
{
ValueVertex *id = GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithIC(CommonStubCSigns::LdGlobalVar, {id, globalEnv});
}
void ArkSteedGraphBuilder::LowerDefineGetterSetterByValue()
{
ValueVertex *obj = LoadRegister(0);
ValueVertex *prop = LoadRegister(1);
ValueVertex *getter = LoadRegister(2);
ValueVertex *setter = LoadRegister(3);
ValueVertex *acc = currentFrameState_->GetAcc();
ValueVertex *undefinedValue = GetRootConstant(RootConstantVertex::RootIndex::UNDEFINED);
ValueVertex *taggedOne = NewTaggedVertexFromRawInt32(1);
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({obj, prop, getter, setter, acc, undefinedValue, taggedOne},
RTSTUB_ID(DefineGetterSetterByValue)));
}
void ArkSteedGraphBuilder::LowerLdThisByValue()
{
ValueVertex *receiver = currentFrameState_->GetParam(THIS_OBJECT_PARAM_INDEX);
ValueVertex *key = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithIC(CommonStubCSigns::GetPropertyByValue, {receiver, key, globalEnv});
}
void ArkSteedGraphBuilder::LowerStThisByValue()
{
ValueVertex *receiver = currentFrameState_->GetParam(THIS_OBJECT_PARAM_INDEX);
ValueVertex *key = LoadRegister(1);
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithICPreserveAcc(CommonStubCSigns::SetPropertyByValue, {receiver, key, value, globalEnv});
}
void ArkSteedGraphBuilder::LowerLdSuperByName()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *thisObj = currentFrameState_->GetAcc();
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *prop = GetStringFromConstPool(stringId);
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({thisObj, prop, jsFunc}, RTSTUB_ID(OptLdSuperByValue)));
}
void ArkSteedGraphBuilder::LowerStSuperByName()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *thisObj = LoadRegister(1);
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *prop = GetStringFromConstPool(stringId);
NewVertex<CallRuntimeVertex>({thisObj, prop, value, jsFunc}, RTSTUB_ID(OptStSuperByValue));
}
void ArkSteedGraphBuilder::LowerLdLexVar()
{
ValueVertex *level = GetInt32Constant(static_cast<int>(GetImmediate(0)));
ValueVertex *slot = GetInt32Constant(static_cast<int>(GetImmediate(1)));
ValueVertex *lexicalEnv = LoadRegister(2);
ValueVertex *glue = GetGlue();
currentFrameState_->SetAcc(NewCommonStubCall({glue, level, slot, lexicalEnv}, CommonStubCSigns::LdLexVar));
}
void ArkSteedGraphBuilder::LowerStLexVar()
{
ValueVertex *level = GetInt32Constant(static_cast<int>(GetImmediate(0)));
ValueVertex *slot = GetInt32Constant(static_cast<int>(GetImmediate(1)));
ValueVertex *lexicalEnv = LoadRegister(2);
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *glue = GetGlue();
NewCommonStubCall({glue, level, slot, lexicalEnv, value}, CommonStubCSigns::StLexVar);
}
void ArkSteedGraphBuilder::LowerDefineClassWithBuffer()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *methodId = NewTaggedVertexFromRawInt32(static_cast<int>(GetConstDataId(0)));
ValueVertex *literalId = NewTaggedVertexFromRawInt32(static_cast<int>(GetConstDataId(1)));
ValueVertex *length = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(2)));
ValueVertex *proto = LoadRegister(3);
ValueVertex *lexicalEnv = LoadRegister(4);
ValueVertex *slotId = NewTaggedVertexFromRawInt32(static_cast<int>(GetICSlotId(5)));
ValueVertex *sharedConstPool = GetSharedConstPool();
ValueVertex *module = GetModuleFromFunction();
std::vector<ValueVertex *> args = {
proto,
lexicalEnv,
sharedConstPool,
methodId,
literalId,
module,
length,
#if ECMASCRIPT_ENABLE_IC
slotId,
jsFunc
#endif
};
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>(args, RTSTUB_ID(CreateClassWithBuffer)));
}
void ArkSteedGraphBuilder::LowerDefineFunc()
{
ValueVertex *glue = GetGlue();
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *slotId = GetInt32Constant(static_cast<int>(GetICSlotId(0)));
ValueVertex *methodId = GetInt32Constant(static_cast<int>(GetConstDataId(1)));
ValueVertex *length = GetInt32Constant(static_cast<int>(GetImmediate(2)));
ValueVertex *lexicalEnv = LoadRegister(3);
ValueVertex *globalEnv = GetGlobalEnv();
currentFrameState_->SetAcc(NewCommonStubCall({glue, jsFunc, methodId, length, lexicalEnv, slotId, globalEnv},
CommonStubCSigns::Definefunc));
}
void ArkSteedGraphBuilder::LowerCopyRestArgs()
{
ValueVertex *actualArgc = GetActualArgc();
ValueVertex *taggedArgc = NewVertex<ToTaggedIntVertex>({actualArgc});
ValueVertex *taggedRestIdx = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({taggedArgc, taggedRestIdx}, RTSTUB_ID(OptCopyRestArgs)));
}
void ArkSteedGraphBuilder::LowerLdPatchVar()
{
ValueVertex *index = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({index}, RTSTUB_ID(LdPatchVar)));
}
void ArkSteedGraphBuilder::LowerStPatchVar()
{
ValueVertex *index = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *value = currentFrameState_->GetAcc();
NewVertex<CallRuntimeVertex>({index, value}, RTSTUB_ID(StPatchVar));
}
void ArkSteedGraphBuilder::LowerLdLocalModuleVar()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *index = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
currentFrameState_->SetAcc(
NewVertex<CallRuntimeVertex>({index, jsFunc}, RTSTUB_ID(LdLocalModuleVarByIndexOnJSFunc)));
}
void ArkSteedGraphBuilder::LowerLdThisByName()
{
ValueVertex *receiver = currentFrameState_->GetParam(THIS_OBJECT_PARAM_INDEX);
ValueVertex *id = GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithIC(CommonStubCSigns::GetPropertyByName, {receiver, id, globalEnv});
}
void ArkSteedGraphBuilder::LowerStThisByName()
{
ValueVertex *receiver = currentFrameState_->GetParam(THIS_OBJECT_PARAM_INDEX);
ValueVertex *id = GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
LowerCallStubWithICPreserveAcc(CommonStubCSigns::SetPropertyByName, {receiver, id, value, globalEnv});
}
void ArkSteedGraphBuilder::LowerLdPrivateProperty()
{
ValueVertex *levelIndex = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *slotIndex = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(2)));
ValueVertex *lexicalEnv = LoadRegister(3);
ValueVertex *obj = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(
NewVertex<CallRuntimeVertex>({lexicalEnv, levelIndex, slotIndex, obj}, RTSTUB_ID(LdPrivateProperty)));
}
void ArkSteedGraphBuilder::LowerStPrivateProperty()
{
ValueVertex *levelIndex = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *slotIndex = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(2)));
ValueVertex *obj = LoadRegister(3);
ValueVertex *lexicalEnv = LoadRegister(4);
ValueVertex *value = currentFrameState_->GetAcc();
NewVertex<CallRuntimeVertex>({lexicalEnv, levelIndex, slotIndex, obj, value}, RTSTUB_ID(StPrivateProperty));
}
void ArkSteedGraphBuilder::LowerNotifyConcurrentResult()
{
ValueVertex *jsFunc = currentFrameState_->GetParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *result = currentFrameState_->GetAcc();
NewVertex<CallRuntimeVertex>({result, jsFunc}, RTSTUB_ID(NotifyConcurrentResult));
}
void ArkSteedGraphBuilder::LowerDefinePropertyByName()
{
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(1)));
ValueVertex *prop = GetStringFromConstPool(stringId);
ValueVertex *obj = LoadRegister(2);
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *glue = GetGlue();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, obj, prop, value, globalEnv}, CommonStubCSigns::DefineField);
}
void ArkSteedGraphBuilder::LowerDefineFieldByName()
{
ValueVertex *stringId = GetInt32Constant(static_cast<int>(GetConstDataId(1)));
ValueVertex *prop = GetStringFromConstPool(stringId);
ValueVertex *obj = LoadRegister(2);
ValueVertex *value = currentFrameState_->GetAcc();
ValueVertex *glue = GetGlue();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, obj, prop, value, globalEnv}, CommonStubCSigns::DefineField);
}
void ArkSteedGraphBuilder::LowerDefineFieldByValue()
{
ValueVertex *glue = GetGlue();
ValueVertex *receiver = LoadRegister(1);
ValueVertex *propKey = LoadRegister(0);
ValueVertex *acc = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, receiver, propKey, acc, globalEnv}, CommonStubCSigns::DefineField);
}
void ArkSteedGraphBuilder::LowerDefineFieldByIndex()
{
ValueVertex *glue = GetGlue();
ValueVertex *receiver = LoadRegister(1);
ValueVertex *propKey = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *acc = currentFrameState_->GetAcc();
ValueVertex *globalEnv = GetGlobalEnv();
NewCommonStubCall({glue, receiver, propKey, acc, globalEnv}, CommonStubCSigns::DefineField);
}
void ArkSteedGraphBuilder::LowerToPropertyKey()
{
ValueVertex *value = currentFrameState_->GetAcc();
currentFrameState_->SetAcc(NewVertex<CallRuntimeVertex>({value}, RTSTUB_ID(ToPropertyKey)));
}
void ArkSteedGraphBuilder::LowerCreatePrivateProperty()
{
ValueVertex *count = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *literalId = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *lexicalEnv = LoadRegister(2);
ValueVertex *constpool = GetSharedConstPool();
ValueVertex *module = GetModuleFromFunction();
NewVertex<CallRuntimeVertex>({lexicalEnv, count, constpool, literalId, module}, RTSTUB_ID(CreatePrivateProperty));
}
void ArkSteedGraphBuilder::LowerDefinePrivateProperty()
{
ValueVertex *levelIndex = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *slotIndex = NewTaggedVertexFromRawInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *obj = LoadRegister(2);
ValueVertex *lexicalEnv = LoadRegister(3);
ValueVertex *value = currentFrameState_->GetAcc();
NewVertex<CallRuntimeVertex>({lexicalEnv, levelIndex, slotIndex, obj, value}, RTSTUB_ID(DefinePrivateProperty));
}
void ArkSteedGraphBuilder::MergeCurrentFrameStateTo(BB *predecessor, uint32_t destIndex)
{
ASSERT(predecessor != nullptr);
if (mergeStates_[destIndex] == nullptr) {
const LivenessBitSet *liveness = GetInLivenessFor(destIndex);
uint32_t predCount = PredecessorCount(destIndex);
ASSERT(predCount > 0);
mergeStates_[destIndex] = MergePointFrameState::New(destIndex, predCount, liveness, GetChunk());
}
mergeStates_[destIndex]->MergeFrom(*currentFrameState_, predecessor);
}
ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::Label::Label(ArkSteedSubGraphBuilder *subBuilder,
uint32_t predecessorCount)
: subBuilder_(subBuilder),
predecessorCount_(predecessorCount),
mergeLiveSet_(subBuilder->builder_->GetChunk()->New<LivenessBitSet>(
subBuilder->builder_->GetChunk(), subBuilder->numLocal_, subBuilder->numParams_))
{
}
ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::Label::Label(ArkSteedSubGraphBuilder *subBuilder,
uint32_t predecessorCount,
std::initializer_list<SubGraphVariable *> liveVariables)
: Label(subBuilder, predecessorCount)
{
for (SubGraphVariable *var : liveVariables) {
ASSERT(var != nullptr);
mergeLiveSet_->Set(var->pseudoRegister_);
}
}
ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::ArkSteedSubGraphBuilder(ArkSteedGraphBuilder *builder, int variableCount)
: builder_(builder),
numLocal_(CheckedSubGraphVariableCount(variableCount)),
numParams_(0),
subGraphFrame_(builder->GetChunk()->New<InterpreterFrameState>(numLocal_, numParams_, builder->GetChunk()))
{
InterpreterFrameState *parentFrame = builder_->CurrentFrameState();
ASSERT(parentFrame != nullptr);
subGraphFrame_->SetEnv(parentFrame->GetEnv());
subGraphFrame_->SetAcc(parentFrame->GetAcc());
}
void ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::MergeIntoLabel(Label *label, BB *predecessor)
{
ASSERT(label != nullptr);
ASSERT(label->subBuilder_ == this);
ASSERT(predecessor != nullptr);
if (label->variableMergeState_ == nullptr) {
label->variableMergeState_ = MergePointFrameState::New(
BytecodeContext::INVALID_BC_INDEX, label->predecessorCount_, label->mergeLiveSet_, builder_->GetChunk());
}
label->variableMergeState_->MergeFrom(*subGraphFrame_, predecessor);
}
void ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::TrimUnmergedPredecessors(Label *label, uint32_t num)
{
ASSERT(label != nullptr);
ASSERT(label->subBuilder_ == this);
ASSERT(num <= label->predecessorCount_);
if (num == 0) {
return;
}
label->predecessorCount_ -= num;
if (label->variableMergeState_ != nullptr) {
label->variableMergeState_->ReducePredecessorCount(num);
}
}
void ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::Goto(Label *label)
{
ASSERT(builder_->CurrentBlock() != nullptr);
BB *predecessor = builder_->FinishBlock<JumpVertex>({}, &label->ref_);
MergeIntoLabel(label, predecessor);
}
void ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::GotoOrTrim(Label *label)
{
if (builder_->CurrentBlock() == nullptr) {
TrimUnmergedPredecessors(label);
return;
}
Goto(label);
}
void ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::Bind(Label *label)
{
ASSERT(label != nullptr);
ASSERT(label->subBuilder_ == this);
ASSERT(builder_->CurrentBlock() == nullptr);
ASSERT(label->variableMergeState_ != nullptr);
ASSERT(label->variableMergeState_->PredecessorsSoFar() == label->predecessorCount_);
subGraphFrame_->CopyFrom(*label->variableMergeState_);
builder_->StartNewBlock(nullptr, label->variableMergeState_, &label->ref_);
builder_->ProcessMergePointPredecessors(label->variableMergeState_, &label->ref_, builder_->CurrentBlock());
}
ArkSteedGraphBuilder::ReduceResult ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::TrimPredecessorsAndBind(Label *label)
{
ASSERT(label != nullptr);
uint32_t predecessorsSoFar =
label->variableMergeState_ == nullptr ? 0 : label->variableMergeState_->PredecessorsSoFar();
if (predecessorsSoFar == 0) {
builder_->SetCurrentBlock(nullptr);
return ReduceResult::DoneWithAbort();
}
ASSERT(predecessorsSoFar <= label->predecessorCount_);
builder_->SetCurrentBlock(nullptr);
TrimUnmergedPredecessors(label, label->predecessorCount_ - predecessorsSoFar);
Bind(label);
return ReduceResult::Done();
}
ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::LoopLabel ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::BeginLoop(
std::initializer_list<SubGraphVariable *> loopVars)
{
constexpr uint32_t kLoopHeaderPredecessorCount = 2;
Chunk *chunk = builder_->GetChunk();
auto *loopHeaderRef = chunk->New<BBRef>();
auto *loopInfo = chunk->New<LoopInfo>(chunk, BytecodeContext::INVALID_BC_INDEX, BytecodeContext::INVALID_BC_INDEX,
numLocal_, numParams_);
auto *loopHeaderLiveness = chunk->New<LivenessBitSet>(chunk, numLocal_, numParams_);
for (SubGraphVariable *var : loopVars) {
ASSERT(var != nullptr);
loopHeaderLiveness->Set(var->pseudoRegister_);
loopInfo->AddDef(var->pseudoRegister_);
}
BB *loopPredecessor = builder_->FinishBlock<JumpVertex>({}, loopHeaderRef);
MergePointFrameState *loopState = MergePointFrameState::NewForLoop(
BytecodeContext::INVALID_BC_INDEX, kLoopHeaderPredecessorCount, loopHeaderLiveness, loopInfo, chunk);
loopState->MergeFrom(*subGraphFrame_, loopPredecessor);
builder_->StartNewBlock(nullptr, loopState, loopHeaderRef);
BB *loopHeaderBlock = builder_->CurrentBlock();
builder_->ProcessMergePointPredecessors(loopState, loopHeaderRef, loopHeaderBlock);
subGraphFrame_->CopyFrom(*loopState);
return LoopLabel(this, loopState, loopHeaderRef, loopHeaderBlock);
}
void ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::EndLoop(LoopLabel *loopLabel)
{
ASSERT(loopLabel != nullptr);
ASSERT(loopLabel->subBuilder_ == this);
ASSERT(loopLabel->loopHeaderBlock_ != nullptr);
if (builder_->CurrentBlock() == nullptr) {
loopLabel->mergeState_->ReducePredecessorCount();
loopLabel->mergeState_->ClearIsLoop();
loopLabel->mergeState_->ClearLoopInfo();
return;
}
BB *loopBackedge = builder_->FinishBlock<JumpLoopVertex>({}, loopLabel->loopHeaderRef_);
loopLabel->mergeState_->MergeFrom(*subGraphFrame_, loopBackedge);
ASSERT(loopLabel->mergeState_->PredecessorsSoFar() == loopLabel->mergeState_->PredecessorCount());
loopBackedge->SetPredecessorId(loopLabel->mergeState_->PredecessorCount() - 1);
}
ArkSteedGraphBuilder::ReduceResult ArkSteedGraphBuilder::ArkSteedSubGraphBuilder::Branch(
std::initializer_list<SubGraphVariable *> vars, CallbackRef<BranchResult(BranchBuilder &)> cond,
CallbackRef<ReduceResult()> ifTrue, CallbackRef<ReduceResult()> ifFalse)
{
constexpr uint32_t kBinaryBranchPredecessorCount = 2;
Label elseBranch(this, 1);
BranchBuilder branchBuilder(builder_, this, BranchType::FALSE_BRANCH, &elseBranch);
BranchResult branchResult = cond(branchBuilder);
switch (branchResult) {
case BranchResult::ALWAYS_TRUE:
return ifTrue();
case BranchResult::ALWAYS_FALSE:
return ifFalse();
case BranchResult::ABORT:
return ReduceResult::DoneWithAbort();
case BranchResult::DEFAULT:
break;
}
Label done(this, kBinaryBranchPredecessorCount, vars);
ReduceResult trueResult = ifTrue();
GotoOrTrim(&done);
Bind(&elseBranch);
ReduceResult falseResult = ifFalse();
if (trueResult.IsDoneWithAbort() && falseResult.IsDoneWithAbort()) {
return ReduceResult::DoneWithAbort();
}
GotoOrTrim(&done);
ReduceResult bindResult = TrimPredecessorsAndBind(&done);
if (bindResult.IsDoneWithAbort()) {
return bindResult;
}
return ReduceResult::Done();
}
ArkSteedGraphBuilder::ReduceResult ArkSteedGraphBuilder::Select(CallbackRef<BranchResult(BranchBuilder &)> cond,
CallbackRef<ReduceResult()> ifTrue,
CallbackRef<ReduceResult()> ifFalse)
{
constexpr uint32_t kBinaryBranchPredecessorCount = 2;
ArkSteedSubGraphBuilder subGraph(this, 1);
ArkSteedSubGraphBuilder::SubGraphVariable resultVar(0);
ArkSteedSubGraphBuilder::Label elseBranch(&subGraph, 1);
BranchBuilder branchBuilder(this, &subGraph, BranchType::FALSE_BRANCH, &elseBranch);
BranchResult branchResult = cond(branchBuilder);
switch (branchResult) {
case BranchResult::ALWAYS_TRUE:
return ifTrue();
case BranchResult::ALWAYS_FALSE:
return ifFalse();
case BranchResult::ABORT:
return ReduceResult::DoneWithAbort();
case BranchResult::DEFAULT:
break;
}
ArkSteedSubGraphBuilder::Label done(&subGraph, kBinaryBranchPredecessorCount, {&resultVar});
auto completeArm = [&subGraph, &resultVar, &done](const ReduceResult &result) {
if (result.IsDoneWithValue()) {
subGraph.Set(resultVar, result.Value());
}
subGraph.GotoOrTrim(&done);
return result.IsDoneWithAbort();
};
bool truePathAborted = completeArm(ifTrue());
subGraph.Bind(&elseBranch);
bool falsePathAborted = completeArm(ifFalse());
if (truePathAborted && falsePathAborted) {
return ReduceResult::DoneWithAbort();
}
subGraph.Bind(&done);
return ReduceResult::Done(subGraph.Get(resultVar));
}
uint32_t ArkSteedGraphBuilder::PredecessorCount(uint32_t index) const
{
ASSERT(index < static_cast<uint32_t>(bytecodeContext_.GetPredecessorCount().size()));
ASSERT(index < static_cast<uint32_t>(predecessorCountReductions_.size()));
uint32_t staticPredecessorCount = bytecodeContext_.GetPredecessorCount()[index];
ASSERT(predecessorCountReductions_[index] <= staticPredecessorCount);
return staticPredecessorCount - predecessorCountReductions_[index];
}
void ArkSteedGraphBuilder::ReduceBytecodePredecessorCount(uint32_t index, uint32_t num)
{
if (num == 0) {
return;
}
ASSERT(index < static_cast<uint32_t>(predecessorCountReductions_.size()));
ASSERT(num <= PredecessorCount(index));
predecessorCountReductions_[index] += num;
if (mergeStates_[index] != nullptr) {
mergeStates_[index]->ReducePredecessorCount(num);
}
}
void ArkSteedGraphBuilder::MarkDeadLoopBackedge(uint32_t index)
{
if (mergeStates_[index] == nullptr && PredecessorCount(index) == 0) {
return;
}
ASSERT(PredecessorCount(index) > 0);
if (mergeStates_[index] != nullptr) {
ASSERT(mergeStates_[index]->IsLoopHeader());
ASSERT(mergeStates_[index]->PredecessorCount() == PredecessorCount(index));
ASSERT(mergeStates_[index]->PredecessorsSoFar() + 1 == mergeStates_[index]->PredecessorCount());
mergeStates_[index]->ReducePredecessorCount();
mergeStates_[index]->ClearIsLoop();
mergeStates_[index]->ClearLoopInfo();
}
predecessorCountReductions_[index]++;
}
void ArkSteedGraphBuilder::MarkDeadPredecessorsForSuccessors(uint32_t index, const BytecodeInfo &bytecodeInfo)
{
if (bytecodeInfo.IsCondJump()) {
uint32_t jumpTarget = bytecodeContext_.GetJumpTargetBcIndex(index);
uint32_t fallthrough = index + 1;
ReduceBytecodePredecessorCount(jumpTarget);
if (fallthrough < bytecodeContext_.GetBytecodeCount() && fallthrough != jumpTarget) {
ReduceBytecodePredecessorCount(fallthrough);
}
return;
}
if (bytecodeInfo.IsJump()) {
uint32_t jumpTarget = bytecodeContext_.GetJumpTargetBcIndex(index);
if (bytecodeContext_.GetJumpLoop()[index]) {
MarkDeadLoopBackedge(jumpTarget);
} else {
ReduceBytecodePredecessorCount(jumpTarget);
}
return;
}
if (bytecodeInfo.needFallThrough()) {
uint32_t nextIndex = index + 1;
if (nextIndex < bytecodeContext_.GetBytecodeCount()) {
ReduceBytecodePredecessorCount(nextIndex);
}
}
}
void ArkSteedGraphBuilder::StartNewBlock(BB *predecessor, MergePointFrameState *mergeState, BBRef *refsToBlock)
{
ASSERT(CurrentBlock() == nullptr);
BB *current = BB::New(GetChunk());
if (mergeState == nullptr) {
ASSERT(predecessor != nullptr);
current->SetPredecessorCount(1);
current->AddPredecessor(predecessor);
} else {
uint32_t numPreds = mergeState->PredecessorCount();
current->SetPredecessorCount(numPreds);
current->SetRegisterMergeState(&mergeState->RegisterState());
if (mergeState->IsLoopHeader()) {
current->SetLoopHeader(true);
}
if (mergeState->IsExceptionHandler()) {
current->SetExceptionHandler(true);
}
for (PhiVertex *phi : mergeState->Phis()) {
phi->SetOwner(current);
current->GetPhis().push_back(phi);
RegisterVertexWithLabeller(phi);
}
}
SetCurrentBlock(current);
if (refsToBlock != nullptr) {
refsToBlock->Bind(current);
}
}
void ArkSteedGraphBuilder::StartNewBlockWithMergeState(uint32_t index)
{
#ifndef NDEBUG
LOG_COMPILER(DEBUG) << "Creating new basic block at bytecode #" << index << " (with merge state)";
#endif
ASSERT(mergeStates_[index] != nullptr);
StartNewBlock(nullptr, mergeStates_[index], &jumpTargets_[index]);
BB *current = CurrentBlock();
mergeStates_[index]->FrameState().ForEach([this](ValueVertex *vertex, VirtualRegister reg) {
#ifndef NDEBUG
LOG_COMPILER(DEBUG) << "\tLive-in virtual register " << VRegDisplayString(reg) << " -> Vertex "
<< GetCurrentGraphLabeller()->GetVertexInputLabel(vertex);
#endif
currentFrameState_->Set(reg, vertex);
});
ProcessMergePointPredecessors(mergeStates_[index], &jumpTargets_[index], current);
}
void ArkSteedGraphBuilder::ProcessMergePointPredecessors(MergePointFrameState *mergeState, BBRef *ref, BB *mergeBlock)
{
ASSERT(mergeState != nullptr);
ASSERT(ref != nullptr);
ASSERT(mergeBlock != nullptr);
uint32_t numPreds = mergeState->PredecessorCount();
if (numPreds <= 1) {
return;
}
if (mergeState->IsExceptionHandler()) {
LOG_COMPILER(WARN) << "to do: Exception handlers are not supported now.";
} else if (mergeState->IsLoopHeader()) {
ASSERT(mergeState->PredecessorsSoFar() == numPreds - 1);
for (uint32_t i = 0; i + 1 < numPreds; i++) {
TrySplitCriticalEdge(mergeState, ref, mergeBlock, i);
}
} else {
ASSERT(mergeState->PredecessorsSoFar() == numPreds);
for (uint32_t i = 0; i < numPreds; i++) {
TrySplitCriticalEdge(mergeState, ref, mergeBlock, i);
}
}
}
void ArkSteedGraphBuilder::TrySplitCriticalEdge(MergePointFrameState *mergeState, BBRef *ref, BB *mergeBlock,
uint32_t predIndex)
{
ASSERT(mergeState != nullptr);
ASSERT(ref != nullptr);
ASSERT(mergeBlock != nullptr);
BB *predecessor = mergeState->PredecessorAt(predIndex);
BranchIfTrueVertex *branchIf = predecessor->GetControlVertex()->TryCast<BranchIfTrueVertex>();
if (branchIf == nullptr) {
predecessor->SetPredecessorId(predIndex);
return;
}
RegisterMergeState *state = GetChunk()->New<RegisterMergeState>();
BB *splitBlock = BB::New(GetChunk());
splitBlock->SetPredecessorCount(1);
splitBlock->SetRegisterMergeState(state);
GetGraph()->Add(splitBlock);
JumpVertex *splitJump = Vertex::New<JumpVertex>(GetChunk(), {}, ref->BlockRef());
splitJump->SetOwner(splitBlock);
splitBlock->SetControlVertex(splitJump);
RegisterVertexWithLabeller(splitJump);
splitBlock->AddPredecessor(predecessor);
splitBlock->SetPredecessorId(predIndex);
mergeState->SetPredecessorAt(predIndex, splitBlock);
ASSERT(!!(branchIf->IfTrue() == mergeBlock) + !!(branchIf->IfFalse() == mergeBlock) == 1);
if (branchIf->IfTrue() == mergeBlock) {
#ifndef NDEBUG
LOG_COMPILER(DEBUG) << "Creates edge-split block at predecessor #" << predIndex << " of merge block #"
<< mergeBlock->GetId() << " (splitting true-branch)";
#endif
branchIf->SetIfTrue(splitBlock);
} else if (branchIf->IfFalse() == mergeBlock) {
#ifndef NDEBUG
LOG_COMPILER(DEBUG) << "Creates edge-split block at predecessor #" << predIndex << " of merge block #"
<< mergeBlock->GetId() << " (splitting false-branch)";
#endif
branchIf->SetIfFalse(splitBlock);
}
}
void ArkSteedGraphBuilder::BranchBuilder::StartFallthroughBlock(BB *predecessor)
{
switch (GetMode()) {
case Mode::JUMP_BYTECODE_TARGET: {
auto &data = data_.bytecodeTarget;
builder_->MergeCurrentFrameStateTo(predecessor, data.jumpTargetBcIndex);
builder_->MergeCurrentFrameStateTo(predecessor, data.fallthroughBcIndex);
break;
}
case Mode::JUMP_LABEL_TARGET: {
auto &data = data_.labelTarget;
subBuilder_->MergeIntoLabel(data.jumpLabel, predecessor);
if (data.fallthroughBlock == nullptr) {
data.fallthroughBlock = BB::New(builder_->GetChunk());
data.fallthroughBlock->AddPredecessor(predecessor);
data.fallthroughTarget.Bind(data.fallthroughBlock);
}
builder_->SetCurrentBlock(data.fallthroughBlock);
break;
}
}
}
BBRef *ArkSteedGraphBuilder::BranchBuilder::JumpTarget()
{
switch (GetMode()) {
case Mode::JUMP_BYTECODE_TARGET: {
return &builder_->jumpTargets_[data_.bytecodeTarget.jumpTargetBcIndex];
}
case Mode::JUMP_LABEL_TARGET:
return &data_.labelTarget.jumpLabel->ref_;
}
}
BBRef *ArkSteedGraphBuilder::BranchBuilder::FallThrough()
{
switch (GetMode()) {
case Mode::JUMP_BYTECODE_TARGET: {
return &builder_->jumpTargets_[data_.bytecodeTarget.fallthroughBcIndex];
}
case Mode::JUMP_LABEL_TARGET:
return &data_.labelTarget.fallthroughTarget;
}
}
BBRef *ArkSteedGraphBuilder::BranchBuilder::TrueTarget()
{
return GetCurrentBranchType() == BranchType::TRUE_BRANCH ? JumpTarget() : FallThrough();
}
BBRef *ArkSteedGraphBuilder::BranchBuilder::FalseTarget()
{
return GetCurrentBranchType() == BranchType::FALSE_BRANCH ? JumpTarget() : FallThrough();
}
void ArkSteedGraphBuilder::BuildThrow(kungfu::RuntimeStubCSigns::ID id, ValueVertex *input)
{
bool hasInput = (input != nullptr);
if (!hasInput) {
input = GetInt32Constant(0);
}
FinishBlock<ThrowVertex>({input}, id, hasInput);
}
}