Type system adaption for Bytecode optimizer

1. Adapt typescript type system for bytecode optimizer
2. Delete file_items_gen_inc as we do not have multi languages to support
3. Add log which can display typeinfo after optimizations in debug mode

Issue: I5HYBL
Signed-off-by: qiuyu <qiuyu22@huawei.com>
Change-Id: I97ce3fb3aca1592329abad86e022e74ecff4b9eb
This commit is contained in:
qiuyu 2022-07-19 17:00:49 +08:00
parent 9a5d32a838
commit 5a0298be18
16 changed files with 614 additions and 125 deletions

View File

@ -279,3 +279,7 @@ merge_yamls("merge_runtime_options_yamls") {
output_file = "$target_gen_dir/runtime_options.yaml"
add_yamls = [ "$ark_root/runtime/options.yaml" ] + runtime_options_yamls
}
group("bcopt_type_adapter_unit_test") {
deps = [ "$ark_root/bytecode_optimizer/tests:bcopt_type_adapter_unit_test(//build/toolchain/linux:clang_x64)" ]
}

View File

@ -102,6 +102,10 @@ void BytecodeGen::VisitTryBegin(const compiler::BasicBlock *bb)
bool BytecodeGen::RunImpl()
{
Reserve(function_->ins.size());
std::vector<ScalarValue> elements;
AddTypeInfoIndexForArguments(&elements);
bool need_handle_ins_type = GetGraph()->GetRuntime()->HasInsTypeinfo();
int32_t insn_order = 0;
for (auto *bb : GetGraph()->GetBlocksLinearOrder()) {
EmitLabel(BytecodeGen::LabelName(bb->GetId()));
if (bb->IsTryEnd() || bb->IsCatchEnd()) {
@ -118,9 +122,13 @@ bool BytecodeGen::RunImpl()
ASSERT(end >= start);
for (auto i = start; i < end; ++i) {
AddLineNumber(inst, i);
if (GetGraph()->IsDynamicMethod()) {
AddColumnNumber(inst, i);
}
AddColumnNumber(inst, i);
}
if (need_handle_ins_type && end > start) {
// fill ins types. Need to exclude invalid ins as they do not emit
insn_order += std::count_if(GetResult().begin() + start, GetResult().end(),
[](const auto &ins) { return ins.opcode != pandasm::Opcode::INVALID; });
AddTypeInfoIndexForIns(insn_order - 1, inst->GetId(), &elements);
}
}
if (bb->NeedsJump()) {
@ -136,9 +144,60 @@ bool BytecodeGen::RunImpl()
}
function_->ins = std::move(GetResult());
function_->catch_blocks = catch_blocks_;
UpdateTypeInfoIndexAnnotation(&elements);
return true;
}
void BytecodeGen::AddTypeInfoIndexForArguments(std::vector<ScalarValue> *elements) const
{
std::unordered_map<int32_t, TypeInfoIndex> args_types_map;
if (GetGraph()->GetRuntime()->FillArgTypePairs(&args_types_map)) {
for (const auto &[arg, type] : args_types_map) {
ASSERT(arg < 0);
AddOrderAndTypeInfoIndex(arg, type, elements);
}
}
}
void BytecodeGen::AddOrderAndTypeInfoIndex(int32_t order, TypeInfoIndex type, std::vector<ScalarValue> *elements) const
{
ScalarValue insn_order(ScalarValue::Create<panda::pandasm::Value::Type::I32>(order));
elements->emplace_back(std::move(insn_order));
ScalarValue type_info_index(ScalarValue::Create<panda::pandasm::Value::Type::I32>(type));
elements->emplace_back(std::move(type_info_index));
}
void BytecodeGen::AddTypeInfoIndexForIns(int32_t order, size_t id, std::vector<ScalarValue> *elements) const
{
auto type = GetGraph()->GetRuntime()->GetTypeInfoIndexByInstId(id);
if (type != NO_EXPLICIT_TYPE) {
AddOrderAndTypeInfoIndex(order, type, elements);
}
}
void BytecodeGen::UpdateTypeInfoIndexAnnotation(const std::vector<ScalarValue> *elements)
{
#ifndef NDEBUG
LOG(DEBUG, BYTECODE_OPTIMIZER) << "Typeinfo after optimization for function : " << function_->name;
const size_t PAIR_GAP = 2;
for (size_t i = 0; i < elements->size(); i += PAIR_GAP) {
auto order = (*elements)[i].GetValue<int32_t>();
auto type = (*elements)[i + 1].GetValue<int32_t>();
LOG(DEBUG, BYTECODE_OPTIMIZER) << "[" << order << ", " << type << "], ";
}
#endif
const auto *type_idx = GetGraph()->GetRuntime()->GetTypeAnnotationIndex();
ASSERT(type_idx != nullptr);
if (type_idx->first == INVALID_TYPE_INDEX || type_idx->second == INVALID_TYPE_INDEX) {
return;
}
ASSERT(type_idx->first < function_->metadata->GetAnnotations().size());
panda::pandasm::ArrayValue arr(panda::pandasm::Value::Type::I32, *elements);
panda::pandasm::AnnotationElement anno_elem(TSTYPE_ANNO_ELEMENT_NAME,
std::make_unique<panda::pandasm::ArrayValue>(arr));
function_->metadata->SetOrAddAnnotationElementByIndex(type_idx->first, type_idx->second, std::move(anno_elem));
}
void BytecodeGen::EmitJump(const BasicBlock *bb)
{
BasicBlock *suc_bb = nullptr;

View File

@ -16,6 +16,7 @@
#ifndef PANDA_BYTECODE_OPT_CODEGEN_H
#define PANDA_BYTECODE_OPT_CODEGEN_H
#include "assembler/annotation.h"
#include "assembler/assembly-function.h"
#include "assembler/assembly-ins.h"
#include "ins_create_api.h"
@ -146,6 +147,13 @@ private:
const compiler::BasicBlock *catch_begin, const compiler::BasicBlock *catch_end = nullptr);
void VisitTryBegin(const compiler::BasicBlock *bb);
// TypeInfoIndex typeinfo adaption
using ScalarValue = panda::pandasm::ScalarValue;
void AddTypeInfoIndexForArguments(std::vector<ScalarValue> *elements) const;
void AddOrderAndTypeInfoIndex(int32_t order, TypeInfoIndex type, std::vector<ScalarValue> *elements) const;
void AddTypeInfoIndexForIns(int32_t order, size_t id, std::vector<ScalarValue> *elements) const;
void UpdateTypeInfoIndexAnnotation(const std::vector<ScalarValue> *elements);
private:
pandasm::Function *function_;
const BytecodeOptIrInterface *ir_interface_;

View File

@ -149,6 +149,67 @@ void BuildMapFromPcToIns(pandasm::Function &function, BytecodeOptIrInterface &ir
}
}
static void ExtractTypeInfo(const pandasm::Function &function, compiler::RuntimeInterface *adapter,
std::unordered_map<int32_t, TypeInfoIndex> *order_type_map)
{
const auto &annos = function.metadata->GetAnnotations();
const auto type_anno = std::find_if(annos.begin(), annos.end(),
[](const auto &an) { return an.GetName() == TSTYPE_ANNO_RECORD_NAME; });
if (type_anno == annos.end()) {
return;
}
const auto &elems = type_anno->GetElements();
const auto type_elem = std::find_if(elems.begin(), elems.end(),
[](const auto &e) { return e.GetName() == TSTYPE_ANNO_ELEMENT_NAME; });
if (type_elem == elems.end()) {
return;
}
adapter->SetTypeAnnotationIndex(type_anno - annos.begin(), type_elem - elems.begin());
const auto *arr_val = type_elem->GetValue();
ASSERT(arr_val != nullptr);
ASSERT(arr_val->IsArray());
const auto &values = arr_val->GetAsArray()->GetValues();
ASSERT(values.size() % 2 == 0); // 2: size must be even because values consits of pairs of orders and types
size_t i = 0;
while (i < values.size()) {
auto order = values[i++].GetValue<int32_t>();
auto type = values[i++].GetValue<int32_t>();
if (order < 0) { // arguments
adapter->AddPcTypePair(order, type);
} else { // instructions
order_type_map->emplace(order, type);
}
}
}
static void BuildMapFromPcToType(const pandasm::Function &function, const compiler::Graph *graph,
compiler::RuntimeInterface::MethodPtr method_ptr)
{
std::unordered_map<int32_t, TypeInfoIndex> tmp_order_type_map;
ExtractTypeInfo(function, graph->GetRuntime(), &tmp_order_type_map);
if (tmp_order_type_map.empty()) {
return;
}
const auto *instruction_buf = graph->GetRuntime()->GetMethodCode(method_ptr);
compiler::BytecodeInstructions instructions(instruction_buf, graph->GetRuntime()->GetMethodCodeSize(method_ptr));
int32_t order = 0;
size_t num_collected = 0;
for (const auto &insn : instructions) {
const auto it = tmp_order_type_map.find(order++);
if (it == tmp_order_type_map.end()) {
continue;
}
auto pc = static_cast<int32_t>(instructions.GetPc(insn));
graph->GetRuntime()->AddPcTypePair(pc, it->second);
num_collected++;
// stop when all typeinfo has been collected
if (num_collected == tmp_order_type_map.size()) {
break;
}
}
}
static void ColumnNumberPropagate(pandasm::Function *function)
{
auto &ins_vec = function->ins;
@ -282,6 +343,8 @@ bool OptimizeFunction(pandasm::Program *prog, const pandasm::AsmEmitter::PandaFi
return false;
}
BuildMapFromPcToType(function, graph, method_ptr);
// build map from pc to pandasm::ins (to re-build line-number info in BytecodeGen)
BuildMapFromPcToIns(function, ir_interface, graph, method_ptr);

View File

@ -342,6 +342,62 @@ public:
return utf::Mutf8AsCString(string_data.data);
}
TypeInfoIndex GetTypeInfoIndexByInstId(size_t id) const override
{
const auto it = instid_type_map_.find(id);
if (it == instid_type_map_.end()) {
return NO_EXPLICIT_TYPE;
}
return it->second;
}
bool FillInstIdTypePairByPc(size_t id, int32_t pc) override
{
const auto it = pc_type_map_.find(pc);
if (it != pc_type_map_.end()) {
instid_type_map_.emplace(id, it->second);
return true;
}
return false;
}
bool HasInsTypeinfo() const override
{
return !instid_type_map_.empty();
}
bool AddPcTypePair(int32_t pc, TypeInfoIndex type) override
{
if (pc_type_map_.find(pc) != pc_type_map_.end()) {
return false;
}
pc_type_map_.emplace(pc, type);
return true;
}
bool FillArgTypePairs(std::unordered_map<int32_t, TypeInfoIndex> *map) const override
{
ASSERT(map != nullptr);
ASSERT(map->empty());
for (const auto &[pc, type] : pc_type_map_) {
if (pc < 0) {
map->emplace(pc, type);
}
}
return !map->empty();
}
bool SetTypeAnnotationIndex(size_t anno_idx, size_t elem_idx) override
{
anno_elem_idx_ = { anno_idx, elem_idx };
return anno_idx != INVALID_TYPE_INDEX && elem_idx != INVALID_TYPE_INDEX;
}
const std::pair<size_t, size_t> *GetTypeAnnotationIndex() const override
{
return &anno_elem_idx_;
}
private:
static compiler::DataType::Type ToCompilerType(panda_file::Type type)
{
@ -397,6 +453,9 @@ private:
}
const panda_file::File &panda_file_;
std::unordered_map<size_t, TypeInfoIndex> instid_type_map_;
std::unordered_map<int32_t, TypeInfoIndex> pc_type_map_;
std::pair<size_t, size_t> anno_elem_idx_ = std::make_pair(INVALID_TYPE_INDEX, INVALID_TYPE_INDEX);
};
} // namespace panda

