* 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.
*/
#ifndef ECMASCRIPT_ARKSTEED_BYTECODE_CONTEXT_H
#define ECMASCRIPT_ARKSTEED_BYTECODE_CONTEXT_H
#include "ecmascript/arksteed/arksteed_bytecode_preprocessor.h"
#include "ecmascript/arksteed/arksteed_compiler.h"
#include "ecmascript/compiler/bytecode_info_collector.h"
#include "ecmascript/compiler/bytecodes.h"
#include "ecmascript/compiler/jit_compilation_env.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/jspandafile/method_literal.h"
#include "ecmascript/mem/chunk_containers.h"
#include "libpandafile/bytecode_instruction.h"
namespace panda::ecmascript::arksteed {
struct ExceptionItem {
uint32_t startBcIndex;
uint32_t endBcIndex;
std::vector<uint32_t> catchBcIndices;
ExceptionItem(uint32_t startBcIndex, uint32_t endBcIndex, std::vector<uint32_t> catchBcIndices)
: startBcIndex(startBcIndex), endBcIndex(endBcIndex), catchBcIndices(catchBcIndices)
{}
};
using ExceptionInfo = ChunkVector<ExceptionItem>;
class BytecodeContext {
public:
static constexpr uint32_t INVALID_BC_INDEX = UINT32_MAX;
explicit BytecodeContext(Chunk *chunk)
: chunk_(chunk),
infoData_(chunk),
maxLoopEndIndex_(chunk),
jumpTargetIndex_(chunk),
pcOffsets_(chunk),
bcIndex_(chunk),
exceptionInfo_(chunk),
preprocessor_(chunk)
{}
~BytecodeContext() = default;
void Initialize(MethodLiteral *method, JitCompilationEnv *env, const ArkSteedCompilationOptions *options);
Bytecodes &GetBytecodes()
{
return bytecodes_;
}
const Bytecodes &GetBytecodes() const
{
return bytecodes_;
}
ChunkVector<BytecodeInfo> &GetInfoData()
{
return infoData_;
}
const ChunkVector<BytecodeInfo> &GetInfoData() const
{
return infoData_;
}
std::vector<bool> &GetJumpLoop()
{
return jumpLoop_;
}
const std::vector<bool> &GetJumpLoop() const
{
return jumpLoop_;
}
std::vector<ChunkVector<uint32_t> *> &GetLoopEndIndex()
{
return loopEndIndex_;
}
const std::vector<ChunkVector<uint32_t> *> &GetLoopEndIndex() const
{
return loopEndIndex_;
}
ChunkVector<uint32_t> &GetMaxLoopEndIndex()
{
return maxLoopEndIndex_;
}
const ChunkVector<uint32_t> &GetMaxLoopEndIndex() const
{
return maxLoopEndIndex_;
}
ChunkVector<const uint8_t *> &GetPcOffsets()
{
return pcOffsets_;
}
const ChunkVector<const uint8_t *> &GetPcOffsets() const
{
return pcOffsets_;
}
ChunkVector<uint32_t> &GetBcIndex()
{
return bcIndex_;
}
const ChunkVector<uint32_t> &GetBcIndex() const
{
return bcIndex_;
}
const uint8_t *GetBytecodeStart() const
{
return bytecodeStart_;
}
uint32_t GetPcOffset(const uint8_t *pc) const
{
return static_cast<uint32_t>(pc - bytecodeStart_);
}
size_t GetBytecodeCount() const
{
return infoData_.size();
}
MethodLiteral *GetMethod() const
{
return method_;
}
const ExceptionInfo &GetExceptionInfo() const
{
return exceptionInfo_;
}
const ChunkVector<uint32_t> &GetPredecessorCount() const
{
return preprocessor_.GetPredecessorCount();
}
bool HasTryCatch() const
{
return hasTryCatch_;
}
bool IsLogEnabled() const
{
return options_->enableLog;
}
void SetOptions(const ArkSteedCompilationOptions *options)
{
options_ = options;
}
const BytecodePreprocessor &GetPreprocessor() const
{
return preprocessor_;
}
uint32_t GetJumpTargetBcIndex(uint32_t bcIndex) const
{
ASSERT(jumpTargetIndex_[bcIndex] != INVALID_BC_INDEX);
return jumpTargetIndex_[bcIndex];
}
private:
void CollectPcOffsets();
void CollectJumpTargets();
void BuildBytecodeInfo(size_t envVregIdx);
void JumpLoopAnalysis();
bool NeedInsertJumpForLoop(uint32_t loopHeaderIndex) const;
void RebuildBytecodeWithJumpRedirection();
void CollectTryCatchBlockInfo(JitCompilationEnv *env);
Bytecodes bytecodes_;
Chunk *chunk_;
ChunkVector<BytecodeInfo> infoData_;
std::vector<bool> jumpLoop_;
std::vector<ChunkVector<uint32_t> *> loopEndIndex_;
ChunkVector<uint32_t> maxLoopEndIndex_;
ChunkVector<uint32_t> jumpTargetIndex_;
ChunkVector<const uint8_t *> pcOffsets_;
ChunkVector<uint32_t> bcIndex_;
const uint8_t *bytecodeStart_ = nullptr;
uint32_t bytecodeSize_ = 0;
MethodLiteral *method_ = nullptr;
const ArkSteedCompilationOptions *options_ = nullptr;
ExceptionInfo exceptionInfo_;
bool hasTryCatch_ = false;
BytecodePreprocessor preprocessor_;
};
}
#endif