* 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_GRAPH_H
#define ECMASCRIPT_ARKSTEED_GRAPH_H
#include "ecmascript/arksteed/arksteed_bb.h"
#include "ecmascript/arksteed/arksteed_graph_labeller.h"
#include "ecmascript/arksteed/arksteed_opcode.h"
#include "ecmascript/arksteed/arksteed_vertex.h"
#include "ecmascript/mem/chunk_containers.h"
namespace panda::ecmascript::arksteed {
class Graph {
public:
NO_COPY_SEMANTIC(Graph);
NO_MOVE_SEMANTIC(Graph);
static Graph *New(Chunk *chunk)
{
return chunk->New<Graph>(chunk);
}
explicit Graph(Chunk *chunk)
: chunk_(chunk),
blocks_(chunk),
parameters_(chunk),
rootConstants_(chunk),
int32Constants_(chunk),
intPtrConstants_(chunk),
float64Constants_(chunk),
taggedConstants_(chunk),
maxCallStackArgs_(0),
maxDeoptedStackSize_(0),
taggedStackSlots_(0),
untaggedStackSlots_(0),
maxBlockId_(0),
hasRecursiveCalls_(false),
mayHaveUnreachableBlocks_(false)
{}
ValueVertex *GetRootConstant(RootConstantVertex::RootIndex index)
{
return GetOrAddNewConstantVertex(rootConstants_, index);
}
ValueVertex *GetInt32Constant(int32_t value)
{
return GetOrAddNewConstantVertex(int32Constants_, value);
}
ValueVertex *GetIntPtrConstant(intptr_t value)
{
return GetOrAddNewConstantVertex(intPtrConstants_, value);
}
ValueVertex *GetFloat64Constant(double value)
{
return GetOrAddNewConstantVertex(float64Constants_, value);
}
ValueVertex *GetTaggedConstant(uint64_t value)
{
return GetOrAddNewConstantVertex(taggedConstants_, value);
}
const ChunkMap<RootConstantVertex::RootIndex, RootConstantVertex *> &GetRootConstants() const
{
return rootConstants_;
}
const ChunkMap<int32_t, Int32ConstantVertex *> &GetInt32Constants() const
{
return int32Constants_;
}
const ChunkMap<intptr_t, IntPtrConstantVertex *> &GetIntPtrConstants() const
{
return intPtrConstants_;
}
const ChunkMap<double, Float64ConstantVertex *> &GetFloat64Constants() const
{
return float64Constants_;
}
const ChunkMap<uint64_t, TaggedConstantVertex *> &GetTaggedConstants() const
{
return taggedConstants_;
}
BB *operator[](int i)
{
return blocks_[i];
}
const BB *operator[](int i) const
{
return blocks_[i];
}
int NumBlocks() const
{
return static_cast<int>(blocks_.size());
}
void Add(BB *block)
{
if (block->GetId() == INVALID_BLOCK_ID) {
block->SetId(maxBlockId_++);
}
blocks_.push_back(block);
}
void RemoveUnreachableBlocks();
using BlockIterator = ChunkVector<BB *>::iterator;
using ConstBlockIterator = ChunkVector<BB *>::const_iterator;
BlockIterator begin()
{
return blocks_.begin();
}
BlockIterator end()
{
return blocks_.end();
}
ConstBlockIterator begin() const
{
return blocks_.begin();
}
ConstBlockIterator end() const
{
return blocks_.end();
}
BB *LastBlock() const
{
return blocks_.back();
}
void AddParameter(ValueVertex *param)
{
parameters_.push_back(param);
}
ValueVertex *GetParameter(int index) const
{
if (index < 0 || index >= static_cast<int>(parameters_.size())) {
return nullptr;
}
return parameters_[index];
}
size_t GetParameterCount() const
{
return parameters_.size();
}
uint32_t NewBlockId()
{
return maxBlockId_++;
}
uint32_t MaxBlockId() const
{
return maxBlockId_;
}
bool HasRecursiveCalls() const
{
return hasRecursiveCalls_;
}
void SetHasRecursiveCalls(bool value)
{
hasRecursiveCalls_ = value;
}
bool MayHaveUnreachableBlocks() const
{
return mayHaveUnreachableBlocks_;
}
void SetMayHaveUnreachableBlocks(bool value)
{
mayHaveUnreachableBlocks_ = value;
}
Chunk *GetChunk() const
{
return chunk_;
}
void SetMaxCallStackArgs(int args)
{
maxCallStackArgs_ = args;
}
int GetMaxCallStackArgs() const
{
return maxCallStackArgs_;
}
void SetMaxDeoptedStackSize(int size)
{
maxDeoptedStackSize_ = size;
}
int GetMaxDeoptedStackSize() const
{
return maxDeoptedStackSize_;
}
void SetTaggedStackSlots(uint32_t slots)
{
taggedStackSlots_ = slots;
}
uint32_t GetTaggedStackSlots() const
{
return taggedStackSlots_;
}
void SetUntaggedStackSlots(uint32_t slots)
{
untaggedStackSlots_ = slots;
}
uint32_t GetUntaggedStackSlots() const
{
return untaggedStackSlots_;
}
void Print() const;
private:
Chunk *chunk_;
ChunkVector<BB *> blocks_;
ChunkVector<ValueVertex *> parameters_;
ChunkMap<RootConstantVertex::RootIndex, RootConstantVertex *> rootConstants_;
ChunkMap<int32_t, Int32ConstantVertex *> int32Constants_;
ChunkMap<intptr_t, IntPtrConstantVertex *> intPtrConstants_;
ChunkMap<double, Float64ConstantVertex *> float64Constants_;
ChunkMap<uint64_t, TaggedConstantVertex *> taggedConstants_;
int maxCallStackArgs_ = 0;
int maxDeoptedStackSize_ = 0;
uint32_t taggedStackSlots_ = 0;
uint32_t untaggedStackSlots_ = 0;
template <typename VertexT, typename T>
VertexT *GetOrAddNewConstantVertex(ChunkMap<T, VertexT *> &container, T constant)
{
auto it = container.find(constant);
if (it != container.end()) {
return it->second;
}
VertexT *vertex = Vertex::New<VertexT>(chunk_, 0, constant);
ArkSteedGraphLabeller *labeller = GetCurrentGraphLabeller();
if (labeller != nullptr) {
labeller->RegisterVertex(vertex);
}
container.emplace(constant, vertex);
return vertex;
}
uint32_t maxBlockId_;
bool hasRecursiveCalls_;
bool mayHaveUnreachableBlocks_;
};
}
#endif