View File

@ -0,0 +1,64 @@
# Copyright (c) 2022 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.
import("//arkcompiler/runtime_core/ark_config.gni")
import("//build/ohos.gni")
ohos_executable("bcopt_type_adapter_unit_test") {
sources = [ "bcopt_type_adaption_test.cpp" ]
configs = [
"$ark_root:ark_config",
"$ark_root/assembler:arkassembler_public_config",
"$ark_root/runtime:arkruntime_public_config",
"$ark_root/libpandabase:arkbase_public_config",
"$ark_root/libpandafile:arkfile_public_config",
"$ark_root/compiler:arkcompiler_public_config",
"$ark_root/bytecode_optimizer:bytecodeopt_public_config",
sdk_libc_secshared_config,
]
deps = [ sdk_libc_secshared_dep ]
if (is_linux || is_mingw || is_mac) {
deps += [
"$ark_root/assembler:libarkassembler_frontend_static",
"$ark_root/bytecode_optimizer:libarkbytecodeopt_frontend_static",
"$ark_root/compiler:libarkcompiler_frontend_static",
"$ark_root/libpandabase:libarkbase_frontend_static",
"$ark_root/libpandafile:libarkfile_frontend_static",
"$ark_root/libziparchive:libarkziparchive_frontend_static",
]
} else {
deps += [
"$ark_root/assembler:libarkassembler",
"$ark_root/bytecode_optimizer:libarkbytecodeopt",
"$ark_root/compiler:libarkcompiler",
"$ark_root/libpandabase:libarkbase",
"$ark_root/libpandafile:libarkfile",
"$ark_root/libziparchive:libarkziparchive",
]
}
if (is_linux) {
if (build_public_version) {
ldflags = [ "-static-libstdc++" ]
} else {
libs = [ libcpp_static_lib ]
}
}
output_name = "bcopt_type_adapter_unit_test"
install_enable = true
subsystem_name = "ark"
}

