* 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_new.h"
#include "ecmascript/arksteed/arksteed_framestate.h"
#include "ecmascript/lexical_env.h"
#define REGISTER_VERTEX_TO_LABELLER(vertex) \
do { \
ArkSteedGraphLabeller *labeller = GetCurrentGraphLabeller(); \
if (labeller != nullptr) { \
labeller->RegisterVertex(vertex); \
} \
} while (false)
namespace panda::ecmascript::arksteed {
namespace {
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;
}
}
struct GraphBuilderNew::CatchBlockInputData {
struct InputEntry {
ValueVertex *vertex;
uint32_t count;
};
uint32_t totalCount;
ChunkVector<ChunkVector<InputEntry>> inputs;
explicit CatchBlockInputData(const kungfu::BitSet &liveIn, Chunk *chunk) : totalCount(0), inputs(chunk)
{
size_t numLive = liveIn.Count();
inputs.reserve(numLive);
for (size_t i = 0; i < numLive; i++) {
inputs.emplace_back(chunk);
}
}
};
GraphBuilderNew::GraphBuilderNew(Graph *destGraph,
uintptr_t glueAddr,
BytecodePreprocessorNew *preproc,
BytecodeAnalysisNew *analysis)
: graph_(destGraph),
glueAddr_(glueAddr),
preproc_(preproc),
analysis_(analysis),
blocks_(preproc->GetNumLiveBasicBlocks(), preproc->GetChunk()),
frameStates_(preproc->GetNumLiveBasicBlocks(), preproc->GetChunk()),
catchBlockInputs_(preproc->GetChunk())
{}
bool GraphBuilderNew::Run()
{
ASSERT(preproc_->GetNumLiveBasicBlocks() > 0);
DebugLog();
InitializeBasicBlocks();
InitializeGlobalsAndParameters();
BCFrameState frameState(GetNumVRegs(), nullptr, GetChunk());
FinalizeStartBasicBlock(frameState);
frameStates_[0] = CondensedBCFrameState(frameState, analysis_->GetLiveOut(0), GetChunk());
for (uint32_t i = 1, n = preproc_->GetNumLiveBasicBlocks(); i < n; i++) {
frameState.Reset(nullptr);
ProcessBasicBlock(frameState, i);
frameStates_[i] = CondensedBCFrameState(frameState, analysis_->GetLiveOut(i), GetChunk());
}
FinalizeBasicBlockRelations();
return true;
}
void GraphBuilderNew::DebugLog()
{
if (!common::Log::LogIsLoggable(Level::DEBUG, Component::COMPILER)) {
return;
}
JitCompilationEnv *env = preproc_->GetEnv();
MethodLiteral *method = preproc_->GetMethod();
const char *recordName = method->GetRecordNameWithSymbol(env->GetJSPandaFile(), method->GetMethodId());
const char *methodName = method->GetMethodName(env->GetJSPandaFile(), method->GetMethodId());
LOG_COMPILER(DEBUG) << "arksteed::GraphBuilder: Starts compiling " << recordName << " :: " << methodName;
LOG_COMPILER(DEBUG) << "NumLocalVRegs = " << GetNumLocalVRegs()
<< ", NumParamVRegs = " << GetNumParamVRegs();
std::string dumpStr = preproc_->Dump();
std::istringstream preprocStream(dumpStr);
std::string line;
while (std::getline(preprocStream, line)) {
LOG_COMPILER(DEBUG) << line;
}
dumpStr = analysis_->Dump();
std::istringstream analysisStream(dumpStr);
while (std::getline(analysisStream, line)) {
LOG_COMPILER(DEBUG) << line;
}
}
void GraphBuilderNew::InitializeBasicBlocks()
{
uint32_t n = preproc_->GetNumLiveBasicBlocks();
for (uint32_t i = 0; i < n; i++) {
blocks_[i] = BB::New(GetChunk());
const BasicBlockInfo *bcBlock = preproc_->GetBasicBlockByRPO(i);
blocks_[i]->SetLoopHeader(bcBlock->IsLoopHeader());
blocks_[i]->SetExceptionHandler(bcBlock->IsCatchBlockHeader());
uint32_t numPreds = static_cast<uint32_t>(bcBlock->jumpPredecessors.size() +
bcBlock->catchPredecessors.size());
blocks_[i]->SetPredecessorCount(numPreds);
if (numPreds >= 1) {
blocks_[i]->SetRegisterMergeState(GetChunk()->New<RegisterMergeState>());
}
}
}
void GraphBuilderNew::InitializeGlobalsAndParameters()
{
glue_ = graph_->GetIntPtrConstant(glueAddr_);
undefinedValue_ = graph_->GetRootConstant(RootConstantVertex::RootIndex::UNDEFINED);
const int32_t CALL_TARGET_FP_SLOT_INDEX = 3;
for (uint32_t i = 0, n = GetNumParamVRegs(); i < n; i++) {
int32_t slotIndex = static_cast<int32_t>(i + CALL_TARGET_FP_SLOT_INDEX);
auto *v = NewVertexNoInput<InitialValueVertex>(blocks_[0], slotIndex);
graph_->AddParameter(v);
}
}
void GraphBuilderNew::FinalizeStartBasicBlock(BCFrameState &frameState)
{
for (VRegIDType i = 0, n = GetNumParamVRegs(); i < n; i++) {
VRegIDType curIndex = VRegOfParam(GetNumLocalVRegs(), i).GetId();
frameState.Set(curIndex, graph_->GetParameter(i));
}
frameState.SetEnv(NewVertexNoInput<InitialValueVertex>(blocks_[0], -3));
NewControlVertex<JumpVertex>(blocks_[0], {}, blocks_[1]);
}
void GraphBuilderNew::FinalizeBasicBlockRelations()
{
uint32_t n = preproc_->GetNumLiveBasicBlocks();
for (uint32_t i = 0; i < n; i++) {
const BasicBlockInfo *bcBlock = preproc_->GetBasicBlockByRPO(i);
for (const BasicBlockInfo *predBcBlock : bcBlock->jumpPredecessors) {
blocks_[i]->AddPredecessor(blocks_[predBcBlock->rpoIndex]);
}
uint32_t numPreds = bcBlock->jumpPredecessors.size();
if (numPreds <= 1) {
continue;
}
for (uint32_t j = 0; j < numPreds; j++) {
BB *pred = blocks_[bcBlock->jumpPredecessors[j]->rpoIndex];
if (JumpVertex *asJump = pred->GetControlVertex()->TryCast<JumpVertex>()) {
asJump->SetPredecessorId(j);
} else if (JumpLoopVertex *asJumpLoop = pred->GetControlVertex()->TryCast<JumpLoopVertex>()) {
asJumpLoop->SetPredecessorId(j);
} else {
ASSERT(!"Predecessor of a merge point must end with unconditional jump!");
}
}
}
}
void GraphBuilderNew::ProcessBasicBlock(BCFrameState &frameState, uint32_t rpoIndex)
{
const BasicBlockInfo *bcBlock = preproc_->GetBasicBlockByRPO(rpoIndex);
if (bcBlock->IsCatchBlockHeader()) {
ProcessCatchBlockHead(frameState, rpoIndex);
return;
}
bcBlock->IsLoopHeader()
? InitFrameStateForLoopHeader(frameState, rpoIndex)
: InitFrameState(frameState, rpoIndex);
for (uint32_t i = bcBlock->startBcIndex; i <= bcBlock->endBcIndex; i++) {
const BytecodeInfo *bcInfo = preproc_->GetBytecode(i);
VisitBytecode(rpoIndex, &frameState, bcInfo);
}
if (bcBlock->IsSynthetic()) {
BB *target = blocks_[bcBlock->jumpBlock->rpoIndex];
if (bcBlock->IsEndOfLoop()) {
NewControlVertex<JumpLoopVertex>(blocks_[rpoIndex], {}, target);
} else {
NewControlVertex<JumpVertex>(blocks_[rpoIndex], {}, target);
}
} else if (bcBlock->fallthroughBlock != nullptr && bcBlock->jumpBlock == nullptr) {
ASSERT(!bcBlock->IsEndOfLoop());
NewControlVertex<JumpVertex>(blocks_[rpoIndex], {}, blocks_[bcBlock->fallthroughBlock->rpoIndex]);
}
if (bcBlock->IsEndOfLoop()) {
WriteBackFrameStateToLoopHeader(frameState, rpoIndex);
}
}
void GraphBuilderNew::ProcessCatchBlockHead(BCFrameState &frameState, uint32_t rpoIndex)
{
InitFrameStateForCatchBlockHeader(frameState, rpoIndex);
const BasicBlockInfo *bcBlock = preproc_->GetBasicBlockByRPO(rpoIndex);
ASSERT(bcBlock->jumpBlock != nullptr);
NewControlVertex<JumpVertex>(blocks_[rpoIndex], {}, blocks_[bcBlock->jumpBlock->rpoIndex]);
}
void GraphBuilderNew::InitFrameState(BCFrameState &frameState, uint32_t rpoIndex)
{
const BasicBlockInfo *bcBlock = preproc_->GetBasicBlockByRPO(rpoIndex);
uint32_t numPreds = static_cast<uint32_t>(bcBlock->jumpPredecessors.size());
for (uint32_t j = 0; j < numPreds; j++) {
MergeFrameState(frameState, rpoIndex, j);
}
}
void GraphBuilderNew::InitFrameStateForLoopHeader(BCFrameState &frameState, uint32_t rpoIndex)
{
const BasicBlockInfo *blockInfo = preproc_->GetBasicBlockByRPO(rpoIndex);
ASSERT(blockInfo->jumpPredecessors.size() == 2);
kungfu::BitSet phiCandidates = analysis_->GetLiveIn(rpoIndex);
for (uint32_t vregIndex = 0, n = GetNumVRegs(); vregIndex < n; vregIndex++) {
if (phiCandidates.TestBit(vregIndex)) {
frameState.Set(vregIndex, NewPhiVertex(blocks_[rpoIndex], 2, vregIndex));
}
}
MergeFrameState(frameState, rpoIndex, 0);
}
void GraphBuilderNew::InitFrameStateForCatchBlockHeader(BCFrameState &frameState, uint32_t rpoIndex)
{
const BasicBlockInfo *bcBlock = preproc_->GetBasicBlockByRPO(rpoIndex);
frameState.SetAcc(NewVertex<LoadExceptionVertex>(blocks_[rpoIndex], {glue_}));
CatchBlockInputData *data = catchBlockInputs_[rpoIndex];
if (data == nullptr) {
LOG_COMPILER(WARN) << "Catch block " << rpoIndex << " has no throwable predecessors";
return;
}
ASSERT(data->totalCount >= 1);
const kungfu::BitSet &liveIn = analysis_->GetLiveIn(rpoIndex);
VRegIDType liveIndex = 0;
for (VRegIDType vregIndex = 0, n = GetNumVRegs(); vregIndex < n - 1; vregIndex++) {
if (!liveIn.TestBit(vregIndex)) {
continue;
}
const auto &curInputList = data->inputs[liveIndex++];
ASSERT(!curInputList.empty());
if (curInputList.size() == 1) {
frameState.Set(vregIndex, curInputList[0].vertex);
continue;
}
PhiVertex *phi = NewPhiVertex(blocks_[rpoIndex], data->totalCount, vregIndex);
uint32_t inputIndex = 0;
for (const auto &[input, count] : curInputList) {
for (uint32_t j = 0; j < count; j++) {
phi->SetInput(inputIndex++, input);
}
}
frameState.Set(vregIndex, phi);
}
}
void GraphBuilderNew::WriteBackFrameStateToLoopHeader(BCFrameState ¤t, uint32_t rpoIndex)
{
const BasicBlockInfo *blockInfo = preproc_->GetBasicBlockByRPO(rpoIndex);
ASSERT(blockInfo->jumpBlock != nullptr);
ASSERT(blockInfo->jumpBlock->jumpPredecessors.size() == 2);
ASSERT(blockInfo->jumpBlock->loopBackBlock == blockInfo);
uint32_t headerIndex = blockInfo->jumpBlock->rpoIndex;
for (PhiVertex *phi : blocks_[headerIndex]->GetPhis()) {
ASSERT(phi->GetInputCount() == 2);
ValueVertex *fromCurrent = current.Get(phi->GetOwner().GetId());
phi->SetInput(1, fromCurrent != nullptr ? fromCurrent : undefinedValue_);
}
}
void GraphBuilderNew::MergeFrameState(BCFrameState &dest, uint32_t rpoIndex, uint32_t predecessorIndex)
{
const BasicBlockInfo *bcBlock = preproc_->GetBasicBlockByRPO(rpoIndex);
uint32_t numPreds = bcBlock->jumpPredecessors.size();
uint32_t predRpoIndex = bcBlock->jumpPredecessors[predecessorIndex]->rpoIndex;
const kungfu::BitSet &liveIn = analysis_->GetLiveIn(rpoIndex);
frameStates_[predRpoIndex].ForEach([&, this](ValueVertex *fromPred, VRegIDType vregIndex) {
if (!liveIn.TestBit(vregIndex)) {
return;
}
ValueVertex *cur = dest.Get(vregIndex);
if (cur == fromPred) {
return;
}
if (cur == nullptr) {
dest.Set(vregIndex, fromPred);
return;
}
PhiVertex *phi = cur->TryCast<PhiVertex>();
if (phi != nullptr && cur->GetOwner() == blocks_[rpoIndex]) {
phi->SetInput(predecessorIndex, fromPred);
return;
}
phi = NewPhiVertex(blocks_[rpoIndex], numPreds, vregIndex);
for (uint32_t k = 0; k < predecessorIndex; k++) {
phi->SetInput(k, cur);
}
phi->SetInput(predecessorIndex, fromPred);
dest.Set(vregIndex, phi);
});
}
uint32_t GraphBuilderNew::AppendCatchBlockInputs(const BCFrameState ¤t, uint32_t catchBlockIndex)
{
const kungfu::BitSet &liveIn = analysis_->GetLiveIn(catchBlockIndex);
CatchBlockInputData *data = catchBlockInputs_[catchBlockIndex];
if (UNLIKELY(data == nullptr)) {
data = GetChunk()->New<CatchBlockInputData>(liveIn, GetChunk());
catchBlockInputs_[catchBlockIndex] = data;
}
VRegIDType liveIndex = 0;
for (VRegIDType i = 0, n = GetNumVRegs(); i < n - 1; i++) {
if (!liveIn.TestBit(i)) {
continue;
}
ValueVertex *value = current.Get(i);
if (value == nullptr) {
value = undefinedValue_;
}
auto &curInputList = data->inputs[liveIndex++];
if (curInputList.empty() || curInputList.back().vertex != value) {
curInputList.push_back({.vertex = value, .count = 1});
} else {
curInputList.back().count += 1;
}
}
uint32_t curInputIndex = data->totalCount;
data->totalCount += 1;
return curInputIndex;
}
template <class VertexT, class... Args>
VertexT *GraphBuilderNew::NewVertex(BB *owner, std::initializer_list<ValueVertex *> inputs, Args &&...args)
{
VertexT *vertex = Vertex::New<VertexT>(GetChunk(), inputs, std::forward<Args>(args)...);
return FinalizeNonControlVertex(owner, vertex);
}
template <class VertexT, class... Args>
VertexT *GraphBuilderNew::NewVertex(BB *owner, const ChunkVector<ValueVertex *> &inputs, Args &&...args)
{
VertexT *vertex = Vertex::New<VertexT>(GetChunk(), inputs, std::forward<Args>(args)...);
return FinalizeNonControlVertex(owner, vertex);
}
template <class VertexT, class... Args>
VertexT *GraphBuilderNew::NewVertexNoInput(BB *owner, Args &&...args)
{
VertexT *vertex = Vertex::New<VertexT>(GetChunk(), 0, std::forward<Args>(args)...);
return FinalizeNonControlVertex(owner, vertex);
}
PhiVertex *GraphBuilderNew::NewPhiVertex(BB *owner, uint32_t numPredecessors, VRegIDType vreg)
{
PhiVertex *phi = PhiVertex::New(GetChunk(), numPredecessors, nullptr, VirtualRegister(vreg));
phi->SetOwner(owner);
owner->AddPhiVertex(phi);
REGISTER_VERTEX_TO_LABELLER(phi);
return phi;
}
template <class VertexT, class... Args>
VertexT *GraphBuilderNew::NewControlVertex(BB *owner, std::initializer_list<ValueVertex *> inputs, Args &&...args)
{
VertexT *vertex = Vertex::New<VertexT>(GetChunk(), inputs, std::forward<Args>(args)...);
return FinalizeControlVertex(owner, vertex);
}
template <class VertexT>
VertexT *GraphBuilderNew::FinalizeNonControlVertex(BB *owner, VertexT *vertex)
{
constexpr VertexProperties props = VertexT::PROPERTIES;
static_assert(props.IsDeoptCheckpoint() + props.CanEagerDeopt() + props.CanLazyDeopt() <= 1);
vertex->SetOwner(owner);
owner->AddVertex(vertex);
REGISTER_VERTEX_TO_LABELLER(vertex);
return vertex;
}
template <class VertexT>
VertexT *GraphBuilderNew::FinalizeControlVertex(BB *owner, VertexT *vertex)
{
constexpr VertexProperties props = VertexT::PROPERTIES;
static_assert(!props.CanLazyDeopt() && !props.CanWrite());
vertex->SetOwner(owner);
owner->SetControlVertex(vertex);
graph_->Add(owner);
REGISTER_VERTEX_TO_LABELLER(vertex);
return vertex;
}
ValueVertex *GraphBuilderNew::GetGlue() const
{
return glue_;
}
ValueVertex *GraphBuilderNew::GetUndefinedValue() const
{
return undefinedValue_;
}
struct GraphBuilderNew::BytecodeVisitor {
void Visit()
{
switch (bcInfo->details.GetOpcode()) {
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::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::GETUNMAPPEDARGS:
LowerGetUnmappedArgs();
break;
case kungfu::EcmaOpcode::GETPROPITERATOR:
LowerGetPropIterator();
break;
case kungfu::EcmaOpcode::CLOSEITERATOR_IMM8_V8:
case kungfu::EcmaOpcode::CLOSEITERATOR_IMM16_V8:
LowerCloseIterator();
break;
case kungfu::EcmaOpcode::LDNAN:
LowerLdTaggedConstant(base::NumberHelper::GetNaN());
break;
case kungfu::EcmaOpcode::LDINFINITY:
LowerLdTaggedConstant(base::NumberHelper::GetPositiveInfinity());
break;
case kungfu::EcmaOpcode::LDUNDEFINED:
LowerLdRootConstant(RootConstantVertex::RootIndex::UNDEFINED);
break;
case kungfu::EcmaOpcode::LDNULL:
LowerLdRootConstant(RootConstantVertex::RootIndex::NULL_VALUE);
break;
case kungfu::EcmaOpcode::LDTRUE:
LowerLdRootConstant(RootConstantVertex::RootIndex::TRUE_VALUE);
break;
case kungfu::EcmaOpcode::LDFALSE:
LowerLdRootConstant(RootConstantVertex::RootIndex::FALSE_VALUE);
break;
case kungfu::EcmaOpcode::LDHOLE:
LowerLdTaggedConstant(JSTaggedValue::VALUE_HOLE);
break;
case kungfu::EcmaOpcode::LDAI_IMM32:
LowerLdaiImm32();
break;
case kungfu::EcmaOpcode::FLDAI_IMM64:
LowerFldaiImm64();
break;
case kungfu::EcmaOpcode::LDFUNCTION:
frameState->SetAcc(LoadParam(CALL_TARGET_PARAM_INDEX));
break;
case kungfu::EcmaOpcode::LDNEWTARGET:
frameState->SetAcc(LoadParam(NEW_TARGET_PARAM_INDEX));
break;
case kungfu::EcmaOpcode::LDTHIS:
frameState->SetAcc(LoadParam(THIS_OBJECT_PARAM_INDEX));
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();
break;
case kungfu::EcmaOpcode::INC_IMM8:
LowerInc();
break;
case kungfu::EcmaOpcode::DEC_IMM8:
LowerDec();
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::EXP_IMM8_V8:
LowerExp();
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::STRICTNOTEQ_IMM8_V8:
LowerStrictNotEq();
break;
case kungfu::EcmaOpcode::STRICTEQ_IMM8_V8:
LowerStrictEq();
break;
case kungfu::EcmaOpcode::TONUMBER_IMM8:
LowerToNumber();
break;
case kungfu::EcmaOpcode::TONUMERIC_IMM8:
LowerToNumeric();
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::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_DELETESUPERPROPERTY_PREF_NONE:
LowerThrowDeleteSuperProperty();
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::LDSYMBOL:
LowerLdSymbol();
break;
case kungfu::EcmaOpcode::LDGLOBAL:
LowerLdGlobal();
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::ISIN_IMM8_V8:
LowerIsIn();
break;
case kungfu::EcmaOpcode::INSTANCEOF_IMM8_V8:
LowerInstanceOf();
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::CREATEOBJECTWITHEXCLUDEDKEYS_IMM8_V8_V8:
case kungfu::EcmaOpcode::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8:
LowerCreateObjectWithExcludedKeys();
break;
case kungfu::EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
case kungfu::EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
LowerCreateArrayWithBuffer();
break;
case kungfu::EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8:
case kungfu::EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8:
LowerCreateRegExpWithLiteral();
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::DYNAMICIMPORT:
LowerDynamicImport();
break;
case kungfu::EcmaOpcode::LDEXTERNALMODULEVAR_IMM8:
case kungfu::EcmaOpcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16:
case kungfu::EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8:
case kungfu::EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_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:
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:
LowerJumpIfZero();
break;
case kungfu::EcmaOpcode::JNEZ_IMM8:
case kungfu::EcmaOpcode::JNEZ_IMM16:
case kungfu::EcmaOpcode::JNEZ_IMM32:
LowerJumpIfNonZero();
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::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::LDOBJBYINDEX_IMM8_IMM16:
case kungfu::EcmaOpcode::LDOBJBYINDEX_IMM16_IMM16:
case kungfu::EcmaOpcode::WIDE_LDOBJBYINDEX_PREF_IMM32:
LowerLdObjByIndex();
break;
case kungfu::EcmaOpcode::STOBJBYINDEX_IMM8_V8_IMM16:
case kungfu::EcmaOpcode::STOBJBYINDEX_IMM16_V8_IMM16:
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::STOBJBYVALUE_IMM8_V8_V8:
case kungfu::EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8:
LowerStoreObjByValue();
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::LDTHISBYVALUE_IMM8:
case kungfu::EcmaOpcode::LDTHISBYVALUE_IMM16:
LowerLdThisByValue();
break;
case kungfu::EcmaOpcode::STTHISBYVALUE_IMM8_V8:
case kungfu::EcmaOpcode::STTHISBYVALUE_IMM16_V8:
LowerStThisByValue();
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::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::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::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::LDPRIVATEPROPERTY_IMM8_IMM16_IMM16:
LowerLdPrivateProperty();
break;
case kungfu::EcmaOpcode::STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8:
LowerStPrivateProperty();
break;
case kungfu::EcmaOpcode::LDGLOBALVAR_IMM16_ID16:
LowerLdGlobalVar();
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::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::STARRAYSPREAD_V8_V8:
LowerStoreArraySpread();
break;
case kungfu::EcmaOpcode::DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8:
LowerDefineGetterSetterByValue();
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::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::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::RETURNUNDEFINED:
self->NewControlVertex<ReturnVertex>(CurrentBlock(), {self->GetUndefinedValue()});
break;
case kungfu::EcmaOpcode::RETURN:
self->NewControlVertex<ReturnVertex>(CurrentBlock(), {frameState->GetAcc()});
break;
default:
UNREACHABLE();
}
}
void LowerCallArg0()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *func = frameState->GetAcc();
ValueVertex *result = CommonStubCall(
{glue, func}, CommonStubCSigns::CallArg0Stub);
frameState->SetAcc(result);
}
void LowerCallArg1()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *a0Value = LoadRegister(0);
ValueVertex *func = frameState->GetAcc();
ValueVertex *result = CommonStubCall(
{glue, func, a0Value}, CommonStubCSigns::CallArg1Stub);
frameState->SetAcc(result);
}
void LowerCallArgs2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *a0Value = LoadRegister(0);
ValueVertex *a1Value = LoadRegister(1);
ValueVertex *func = frameState->GetAcc();
ValueVertex *result = CommonStubCall(
{glue, func, a0Value, a1Value}, CommonStubCSigns::CallArg2Stub);
frameState->SetAcc(result);
}
void LowerCallArgs3()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *a0Value = LoadRegister(0);
ValueVertex *a1Value = LoadRegister(1);
ValueVertex *a2Value = LoadRegister(2);
ValueVertex *func = frameState->GetAcc();
ValueVertex *result = CommonStubCall(
{glue, func, a0Value, a1Value, a2Value}, CommonStubCSigns::CallArg3Stub);
frameState->SetAcc(result);
}
void LowerCallThis0()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *func = frameState->GetAcc();
ValueVertex *result = CommonStubCall(
{glue, func, thisObj}, CommonStubCSigns::CallThis0Stub);
frameState->SetAcc(result);
}
void LowerCallThis1()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *a0Value = LoadRegister(1);
ValueVertex *func = frameState->GetAcc();
ValueVertex *result = CommonStubCall(
{glue, func, thisObj, a0Value}, CommonStubCSigns::CallThis1Stub);
frameState->SetAcc(result);
}
void LowerCallThis2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *a0Value = LoadRegister(1);
ValueVertex *a1Value = LoadRegister(2);
ValueVertex *func = frameState->GetAcc();
ValueVertex *result = CommonStubCall(
{glue, func, thisObj, a0Value, a1Value}, CommonStubCSigns::CallThis2Stub);
frameState->SetAcc(result);
}
void LowerCallThis3()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *a0Value = LoadRegister(1);
ValueVertex *a1Value = LoadRegister(2);
ValueVertex *a2Value = LoadRegister(3);
ValueVertex *func = frameState->GetAcc();
ValueVertex *result = CommonStubCall(
{glue, func, thisObj, a0Value, a1Value, a2Value}, CommonStubCSigns::CallThis3Stub);
frameState->SetAcc(result);
}
void LowerCallRange()
{
uint32_t inputSize = bcInfo->details.inputs.size();
ValueVertex *func = frameState->GetAcc();
ValueVertex *taggedInputSize = TaggedConstantFromInt32(static_cast<int>(inputSize));
ValueVertex *taggedArray = TaggedArrayFromValueIn(taggedInputSize, inputSize);
ValueVertex *result = RuntimeCall({func, taggedArray, taggedInputSize}, RTSTUB_ID(CallRange));
frameState->SetAcc(result);
}
void LowerCallThisRange()
{
uint32_t argc = bcInfo->details.inputs.size() - 1;
ValueVertex *func = frameState->GetAcc();
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *taggedArgc = TaggedConstantFromInt32(static_cast<int>(argc));
ValueVertex *taggedArray = TaggedArrayFromValueIn(taggedArgc, argc, 1);
ValueVertex *result = RuntimeCall({thisObj, func, taggedArray, taggedArgc}, RTSTUB_ID(CallThisRange));
frameState->SetAcc(result);
}
void LowerCallSpread()
{
ValueVertex *func = frameState->GetAcc();
ValueVertex *thisArg = LoadRegister(0);
ValueVertex *argsArray = LoadRegister(1);
frameState->SetAcc(RuntimeCall({func, thisArg, argsArray}, RTSTUB_ID(CallSpread)));
}
void LowerSuperCallThisRange()
{
uint32_t inputSize = bcInfo->details.inputs.size();
ValueVertex *thisFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *newTarget = LoadParam(NEW_TARGET_PARAM_INDEX);
ValueVertex *taggedInputSize = TaggedConstantFromInt32(static_cast<int>(inputSize));
ValueVertex *taggedArray = TaggedArrayFromValueIn(taggedInputSize, inputSize);
frameState->SetAcc(RuntimeCall({thisFunc, newTarget, taggedArray, taggedInputSize}, RTSTUB_ID(OptSuperCall)));
}
void LowerSuperCallArrowRange()
{
uint32_t argc = bcInfo->details.inputs.size() - 1;
ValueVertex *func = LoadRegister(argc);
ValueVertex *newTarget = LoadParam(NEW_TARGET_PARAM_INDEX);
ValueVertex *taggedArgc = TaggedConstantFromInt32(static_cast<int>(argc));
ValueVertex *taggedArray = TaggedArrayFromValueIn(taggedArgc, argc);
frameState->SetAcc(RuntimeCall({func, newTarget, taggedArray, taggedArgc}, RTSTUB_ID(OptSuperCall)));
}
void LowerSuperCallSpread()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *globalEnv = GlobalEnv();
ValueVertex *array = LoadRegister(0);
ValueVertex *func = frameState->GetAcc();
ValueVertex *newTarget = LoadParam(NEW_TARGET_PARAM_INDEX);
ValueVertex *argsArray = CommonStubCall({glue, array, globalEnv}, CommonStubCSigns::GetCallSpreadArgs);
frameState->SetAcc(RuntimeCall({func, newTarget, argsArray}, RTSTUB_ID(OptSuperCallSpread)));
}
void LowerSuperCallForwardAllArgs()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *func = LoadRegister(0);
ValueVertex *superFunc = CommonStubCall({glue, func}, CommonStubCSigns::GetPrototype);
ValueVertex *newTarget = LoadParam(NEW_TARGET_PARAM_INDEX);
ValueVertex *taggedActualArgc = TaggedActualArgc();
frameState->SetAcc(RuntimeCall({
superFunc, newTarget, taggedActualArgc}, RTSTUB_ID(OptSuperCallForwardAllArgs)));
}
void LowerGetUnmappedArgs()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *argv = self->graph_->GetIntPtrConstant(0);
ValueVertex *numArgs = ActualArgc();
ValueVertex *argvTaggedArray = self->GetUndefinedValue();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall(
{glue, argv, numArgs, argvTaggedArray, globalEnv}, CommonStubCSigns::GetUnmappedArgs));
}
void LowerGetPropIterator()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *object = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, object, globalEnv}, CommonStubCSigns::Getpropiterator));
}
void LowerCloseIterator()
{
ValueVertex *iterator = LoadRegister(0);
frameState->SetAcc(RuntimeCall({iterator}, RTSTUB_ID(CloseIterator)));
}
void LowerLdTaggedConstant(JSTaggedType taggedValue)
{
frameState->SetAcc(self->graph_->GetTaggedConstant(taggedValue));
}
void LowerLdRootConstant(RootConstantVertex::RootIndex index)
{
frameState->SetAcc(self->graph_->GetRootConstant(index));
}
void LowerLdaiImm32()
{
frameState->SetAcc(TaggedConstantFromInt32(static_cast<int>(GetImmediate(0))));
}
void LowerFldaiImm64()
{
JSTaggedType taggedValue = JSTaggedValue(base::bit_cast<double>(GetImmediate(0))).GetRawData();
frameState->SetAcc(self->graph_->GetTaggedConstant(taggedValue));
}
void LowerMoveValues()
{
const auto &info = bcInfo->details;
ValueVertex *vertex = nullptr;
if (info.AccIn()) {
vertex = frameState->GetAcc();
} else {
ASSERT(!info.inputs.empty());
vertex = LoadRegister(0);
}
if (info.AccOut()) {
frameState->SetAcc(vertex);
} else {
ASSERT(!info.vregOut.empty());
frameState->Set(info.vregOut[0], vertex);
}
}
void LowerInc()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = frameState->GetAcc();
frameState->SetAcc(CommonStubCall({glue, x}, CommonStubCSigns::Inc));
}
void LowerDec()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = frameState->GetAcc();
frameState->SetAcc(CommonStubCall({glue, x}, CommonStubCSigns::Dec));
}
void LowerAdd2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Add));
}
void LowerSub2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Sub));
}
void LowerMul2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Mul));
}
void LowerDiv2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Div));
}
void LowerMod2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Mod));
}
void LowerExp()
{
ValueVertex *left = LoadRegister(0);
ValueVertex *right = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({left, right}, RTSTUB_ID(Exp)));
}
void LowerEq()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Equal));
}
void LowerNotEq()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::NotEqual));
}
void LowerLess()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Less));
}
void LowerLessEq()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::LessEq));
}
void LowerGreater()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Greater));
}
void LowerGreaterEq()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::GreaterEq));
}
void LowerStrictEq()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::StrictEqual));
}
void LowerStrictNotEq()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::StrictNotEqual));
}
void LowerToNumber()
{
ValueVertex *value = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({value}, RTSTUB_ID(ToNumber)));
}
void LowerToNumeric()
{
ValueVertex *value = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({value}, RTSTUB_ID(ToNumeric)));
}
void LowerNeg()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = frameState->GetAcc();
frameState->SetAcc(CommonStubCall({glue, x}, CommonStubCSigns::Neg));
}
void LowerNot()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = frameState->GetAcc();
frameState->SetAcc(CommonStubCall({glue, x}, CommonStubCSigns::Not));
}
void LowerShl2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Shl));
}
void LowerShr2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Shr));
}
void LowerAshr2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Ashr));
}
void LowerAnd2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::And));
}
void LowerOr2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Or));
}
void LowerXor2()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *x = LoadRegister(0);
ValueVertex *y = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, x, y, globalEnv}, CommonStubCSigns::Xor));
}
void LowerCreateIterResultObj()
{
ValueVertex *value = LoadRegister(0);
ValueVertex *done = LoadRegister(1);
frameState->SetAcc(RuntimeCall({value, done}, RTSTUB_ID(CreateIterResultObj)));
}
void LowerTryLdGlobalByName()
{
ValueVertex *id = self->graph_->GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCallWithIC({id, globalEnv}, CommonStubCSigns::TryLdGlobalByName));
}
void LowerStGlobalVar()
{
ValueVertex *id = self->graph_->GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *value = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCallWithIC({id, value, globalEnv}, CommonStubCSigns::StGlobalVar);
}
void LowerGetIterator()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *obj = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, obj, globalEnv}, CommonStubCSigns::GetIterator));
}
void LowerNewObjApply()
{
ValueVertex *target = LoadRegister(0);
ValueVertex *args = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({target, args}, RTSTUB_ID(NewObjApply)));
}
void LowerTypeOf()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *obj = frameState->GetAcc();
frameState->SetAcc(CommonStubCall({glue, obj}, CommonStubCSigns::TypeOf));
}
void LowerThrow()
{
constexpr bool HAS_INPUT = true;
ValueVertex *exception = frameState->GetAcc();
auto *vertex = self->NewControlVertex<ThrowVertex>(CurrentBlock(), {exception}, RTSTUB_ID(Throw), HAS_INPUT);
MergeCurrentFrameStateToCatchBlock(vertex);
}
void LowerThrowConstAssignment()
{
constexpr bool HAS_INPUT = true;
ValueVertex *value = LoadRegister(0);
auto *vertex = self->NewControlVertex<ThrowVertex>(
CurrentBlock(), {value}, RTSTUB_ID(ThrowConstAssignment), HAS_INPUT);
MergeCurrentFrameStateToCatchBlock(vertex);
}
void LowerThrowNotExists()
{
constexpr bool HAS_INPUT = false;
auto *vertex = self->NewControlVertex<ThrowVertex>(
CurrentBlock(), {self->undefinedValue_}, RTSTUB_ID(ThrowThrowNotExists), HAS_INPUT);
MergeCurrentFrameStateToCatchBlock(vertex);
}
void LowerThrowPatternNonCoercible()
{
constexpr bool HAS_INPUT = false;
auto *vertex = self->NewControlVertex<ThrowVertex>(
CurrentBlock(), {self->undefinedValue_}, RTSTUB_ID(ThrowPatternNonCoercible), HAS_INPUT);
MergeCurrentFrameStateToCatchBlock(vertex);
}
void LowerThrowDeleteSuperProperty()
{
constexpr bool HAS_INPUT = false;
auto *vertex = self->NewControlVertex<ThrowVertex>(
CurrentBlock(), {self->undefinedValue_}, RTSTUB_ID(ThrowDeleteSuperProperty), HAS_INPUT);
MergeCurrentFrameStateToCatchBlock(vertex);
}
void LowerThrowIfNotObject()
{
LOG_COMPILER(WARN) << "Unimplemented: LowerThrowIfNotObject";
}
void LowerThrowUndefinedIfHole()
{
LOG_COMPILER(WARN) << "Unimplemented: LowerThrowUndefinedIfHole";
}
void LowerThrowUndefinedIfHoleWithName()
{
LOG_COMPILER(WARN) << "Unimplemented: LowerThrowUndefinedIfHoleWithName";
}
void LowerThrowIfSuperNotCorrectCall()
{
ValueVertex *index = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *thisValue = frameState->GetAcc();
auto *vertex = self->NewVertex<ThrowIfSuperNotCorrectCallVertex>(
CurrentBlock(), {index, thisValue}, RTSTUB_ID(ThrowIfSuperNotCorrectCall));
MergeCurrentFrameStateToCatchBlock(vertex);
}
void LowerLdSymbol()
{
constexpr int32_t offset = static_cast<int32_t>(
GlobalEnv::HEADER_SIZE + GlobalEnv::SYMBOL_FUNCTION_INDEX * JSTaggedValue::TaggedTypeSize());
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(self->NewVertex<LoadTaggedFieldVertex>(CurrentBlock(), {globalEnv}, offset));
}
void LowerLdGlobal()
{
constexpr int32_t offset = static_cast<int32_t>(
GlobalEnv::HEADER_SIZE + GlobalEnv::JS_GLOBAL_OBJECT_INDEX * JSTaggedValue::TaggedTypeSize());
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(self->NewVertex<LoadTaggedFieldVertex>(CurrentBlock(), {globalEnv}, offset));
}
void LowerDelObjProp()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *object = LoadRegister(0);
ValueVertex *prop = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall(
{glue, object, prop, globalEnv}, CommonStubCSigns::DeleteObjectProperty));
}
void LowerDefineMethod()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *taggedMethodId = TaggedConstantFromInt32(static_cast<int>(GetConstDataId(0)));
ValueVertex *length = TaggedConstantFromInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *env = LoadRegister(2);
ValueVertex *homeObject = frameState->GetAcc();
ValueVertex *module = ModuleFromFunction();
ValueVertex *method = MethodFromConstPool(taggedMethodId);
#if ECMASCRIPT_ENABLE_IC
ValueVertex *slotId = TaggedConstantFromInt32(static_cast<int>(GetICSlotId(3)));
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
frameState->SetAcc(RuntimeCall(
{method, homeObject, length, env, module, slotId, jsFunc}, RTSTUB_ID(DefineMethod)));
#else
frameState->SetAcc(RuntimeCall(
{method, homeObject, length, env, module}, RTSTUB_ID(DefineMethod)));
#endif
}
void LowerIsIn()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *prop = LoadRegister(0);
ValueVertex *obj = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, prop, obj, globalEnv}, CommonStubCSigns::IsIn));
}
void LowerInstanceOf()
{
ValueVertex *object = LoadRegister(1);
ValueVertex *target = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCallWithIC({object, target, globalEnv}, CommonStubCSigns::Instanceof));
}
void LowerCreateEmptyObject()
{
frameState->SetAcc(RuntimeCall({}, RTSTUB_ID(CreateEmptyObject)));
}
void LowerCreateEmptyArray()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, globalEnv}, CommonStubCSigns::CreateEmptyArray));
}
void LowerCreateObjectWithBuffer()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *index = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *obj = ObjectFromConstPool(index);
ValueVertex *lexEnv = LoadRegister(1);
frameState->SetAcc(CommonStubCall({glue, obj, lexEnv}, CommonStubCSigns::CreateObjectHavingMethod));
}
void LowerCreateObjectWithExcludedKeys()
{
uint32_t inputSize = bcInfo->details.inputs.size();
ChunkVector<ValueVertex *> args(self->GetChunk());
for (uint32_t idx = 0; idx < inputSize; idx++) {
args.push_back(LoadRegister(idx));
}
frameState->SetAcc(RuntimeCall(args, RTSTUB_ID(OptCreateObjectWithExcludedKeys)));
}
void LowerCreateArrayWithBuffer()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *index = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *slotId = self->graph_->GetInt32Constant(static_cast<int>(GetICSlotId(1)));
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall(
{glue, index, jsFunc, slotId, globalEnv}, CommonStubCSigns::CreateArrayWithBuffer));
}
void LowerCreateRegExpWithLiteral()
{
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *pattern = StringFromConstPool(stringId);
ValueVertex *flags = TaggedConstantFromInt32(static_cast<int>(GetImmediate(1)));
frameState->SetAcc(RuntimeCall({pattern, flags}, RTSTUB_ID(CreateRegExpWithLiteral)));
}
void LowerStModuleVar()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *index = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *value = frameState->GetAcc();
RuntimeCall({index, value, jsFunc}, RTSTUB_ID(StModuleVarByIndexOnJSFunc));
}
void LowerGetTemplateObject()
{
ValueVertex *value = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({value}, RTSTUB_ID(GetTemplateObject)));
}
void LowerSetObjectWithProto()
{
ValueVertex *proto = LoadRegister(0);
ValueVertex *obj = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({proto, obj}, RTSTUB_ID(SetObjectWithProto)));
}
void LowerLoadBigInt()
{
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *numberBigInt = StringFromConstPool(stringId);
frameState->SetAcc(RuntimeCall({numberBigInt}, RTSTUB_ID(LdBigInt)));
}
void LowerDynamicImport()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *specifier = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({specifier, jsFunc}, RTSTUB_ID(DynamicImport)));
}
void LowerLdExternalModuleVar()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *index = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
frameState->SetAcc(RuntimeCall({index, jsFunc}, RTSTUB_ID(LdExternalModuleVarByIndexOnJSFunc)));
}
void LowerGetModuleNamespace()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *index = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
frameState->SetAcc(RuntimeCall({index, jsFunc}, RTSTUB_ID(GetModuleNamespaceByIndexOnJSFunc)));
}
void LowerNewObjRange()
{
uint32_t inputSize = bcInfo->details.inputs.size();
ChunkVector<ValueVertex *> args(self->GetChunk());
for (uint32_t idx = 0; idx < inputSize; idx++) {
args.push_back(LoadRegister(idx));
}
frameState->SetAcc(RuntimeCall(args, RTSTUB_ID(OptNewObjRange)));
}
void LowerJumpIfZero()
{
const BasicBlockInfo *blockInfo = self->preproc_->GetBasicBlockByRPO(rpoIndex);
ASSERT(blockInfo->jumpBlock != nullptr);
ASSERT(blockInfo->fallthroughBlock != nullptr);
uint32_t jumpIndex = blockInfo->jumpBlock->rpoIndex;
uint32_t fallthroughIndex = blockInfo->fallthroughBlock->rpoIndex;
ValueVertex *acc = frameState->GetAcc();
self->NewControlVertex<BranchIfTrueVertex>(
self->blocks_[rpoIndex],
{acc},
self->blocks_[fallthroughIndex],
self->blocks_[jumpIndex]);
}
void LowerJumpIfNonZero()
{
const BasicBlockInfo *blockInfo = self->preproc_->GetBasicBlockByRPO(rpoIndex);
ASSERT(blockInfo->jumpBlock != nullptr);
ASSERT(blockInfo->fallthroughBlock != nullptr);
uint32_t jumpIndex = blockInfo->jumpBlock->rpoIndex;
uint32_t fallthroughIndex = blockInfo->fallthroughBlock->rpoIndex;
ValueVertex *acc = frameState->GetAcc();
self->NewControlVertex<BranchIfTrueVertex>(
self->blocks_[rpoIndex],
{acc},
self->blocks_[jumpIndex],
self->blocks_[fallthroughIndex]);
}
void LowerIsTrueOrFalse(bool isTrue)
{
CommonStubID id = isTrue ? CommonStubCSigns::ToBooleanTrue : CommonStubCSigns::ToBooleanFalse;
ValueVertex *glue = self->GetGlue();
ValueVertex *value = frameState->GetAcc();
frameState->SetAcc(CommonStubCall({glue, value}, id));
}
void LowerGetNextPropName()
{
ValueVertex *iterator = LoadRegister(0);
frameState->SetAcc(RuntimeCall({iterator}, RTSTUB_ID(GetNextPropNameSlowpath)));
}
void LowerCopyDataProperties()
{
ValueVertex *target = LoadRegister(0);
ValueVertex *source = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({target, source}, RTSTUB_ID(CopyDataProperties)));
}
void LowerLoadObjByName()
{
ValueVertex *receiver = frameState->GetAcc();
ValueVertex *id = self->graph_->GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCallWithIC({receiver, id, globalEnv}, CommonStubCSigns::GetPropertyByName));
}
void LowerStoreObjByName()
{
ValueVertex *receiver = LoadRegister(2);
ValueVertex *id = self->graph_->GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *value = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCallWithIC({receiver, id, value, globalEnv}, CommonStubCSigns::SetPropertyByName);
}
void LowerLoadObjByValue()
{
ValueVertex *receiver = LoadRegister(1);
ValueVertex *key = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCallWithIC({receiver, key, globalEnv}, CommonStubCSigns::GetPropertyByValue));
}
void LowerStoreObjByValue()
{
ValueVertex *receiver = LoadRegister(1);
ValueVertex *key = LoadRegister(2);
ValueVertex *value = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCallWithIC({receiver, key, value, globalEnv}, CommonStubCSigns::SetPropertyByValue);
}
void LowerLdObjByIndex()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *receiver = LoadRegister(1);
ValueVertex *index = self->graph_->GetInt32Constant(static_cast<int>(GetImmediate(0)));
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall({glue, receiver, index, globalEnv}, CommonStubCSigns::LdObjByIndex));
}
void LowerStObjByIndex()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *receiver = LoadRegister(0);
ValueVertex *index = self->graph_->GetInt32Constant(static_cast<int>(GetImmediate(1)));
ValueVertex *value = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, receiver, index, value, globalEnv}, CommonStubCSigns::StObjByIndex);
}
void LowerStOwnByValue()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *receiver = LoadRegister(0);
ValueVertex *key = LoadRegister(1);
ValueVertex *value = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, receiver, key, value, globalEnv}, CommonStubCSigns::StOwnByValue);
}
void LowerStOwnByIndex()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *receiver = LoadRegister(0);
ValueVertex *index = self->graph_->GetInt32Constant(static_cast<int>(GetImmediate(1)));
ValueVertex *value = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, receiver, index, value, globalEnv}, CommonStubCSigns::StOwnByIndex);
}
void LowerStOwnByName()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *propKey = StringFromConstPool(stringId);
ValueVertex *receiver = LoadRegister(1);
ValueVertex *accValue = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, receiver, propKey, accValue, globalEnv}, CommonStubCSigns::StOwnByName);
}
void LowerLdThisByValue()
{
ValueVertex *receiver = LoadParam(THIS_OBJECT_PARAM_INDEX);
ValueVertex *key = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCallWithIC({receiver, key, globalEnv}, CommonStubCSigns::GetPropertyByValue));
}
void LowerStThisByValue()
{
ValueVertex *receiver = LoadParam(THIS_OBJECT_PARAM_INDEX);
ValueVertex *key = LoadRegister(1);
ValueVertex *value = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCallWithIC({receiver, key, value, globalEnv}, CommonStubCSigns::SetPropertyByValue);
}
void LowerLdThisByName()
{
ValueVertex *receiver = LoadParam(THIS_OBJECT_PARAM_INDEX);
ValueVertex *id = self->graph_->GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCallWithIC({receiver, id, globalEnv}, CommonStubCSigns::GetPropertyByName));
}
void LowerStThisByName()
{
ValueVertex *receiver = LoadParam(THIS_OBJECT_PARAM_INDEX);
ValueVertex *id = self->graph_->GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *value = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCallWithIC({receiver, id, value, globalEnv}, CommonStubCSigns::SetPropertyByName);
}
void LowerLdSuperByValue()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *propKey = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({thisObj, propKey, jsFunc}, RTSTUB_ID(OptLdSuperByValue)));
}
void LowerStSuperByValue()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *thisObj = LoadRegister(0);
ValueVertex *propKey = LoadRegister(1);
ValueVertex *value = frameState->GetAcc();
RuntimeCall({thisObj, propKey, value, jsFunc}, RTSTUB_ID(OptStSuperByValue));
}
void LowerLdSuperByName()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *thisObj = frameState->GetAcc();
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *prop = StringFromConstPool(stringId);
frameState->SetAcc(RuntimeCall({thisObj, prop, jsFunc}, RTSTUB_ID(OptLdSuperByValue)));
}
void LowerStSuperByName()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *thisObj = LoadRegister(1);
ValueVertex *value = frameState->GetAcc();
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *prop = StringFromConstPool(stringId);
RuntimeCall({thisObj, prop, value, jsFunc}, RTSTUB_ID(OptStSuperByValue));
}
void LowerTryStGlobalByName()
{
ValueVertex *id = self->graph_->GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *value = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCallWithIC({id, value, globalEnv}, CommonStubCSigns::TryStGlobalByName);
}
void LowerStConstToGlobalRecord(bool isConst)
{
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *propKey = StringFromConstPool(stringId);
ValueVertex *value = frameState->GetAcc();
ValueVertex *isConstGate = isConst
? self->graph_->GetTaggedConstant(JSTaggedValue::True().GetRawData())
: self->graph_->GetTaggedConstant(JSTaggedValue::False().GetRawData());
RuntimeCall({propKey, value, isConstGate}, RTSTUB_ID(StGlobalRecord));
}
void LowerStOwnByValueWithNameSet()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *receiver = LoadRegister(0);
ValueVertex *propKey = LoadRegister(1);
ValueVertex *accValue = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, receiver, propKey, accValue, globalEnv}, CommonStubCSigns::StOwnByValueWithNameSet);
}
void LowerStOwnByNameWithNameSet()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *propKey = StringFromConstPool(stringId);
ValueVertex *receiver = LoadRegister(1);
ValueVertex *accValue = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, receiver, propKey, accValue, globalEnv}, CommonStubCSigns::StOwnByNameWithNameSet);
}
void LowerLdPrivateProperty()
{
ValueVertex *levelIndex = TaggedConstantFromInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *slotIndex = TaggedConstantFromInt32(static_cast<int>(GetImmediate(2)));
ValueVertex *lexicalEnv = LoadRegister(3);
ValueVertex *obj = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({lexicalEnv, levelIndex, slotIndex, obj}, RTSTUB_ID(LdPrivateProperty)));
}
void LowerStPrivateProperty()
{
ValueVertex *levelIndex = TaggedConstantFromInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *slotIndex = TaggedConstantFromInt32(static_cast<int>(GetImmediate(2)));
ValueVertex *obj = LoadRegister(3);
ValueVertex *lexicalEnv = LoadRegister(4);
ValueVertex *value = frameState->GetAcc();
RuntimeCall({lexicalEnv, levelIndex, slotIndex, obj, value}, RTSTUB_ID(StPrivateProperty));
}
void LowerLdGlobalVar()
{
ValueVertex *id = self->graph_->GetIntPtrConstant(static_cast<intptr_t>(GetConstDataId(1)));
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCallWithIC({id, globalEnv}, CommonStubCSigns::LdGlobalVar));
}
void LowerNewLexicalEnv()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *parent = LoadRegister(1);
ValueVertex *scope = self->graph_->GetInt32Constant(static_cast<int>(GetImmediate(0)));
ValueVertex *newEnv = CommonStubCall({glue, parent, scope}, CommonStubCSigns::NewLexicalEnv);
frameState->SetAcc(newEnv);
frameState->SetEnv(newEnv);
}
void LowerNewLexicalEnvWithName()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *level = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *slotId = TaggedConstantFromInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *newEnv = RuntimeCall(
{level, slotId, LoadRegister(2), jsFunc}, RTSTUB_ID(OptNewLexicalEnvWithName));
frameState->SetAcc(newEnv);
frameState->SetEnv(newEnv);
}
void LowerPopLexicalEnv()
{
ValueVertex *currentEnv = LoadRegister(0);
ValueVertex *parentEnv = GetValueFromTaggedArray(currentEnv, LexicalEnv::PARENT_ENV_INDEX);
frameState->SetAcc(parentEnv);
frameState->SetEnv(parentEnv);
}
void LowerLdLexVar()
{
ValueVertex *level = self->graph_->GetInt32Constant(static_cast<int>(GetImmediate(0)));
ValueVertex *slot = self->graph_->GetInt32Constant(static_cast<int>(GetImmediate(1)));
ValueVertex *lexicalEnv = LoadRegister(2);
ValueVertex *glue = self->GetGlue();
frameState->SetAcc(CommonStubCall({glue, level, slot, lexicalEnv}, CommonStubCSigns::LdLexVar));
}
void LowerStLexVar()
{
ValueVertex *level = self->graph_->GetInt32Constant(static_cast<int>(GetImmediate(0)));
ValueVertex *slot = self->graph_->GetInt32Constant(static_cast<int>(GetImmediate(1)));
ValueVertex *lexicalEnv = LoadRegister(2);
ValueVertex *value = frameState->GetAcc();
ValueVertex *glue = self->GetGlue();
CommonStubCall({glue, level, slot, lexicalEnv, value}, CommonStubCSigns::StLexVar);
}
void LowerStoreArraySpread()
{
ValueVertex *array = LoadRegister(0);
ValueVertex *index = LoadRegister(1);
ValueVertex *value = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({array, index, value}, RTSTUB_ID(StArraySpread)));
}
void LowerDefineGetterSetterByValue()
{
ValueVertex *obj = LoadRegister(0);
ValueVertex *prop = LoadRegister(1);
ValueVertex *getter = LoadRegister(2);
ValueVertex *setter = LoadRegister(3);
ValueVertex *acc = frameState->GetAcc();
ValueVertex *undefinedValue = self->GetUndefinedValue();
ValueVertex *taggedOne = TaggedConstantFromInt32(1);
frameState->SetAcc(RuntimeCall(
{obj, prop, getter, setter, acc, undefinedValue, taggedOne},
RTSTUB_ID(DefineGetterSetterByValue)));
}
void LowerDefineClassWithBuffer()
{
ValueVertex *methodId = TaggedConstantFromInt32(static_cast<int>(GetConstDataId(0)));
ValueVertex *literalId = TaggedConstantFromInt32(static_cast<int>(GetConstDataId(1)));
ValueVertex *length = TaggedConstantFromInt32(static_cast<int>(GetImmediate(2)));
ValueVertex *proto = LoadRegister(3);
ValueVertex *lexicalEnv = LoadRegister(4);
ValueVertex *sharedConstPool = SharedConstPool();
ValueVertex *module = ModuleFromFunction();
#if ECMASCRIPT_ENABLE_IC
ValueVertex *slotId = TaggedConstantFromInt32(static_cast<int>(GetICSlotId(5)));
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
frameState->SetAcc(RuntimeCall(
{proto, lexicalEnv, sharedConstPool, methodId, literalId, module, length, slotId, jsFunc},
RTSTUB_ID(CreateClassWithBuffer)));
#else
frameState->SetAcc(RuntimeCall(
{proto, lexicalEnv, sharedConstPool, methodId, literalId, module, length},
RTSTUB_ID(CreateClassWithBuffer)));
#endif
}
void LowerDefineFunc()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *slotId = self->graph_->GetInt32Constant(static_cast<int>(GetICSlotId(0)));
ValueVertex *methodId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(1)));
ValueVertex *length = self->graph_->GetInt32Constant(static_cast<int>(GetImmediate(2)));
ValueVertex *lexicalEnv = LoadRegister(3);
ValueVertex *globalEnv = GlobalEnv();
frameState->SetAcc(CommonStubCall(
{glue, jsFunc, methodId, length, lexicalEnv, slotId, globalEnv},
CommonStubCSigns::Definefunc));
}
void LowerCopyRestArgs()
{
ValueVertex *taggedArgc = TaggedActualArgc();
ValueVertex *taggedRestIdx = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
frameState->SetAcc(RuntimeCall({taggedArgc, taggedRestIdx}, RTSTUB_ID(OptCopyRestArgs)));
}
void LowerLdPatchVar()
{
ValueVertex *index = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
frameState->SetAcc(RuntimeCall({index}, RTSTUB_ID(LdPatchVar)));
}
void LowerStPatchVar()
{
ValueVertex *index = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *value = frameState->GetAcc();
RuntimeCall({index, value}, RTSTUB_ID(StPatchVar));
}
void LowerLdLocalModuleVar()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *index = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
frameState->SetAcc(RuntimeCall({index, jsFunc}, RTSTUB_ID(LdLocalModuleVarByIndexOnJSFunc)));
}
void LowerTestIn()
{
ValueVertex *levelIndex = TaggedConstantFromInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *slotIndex = TaggedConstantFromInt32(static_cast<int>(GetImmediate(2)));
ValueVertex *lexicalEnv = LoadRegister(3);
ValueVertex *obj = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({lexicalEnv, levelIndex, slotIndex, obj}, RTSTUB_ID(TestIn)));
}
void LowerNotifyConcurrentResult()
{
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *result = frameState->GetAcc();
RuntimeCall({result, jsFunc}, RTSTUB_ID(NotifyConcurrentResult));
}
void LowerDefinePropertyByName()
{
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(1)));
ValueVertex *prop = StringFromConstPool(stringId);
ValueVertex *obj = LoadRegister(2);
ValueVertex *value = frameState->GetAcc();
ValueVertex *glue = self->GetGlue();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, obj, prop, value, globalEnv}, CommonStubCSigns::DefineField);
}
void LowerDefineFieldByName()
{
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(1)));
ValueVertex *prop = StringFromConstPool(stringId);
ValueVertex *obj = LoadRegister(2);
ValueVertex *value = frameState->GetAcc();
ValueVertex *glue = self->GetGlue();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, obj, prop, value, globalEnv}, CommonStubCSigns::DefineField);
}
void LowerDefineFieldByValue()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *receiver = LoadRegister(1);
ValueVertex *propKey = LoadRegister(0);
ValueVertex *acc = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, receiver, propKey, acc, globalEnv}, CommonStubCSigns::DefineField);
}
void LowerDefineFieldByIndex()
{
ValueVertex *glue = self->GetGlue();
ValueVertex *receiver = LoadRegister(1);
ValueVertex *propKey = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *acc = frameState->GetAcc();
ValueVertex *globalEnv = GlobalEnv();
CommonStubCall({glue, receiver, propKey, acc, globalEnv}, CommonStubCSigns::DefineField);
}
void LowerToPropertyKey()
{
ValueVertex *value = frameState->GetAcc();
frameState->SetAcc(RuntimeCall({value}, RTSTUB_ID(ToPropertyKey)));
}
void LowerCreatePrivateProperty()
{
ValueVertex *count = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *literalId = TaggedConstantFromInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *lexicalEnv = LoadRegister(2);
ValueVertex *constpool = SharedConstPool();
ValueVertex *module = ModuleFromFunction();
RuntimeCall({lexicalEnv, count, constpool, literalId, module}, RTSTUB_ID(CreatePrivateProperty));
}
void LowerDefinePrivateProperty()
{
ValueVertex *levelIndex = TaggedConstantFromInt32(static_cast<int>(GetImmediate(0)));
ValueVertex *slotIndex = TaggedConstantFromInt32(static_cast<int>(GetImmediate(1)));
ValueVertex *obj = LoadRegister(2);
ValueVertex *lexicalEnv = LoadRegister(3);
ValueVertex *value = frameState->GetAcc();
RuntimeCall({lexicalEnv, levelIndex, slotIndex, obj, value}, RTSTUB_ID(DefinePrivateProperty));
}
void LowerLoadString()
{
ValueVertex *stringId = self->graph_->GetInt32Constant(static_cast<int>(GetConstDataId(0)));
ValueVertex *res = StringFromConstPool(stringId);
frameState->SetAcc(res);
}
void LowerJumpConstant()
{
const BasicBlockInfo *blockInfo = self->preproc_->GetBasicBlockByRPO(rpoIndex);
ASSERT(blockInfo->jumpBlock != nullptr);
uint32_t destIndex = blockInfo->jumpBlock->rpoIndex;
if (blockInfo->jumpBlock->loopBackBlock == blockInfo) {
self->NewControlVertex<JumpLoopVertex>(CurrentBlock(), {}, self->blocks_[destIndex]);
} else {
self->NewControlVertex<JumpVertex>(CurrentBlock(), {}, self->blocks_[destIndex]);
}
}
BB *CurrentBlock() const
{
return self->blocks_[rpoIndex];
}
ValueVertex *LoadRegister(int index) const
{
auto &input = bcInfo->details.inputs[index];
ASSERT(std::holds_alternative<VirtualRegister>(input));
return frameState->Get(std::get<VirtualRegister>(input).GetId());
}
ValueVertex *LoadParam(VRegIDType index) const
{
VirtualRegister v = VRegOfParam(self->GetNumLocalVRegs(), index);
return frameState->Get(v.GetId());
}
uint16_t GetConstDataId(int index) const
{
auto &input = bcInfo->details.inputs[index];
ASSERT(std::holds_alternative<ConstDataId>(input));
return std::get<ConstDataId>(input).GetId();
}
ICSlotIdType GetICSlotId(int index) const
{
auto &input = bcInfo->details.inputs[index];
ASSERT(std::holds_alternative<ICSlotId>(input));
return std::get<ICSlotId>(input).GetId();
}
ImmValueType GetImmediate(int index) const
{
auto &input = bcInfo->details.inputs[index];
ASSERT(std::holds_alternative<Immediate>(input));
return std::get<Immediate>(input).GetValue();
}
ValueVertex *ActualArgc()
{
return self->NewVertexNoInput<ActualArgcVertex>(CurrentBlock());
}
ValueVertex *TaggedActualArgc()
{
ValueVertex *argc = ActualArgc();
return self->NewVertex<ToTaggedIntVertex>(CurrentBlock(), {argc});
}
void MergeCurrentFrameStateToCatchBlock(ThrowableMixin *mixin)
{
if (blockInfo->catchBlock != nullptr) {
uint32_t catchBlockIndex = blockInfo->catchBlock->rpoIndex;
mixin->SetCaughtBy(self->blocks_[catchBlockIndex]);
mixin->SetCatchPredecessorIndex(self->AppendCatchBlockInputs(*frameState, catchBlockIndex));
}
}
void ValidateCommonStubCallArgs(Span<ValueVertex *const> inputs, CommonStubID id)
{
#ifndef NDEBUG
const CallSignature *signature = CommonStubCSigns::Get(id);
size_t actualCount = inputs.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) {
const auto *inputArr = inputs.begin();
for (size_t i = 0; i < expectedCount; ++i) {
if (MatchesCallSignatureType(inputArr[i], params[i])) {
continue;
}
const char *machineTypeName = MachineTypeName(params[i].GetMachineType());
const char *reprName = ValueRepresentationName(inputArr[i]->GetValueRepresentation());
LOG_ECMA(FATAL) << "ArkSteed CommonStub argument type mismatch, stub: " << signature->GetName()
<< ", index: " << i
<< ", expected machine type: " << machineTypeName
<< ", actual representation: " << reprName;
UNREACHABLE();
}
}
#else
(void)inputs;
(void)id;
#endif
}
ValueVertex *CommonStubCall(std::initializer_list<ValueVertex *> inputs, CommonStubID id)
{
ValidateCommonStubCallArgs({inputs.begin(), inputs.end()}, id);
auto *vertex = self->NewVertex<CallCommonStubVertex>(CurrentBlock(), inputs, id);
MergeCurrentFrameStateToCatchBlock(vertex);
return vertex;
}
ValueVertex *CommonStubCallWithIC(std::initializer_list<ValueVertex *> inputs, CommonStubID id)
{
ChunkVector<ValueVertex *> allArgs(self->GetChunk());
allArgs.reserve(inputs.size() + 3);
allArgs.push_back(self->GetGlue());
allArgs.insert(allArgs.end(), inputs.begin(), inputs.end());
allArgs.push_back(LoadParam(CALL_TARGET_PARAM_INDEX));
allArgs.push_back(self->graph_->GetInt32Constant(static_cast<int>(GetICSlotId(0))));
ValidateCommonStubCallArgs({allArgs.data(), allArgs.size()}, id);
auto *vertex = self->NewVertex<CallCommonStubVertex>(CurrentBlock(), allArgs, id);
MergeCurrentFrameStateToCatchBlock(vertex);
return vertex;
}
template <class InputRange = std::initializer_list<ValueVertex *>>
ValueVertex *RuntimeCall(const InputRange &inputs, RuntimeStubID id)
{
auto *vertex = self->NewVertex<CallRuntimeVertex>(CurrentBlock(), inputs, id);
MergeCurrentFrameStateToCatchBlock(vertex);
return vertex;
}
ValueVertex *TaggedConstantFromInt32(int value)
{
JSTaggedType taggedValue = JSTaggedValue(value).GetRawData();
return self->graph_->GetTaggedConstant(taggedValue);
}
ValueVertex *GlobalEnv()
{
ValueVertex *lexicalEnv = frameState->GetEnv();
int32_t globalEnvOffset = static_cast<int32_t>(GlobalEnv::HEADER_SIZE);
return self->NewVertex<LoadTaggedFieldVertex>(CurrentBlock(), {lexicalEnv}, globalEnvOffset);
}
ValueVertex *TaggedArrayFromValueIn(ValueVertex *taggedInputSize, uint32_t inputSize, uint32_t startIndex = 0)
{
ValueVertex *taggedArray = RuntimeCall({taggedInputSize}, RTSTUB_ID(NewTaggedArray));
for (uint32_t idx = 0; idx < inputSize; ++idx) {
ValueVertex *arg = LoadRegister(startIndex + idx);
SetValueToTaggedArray(taggedArray, idx, arg);
}
return taggedArray;
}
ValueVertex *GetValueFromTaggedArray(ValueVertex *array, uint32_t index)
{
int32_t offset = static_cast<int32_t>(TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize());
return self->NewVertex<LoadTaggedFieldVertex>(CurrentBlock(), {array}, offset);
}
ValueVertex *SetValueToTaggedArray(ValueVertex *array, uint32_t index, ValueVertex *value)
{
int32_t offset = static_cast<int32_t>(TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize());
return self->NewVertex<StoreTaggedFieldVertex>(CurrentBlock(), {array, value}, offset);
}
ValueVertex *SharedConstPool()
{
int32_t methodOffset = static_cast<int32_t>(JSFunctionBase::METHOD_OFFSET);
int32_t constpoolOffset = static_cast<int32_t>(Method::CONSTANT_POOL_OFFSET);
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
ValueVertex *method = self->NewVertex<LoadTaggedFieldVertex>(CurrentBlock(), {jsFunc}, methodOffset);
return self->NewVertex<LoadTaggedFieldVertex>(CurrentBlock(), {method}, constpoolOffset);
}
ValueVertex *ModuleFromFunction()
{
int32_t moduleOffset = static_cast<int32_t>(JSFunction::ECMA_MODULE_OFFSET);
ValueVertex *jsFunc = LoadParam(CALL_TARGET_PARAM_INDEX);
return self->NewVertex<LoadTaggedFieldVertex>(CurrentBlock(), {jsFunc}, moduleOffset);
}
ValueVertex *StringFromConstPool(ValueVertex *stringId)
{
ValueVertex *glue = self->GetGlue();
ValueVertex *constpool = SharedConstPool();
return CommonStubCall({glue, constpool, stringId}, CommonStubCSigns::GetStringFromConstPool);
}
ValueVertex *ObjectFromConstPool(ValueVertex *index)
{
ValueVertex *glue = self->GetGlue();
ValueVertex *constpool = SharedConstPool();
ValueVertex *module = ModuleFromFunction();
return CommonStubCall({glue, constpool, index, module}, CommonStubCSigns::GetObjectFromConstPool);
}
ValueVertex *MethodFromConstPool(ValueVertex *index)
{
ValueVertex *constpool = SharedConstPool();
return RuntimeCall({constpool, index}, RTSTUB_ID(GetMethodFromCache));
}
GraphBuilderNew *self;
uint32_t rpoIndex;
BCFrameState *frameState;
const BasicBlockInfo *blockInfo;
const BytecodeInfo *bcInfo;
};
void GraphBuilderNew::VisitBytecode(uint32_t rpoIndex, BCFrameState *frameState, const BytecodeInfo *bcInfo)
{
const BasicBlockInfo *blockInfo = preproc_->GetBasicBlockByRPO(rpoIndex);
BytecodeVisitor{this, rpoIndex, frameState, blockInfo, bcInfo}.Visit();
}
}