View File

@ -0,0 +1,245 @@
/*
* Copyright (c) 2022 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 "assembler/meta.h"
#include "assembler/assembly-parser.h"
#include "bytecode_optimizer/optimize_bytecode.h"
namespace panda::bytecodeopt::test {
using ArrayValue = panda::pandasm::ArrayValue;
using ScalarValue = panda::pandasm::ScalarValue;
using AnnotationData = panda::pandasm::AnnotationData;
using AnnotationElement = panda::pandasm::AnnotationElement;
class TestBase {
public:
template <typename T1, typename T2>
inline void TestAssertEqual(const T1 &left, const T2 &right) const
{
if (left != static_cast<T1>(right)) {
std::cout << "assertion equal failed." << std::endl;
UNREACHABLE();
}
}
template <typename T1, typename T2>
inline void TestAssertNotEqual(const T1 &left, const T2 &right) const
{
if (left == static_cast<T1>(right)) {
std::cout << "assertion not equal failed." << std::endl;
UNREACHABLE();
}
}
inline void TestAssertTrue(bool val) const
{
if (!val) {
UNREACHABLE();
}
}
inline void TestAssertFalse(bool val) const
{
if (val) {
UNREACHABLE();
}
}
};
class BytecodeOptimizerTypeAdaptionTest : TestBase {
public:
std::unordered_map<int32_t, int32_t> ExtractTypeinfo(const panda::pandasm::Function &fun) const
{
const auto *ele = fun.metadata->GetAnnotations()[0].GetElements()[0].GetValue();
const auto &values = ele->GetAsArray()->GetValues();
std::unordered_map<int32_t, int32_t> type_info;
const size_t PAIR_GAP = 2;
TestAssertEqual(values.size() % PAIR_GAP, 0); // must be even as it consits of pairs
for (size_t i = 0; i < values.size(); i += PAIR_GAP) {
type_info.emplace(values[i].GetValue<int32_t>(), values[i + 1].GetValue<int32_t>());
}
return type_info;
}
void CheckTypeExist(const std::unordered_map<int32_t, int32_t> &typeinfo, int32_t order, int32_t type) const
{
auto type_it = typeinfo.find(order);
TestAssertNotEqual(type_it, typeinfo.end());
TestAssertEqual(type_it->second, type);
}
void AddTypeinfo(std::vector<ScalarValue> *elements, int32_t order, int32_t type) const
{
ScalarValue insn_order(ScalarValue::Create<panda::pandasm::Value::Type::I32>(order));
elements->emplace_back(std::move(insn_order));
ScalarValue insn_type(ScalarValue::Create<panda::pandasm::Value::Type::I32>(type));
elements->emplace_back(std::move(insn_type));
}
void TypeAdaptionTest() const;
static constexpr int32_t NUM_TYPE = 1;
static constexpr int32_t STR_TYPE = 4;
};
void BytecodeOptimizerTypeAdaptionTest::TypeAdaptionTest() const
{
/* ts source code
function foo(a:number, b:string, c:string):string
{
let t:number = 100;
if (a > t) {
return b;
}
if (a < t) {
return c;
}
let ret:string = b + c;
return ret;
}
*/
const auto source = R"(
.language ECMAScript
.record _ESTypeAnnotation <external>
.function any foo(any a0, any a1, any a2) <static> {
mov.dyn v2, a2
mov.dyn v1, a1
mov.dyn v0, a0
ecma.ldlexenvdyn
sta.dyn v6
ldai.dyn 0x64
sta.dyn v3
lda.dyn v0
sta.dyn v5
lda.dyn v3
ecma.greaterdyn v5
jeqz jump_label_0
lda.dyn v1
sta.dyn v5
lda.dyn v5
return.dyn
jump_label_0:
lda.dyn v0
sta.dyn v5
lda.dyn v3
ecma.lessdyn v5
jeqz jump_label_1
lda.dyn v2
sta.dyn v5
lda.dyn v5
return.dyn
jump_label_1:
lda.dyn v1
sta.dyn v5
lda.dyn v2
ecma.add2dyn v5
sta.dyn v4
lda.dyn v4
sta.dyn v5
lda.dyn v5
return.dyn
}
)";
panda::pandasm::Parser parser;
auto res = parser.Parse(source);
auto &program = res.Value();
const std::string fun_name = "foo:(any,any,any)";
auto it = program.function_table.find(fun_name);
TestAssertNotEqual(it, program.function_table.end());
auto &func = it->second;
std::vector<panda::pandasm::ScalarValue> elements;
// set arg type
AddTypeinfo(&elements, -1, NUM_TYPE); // -1 means first arg
AddTypeinfo(&elements, -2, STR_TYPE); // -2 means second arg
AddTypeinfo(&elements, -3, STR_TYPE); // -3 means third arg
// set ins type
const size_t LDAI_IDX = 5;
TestAssertEqual(func.ins[LDAI_IDX].opcode, panda::pandasm::Opcode::LDAI_DYN);
TestAssertEqual(func.ins[LDAI_IDX + 1].opcode, panda::pandasm::Opcode::STA_DYN);
AddTypeinfo(&elements, static_cast<int32_t>(LDAI_IDX + 1), NUM_TYPE);
const size_t ADD_IDX = 30;
TestAssertEqual(func.ins[ADD_IDX].opcode, panda::pandasm::Opcode::ECMA_ADD2DYN);
TestAssertEqual(func.ins[ADD_IDX + 1].opcode, panda::pandasm::Opcode::STA_DYN);
AddTypeinfo(&elements, static_cast<int32_t>(ADD_IDX + 1), STR_TYPE);
ArrayValue array_value(panda::pandasm::Value::Type::I32, elements);
AnnotationElement anno_element(TSTYPE_ANNO_ELEMENT_NAME, std::make_unique<ArrayValue>(array_value));
AnnotationData annotation(TSTYPE_ANNO_RECORD_NAME);
annotation.AddElement(std::move(anno_element));
std::vector<AnnotationData> annos;
annos.emplace_back(std::move(annotation));
func.metadata->SetAnnotations(std::move(annos));
const auto iterator = program.record_table.find(TSTYPE_ANNO_RECORD_NAME.data());
TestAssertNotEqual(iterator, program.record_table.end());
iterator->second.metadata->SetAccessFlags(panda::ACC_ANNOTATION);
TestAssertTrue(program.record_table.find(TSTYPE_ANNO_RECORD_NAME.data())->second.metadata->IsAnnotation());
// emit and optimize
const std::string abc_file_name = "TypeAdaptionTest.abc";
std::map<std::string, size_t> stat;
std::map<std::string, size_t> *statp = nullptr;
panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = &maps;
TestAssertTrue(panda::pandasm::AsmEmitter::Emit(abc_file_name, program, statp, mapsp, false));
TestAssertTrue(panda::bytecodeopt::OptimizeBytecode(&program, mapsp, abc_file_name, true));
// check typeinfo after optimization
it = program.function_table.find(fun_name);
TestAssertNotEqual(it, program.function_table.end());
const auto &foo = it->second;
const auto typeinfo = ExtractTypeinfo(foo);
CheckTypeExist(typeinfo, -1, NUM_TYPE); // -1 means first arg
CheckTypeExist(typeinfo, -2, STR_TYPE); // -2 means second arg
CheckTypeExist(typeinfo, -3, STR_TYPE); // -3 means third arg
auto ldai_it = std::find_if(foo.ins.begin(), foo.ins.end(),
[](const auto &in) { return in.opcode == panda::pandasm::Opcode::LDAI_DYN; });
TestAssertNotEqual(ldai_it, foo.ins.end());
const auto opt_ldai_idx = static_cast<size_t>(ldai_it - foo.ins.begin());
TestAssertEqual(foo.ins[opt_ldai_idx].opcode, panda::pandasm::Opcode::LDAI_DYN);
TestAssertTrue(opt_ldai_idx + 1 < foo.ins.size());
TestAssertEqual(foo.ins[opt_ldai_idx + 1].opcode, panda::pandasm::Opcode::STA_DYN);
int32_t num_invalid = std::count_if(foo.ins.begin(), ldai_it,
[](const auto &in) { return in.opcode == panda::pandasm::Opcode::INVALID; });
int32_t ldai_type_idx = opt_ldai_idx - num_invalid; // exclude invalid insns because they do not emit
CheckTypeExist(typeinfo, ldai_type_idx + 1, NUM_TYPE); // type is on sta.dyn
auto add_it = std::find_if(foo.ins.begin(), foo.ins.end(),
[](const auto &in) { return in.opcode == panda::pandasm::Opcode::ECMA_ADD2DYN; });
TestAssertNotEqual(add_it, foo.ins.end());
const auto opt_add_idx = static_cast<size_t>(add_it - foo.ins.begin());
TestAssertEqual(foo.ins[opt_add_idx].opcode, panda::pandasm::Opcode::ECMA_ADD2DYN);
TestAssertTrue(opt_add_idx + 1 < foo.ins.size());
TestAssertNotEqual(foo.ins[opt_add_idx + 1].opcode, panda::pandasm::Opcode::STA_DYN);
num_invalid = std::count_if(foo.ins.begin(), add_it,
[](const auto &in) { return in.opcode == panda::pandasm::Opcode::INVALID; });
int32_t add_type_idx = opt_add_idx - num_invalid; // exclude invalid insns because they do not emit
CheckTypeExist(typeinfo, add_type_idx, STR_TYPE); // type is on ecma.add2dyn as it does not have sta.dyn
TestAssertTrue(panda::pandasm::AsmEmitter::Emit(abc_file_name, program, statp, mapsp, false));
}
} // namespace panda::bytecodeopt::test
int main()
{
panda::bytecodeopt::test::BytecodeOptimizerTypeAdaptionTest test;
std::cout << "BytecodeOptimizerTypeAdaptionTest: " << std::endl;
test.TypeAdaptionTest();
std::cout << "PASS!" << std::endl;
return 0;
}

View File

@ -149,15 +149,6 @@ foreach(plugin, enabled_plugins) {
source_files = []
}
if (!is_win && !is_mac && !is_mingw) {
libarkcompiler_sources += [
"code_info/code_info.cpp",
"code_info/code_info_builder.cpp",
"compile_method.cpp",
"optimizer_run.cpp",
]
}
libarkcompiler_sources += [ "$target_gen_dir/generated/inst_builder_gen.cpp" ]
libarkcompiler_configs = [

View File

@ -18,6 +18,7 @@
#include <cstdint>
#include <limits>
#include <string>
namespace panda::compiler {
constexpr int BITS_PER_BYTE = 8;
@ -58,4 +59,10 @@ constexpr uint32_t MAX_SCALE = 3;
constexpr int MAX_SUCCS_NUM = 2;
} // namespace panda::compiler
// TypeInfoIndex adaption
using TypeInfoIndex = int32_t;
constexpr TypeInfoIndex NO_EXPLICIT_TYPE = 0;
constexpr const std::string_view TSTYPE_ANNO_RECORD_NAME = "_ESTypeAnnotation";
constexpr const std::string_view TSTYPE_ANNO_ELEMENT_NAME = "_TypeOfInstruction";
constexpr auto INVALID_TYPE_INDEX = std::numeric_limits<std::size_t>::max();
#endif // COMPILER_OPTIMIZER_IR_CONSTANTS_H_

View File

@ -44,6 +44,7 @@ enum class ClassType {
class IClassHierarchyAnalysis;
class InlineCachesInterface;
class UnresolvedTypesInterface;
class Inst;
class RuntimeInterface {
public:
@ -907,6 +908,42 @@ public:
return false;
}
// TypeInfoIndex adaption
virtual TypeInfoIndex GetTypeInfoIndexByInstId([[maybe_unused]] size_t id) const
{
return NO_EXPLICIT_TYPE;
}
virtual bool FillInstIdTypePairByPc([[maybe_unused]] size_t id, [[maybe_unused]] int32_t pc)
{
return false;
}
virtual bool HasInsTypeinfo() const
{
return false;
}
virtual bool AddPcTypePair([[maybe_unused]] int32_t pc, [[maybe_unused]] TypeInfoIndex type)
{
return false;
}
virtual bool FillArgTypePairs([[maybe_unused]] std::unordered_map<int32_t, TypeInfoIndex> *map) const
{
return false;
}
virtual bool SetTypeAnnotationIndex([[maybe_unused]] size_t anno_idx, [[maybe_unused]] size_t elem_idx)
{
return false;
}
virtual const std::pair<size_t, size_t> *GetTypeAnnotationIndex() const
{
return nullptr;
}
NO_COPY_SEMANTIC(RuntimeInterface);
NO_MOVE_SEMANTIC(RuntimeInterface);

View File

@ -137,6 +137,12 @@ public:
static void SetParamSpillFill(Graph *graph, ParameterInst *param_inst, size_t num_args, size_t i,
DataType::Type type);
void TryFillInstIdTypePair(size_t id, int32_t pc)
{
ASSERT(GetGraph()->IsBytecodeOptimizer());
ASSERT(GetGraph()->IsDynamicMethod());
GetGraph()->GetRuntime()->FillInstIdTypePairByPc(id, pc);
}
private:
void SyncWithGraph();

View File

@ -118,6 +118,11 @@ templates:
% end
sta: |-
UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), GetDefinitionAcc());
% if inst.properties.include? "dynamic"
if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) {
TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress())));
}
% end
lda: |-
% if inst.mnemonic.include? "null"
UpdateDefinitionAcc(graph_->GetOrCreateNullPtr());
@ -131,6 +136,9 @@ templates:
% else
UpdateDefinitionAcc(FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>()));
% if inst.properties.include? "dynamic"
if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) {
TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress())));
}
BuildCastToAnyNumber(instruction);
% end
% end
@ -139,6 +147,11 @@ templates:
BuildLoadConstArray(instruction);
% else
BuildLoadFromPool<Opcode::<%= inst.opcode =~ /lda_type/ ? 'LoadType' : 'LoadString' %>>(instruction);
% if inst.opcode =~ /lda_str/
if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) {
TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress())));
}
% end
% end
% else
% raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg?
@ -153,6 +166,9 @@ templates:
UpdateDefinitionAcc(FindOrCreateDoubleConstant(imm));
% end
% if inst.properties.include? "dynamic"
if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) {
TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress())));
}
BuildCastToAnyNumber(instruction);
% end
operands: |-
@ -228,6 +244,11 @@ templates:
AddInstruction(jmp_inst);
% else
BuildEcma(instruction);
% if inst.acc.include?("out")
if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) {
TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress())));
}
% end
% end
builtin: |-
BuildBuiltin(instruction);

View File

@ -73,7 +73,6 @@ source_set("libarkfile_static") {
":isa_gen_libarkfile_bytecode_instruction_enum_gen_h",
":isa_gen_libarkfile_file_format_version_h",
":isa_gen_libarkfile_tests_bytecode_emitter_tests_gen_h",
":libarkfile_file_items_gen_inc",
":libarkfile_type_gen_h",
":source_lang_enum_h",
"$ark_root/libpandabase:libarkbase",
@ -108,7 +107,6 @@ source_set("libarkfile_frontend_set_static") {
":isa_gen_libarkfile_bytecode_instruction_enum_gen_h",
":isa_gen_libarkfile_file_format_version_h",
":isa_gen_libarkfile_tests_bytecode_emitter_tests_gen_h",
":libarkfile_file_items_gen_inc",
":libarkfile_type_gen_h",
":source_lang_enum_h",
"$ark_root/libpandabase:libarkbase_frontend_static",
@ -145,14 +143,6 @@ ark_isa_gen("isa_gen_libarkfile") {
requires = [ "pandafile_isapi.rb" ]
}
ark_gen_file("libarkfile_file_items_gen_inc") {
extra_dependencies = [ "$ark_root:concat_plugins_yamls" ]
template_file = "templates/file_items_gen.inc.erb"
data_file = "$target_gen_dir/../plugin_options.yaml"
requires = [ "$ark_root/templates/plugin_options.rb" ]
output_file = "$target_gen_dir/include/file_items_gen.inc"
}
ark_gen_file("source_lang_enum_h") {
extra_dependencies = [ "$ark_root:concat_plugins_yamls" ]
template_file = "templates/source_lang_enum.h.erb"

View File

@ -11,16 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
set(FILE_ITEMS_GEN_INC ${PANDA_BINARY_ROOT}/libpandafile/include/file_items_gen.inc)
panda_gen_file(
DATAFILE ${GEN_PLUGIN_OPTIONS_YAML}
TEMPLATE ${PANDA_ROOT}/libpandafile/templates/file_items_gen.inc.erb
REQUIRES ${PANDA_ROOT}/templates/plugin_options.rb
EXTRA_DEPENDENCIES plugin_options_merge
OUTPUTFILE ${FILE_ITEMS_GEN_INC}
)
set(SOURCE_LANG_ENUM_H ${PANDA_BINARY_ROOT}/libpandafile/include/source_lang_enum.h)
panda_gen_file(
DATAFILE ${GEN_PLUGIN_OPTIONS_YAML}
@ -32,7 +22,6 @@ panda_gen_file(
add_custom_target(arkfile_gen DEPENDS
plugin_options_gen
${FILE_ITEMS_GEN_INC}
${SOURCE_LANG_ENUM_H}
)

View File

@ -23,7 +23,44 @@
namespace panda::panda_file {
#include "file_items_gen.inc"
bool IsDynamicLanguage(panda::panda_file::SourceLang lang)
{
return lang == panda::panda_file::SourceLang::ECMASCRIPT;
}
std::optional<panda::panda_file::SourceLang> LanguageFromString(std::string_view lang)
{
if (lang == "ECMAScript") {
return panda::panda_file::SourceLang::ECMASCRIPT;
}
return panda::panda_file::SourceLang::PANDA_ASSEMBLY;
}
const char *LanguageToString(panda::panda_file::SourceLang lang)
{
if (lang == panda::panda_file::SourceLang::ECMASCRIPT) {
return "ECMAScript";
}
return "PandaAssembly";
}
const char *GetCtorName([[maybe_unused]] panda::panda_file::SourceLang lang)
{
return ".ctor";
}
const char *GetCctorName([[maybe_unused]] panda::panda_file::SourceLang lang)
{
return ".cctor";
}
const char *GetStringClassDescriptor(panda::panda_file::SourceLang lang)
{
if (lang == panda::panda_file::SourceLang::ECMASCRIPT) {
return "Lpanda/JSString;";
}
return "Lpanda/String;";
}
template <class Tag, class Val>
static bool WriteUlebTaggedValue(Writer *writer, Tag tag, Val v)

View File

@ -1,91 +0,0 @@
/**
* Copyright (c) 2021-2022 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.
*/
bool IsDynamicLanguage([[maybe_unused]] panda::panda_file::SourceLang lang)
{
% Common::plugins.each_value do |plugin_opts|
% next unless plugin_opts["language_config"]
% next unless plugin_opts["language_config"]["lang_type"]
if (lang == <%= plugin_opts["lang_enum"] %>) {
return <%= plugin_opts["language_config"]["lang_type"] == "dynamic" %>; //NOLINT(readability-simplify-boolean-expr)
}
% end
return false;
}
std::optional<panda::panda_file::SourceLang> LanguageFromString([[maybe_unused]] std::string_view lang)
{
% Common::plugins.each_value do |plugin_opts|
% next unless plugin_opts["directive_name"]
if (lang == "<%= plugin_opts["directive_name"] %>") {
return <%= plugin_opts["lang_enum"] %>;
}
% end
if (lang == "PandaAssembly") {
return panda::panda_file::SourceLang::PANDA_ASSEMBLY;
}
return {};
}
const char *LanguageToString([[maybe_unused]] panda::panda_file::SourceLang lang)
{
% Common::plugins.each_value do |plugin_opts|
% next unless plugin_opts["directive_name"]
if (lang == <%= plugin_opts["lang_enum"] %>) {
return "<%= plugin_opts["directive_name"] %>";
}
% end
return "PandaAssembly";
}
const char *GetCtorName([[maybe_unused]] panda::panda_file::SourceLang lang)
{
% Common::plugins.each_value do |plugin_opts|
% next unless plugin_opts["ctor_name"]
if (lang == <%= plugin_opts["lang_enum"] %>) {
return "<%= plugin_opts["ctor_name"] %>";
}
% end
return ".ctor";
}
const char *GetCctorName([[maybe_unused]] panda::panda_file::SourceLang lang)
{
% Common::plugins.each_value do |plugin_opts|
% next unless plugin_opts["cctor_name"]
if (lang == <%= plugin_opts["lang_enum"] %>) {
return "<%= plugin_opts["cctor_name"] %>";
}
% end
return ".cctor";
}
const char *GetStringClassDescriptor([[maybe_unused]] panda::panda_file::SourceLang lang)
{
% Common::plugins.each do |plugin_lang, plugin_opts|
% next unless plugin_opts["string_class_descriptor"]
if (lang == <%= plugin_opts["lang_enum"] %>) {
return "<%= plugin_opts["string_class_descriptor"] %>";
}
% end
return "Lpanda/String;";
}