Remove type system for bytecode optimizer

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9GG52
Test: runtime_core UT, es2abc UT, test262, ets_runtime UT, standalone build

Signed-off-by: huangyu <huangyu76@huawei.com>
Change-Id: Ib233fbf1a5df3e49492f7cc411cab54ed3361ae4
This commit is contained in:
huangyu 2024-04-16 16:10:28 +08:00
parent dce65ed901
commit 1f6508d032
12 changed files with 1 additions and 710 deletions

View File

@ -67,9 +67,6 @@ void BytecodeGen::VisitTryBegin(const compiler::BasicBlock *bb)
bool BytecodeGen::RunImpl()
{
Reserve(function_->ins.size());
TypeInfoComponents 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()));
@ -89,12 +86,6 @@ bool BytecodeGen::RunImpl()
AddLineNumber(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()) {
EmitJump(bb);
@ -110,87 +101,9 @@ bool BytecodeGen::RunImpl()
}
function_->ins = std::move(GetResult());
function_->catch_blocks = catch_blocks_;
if (need_handle_ins_type) {
UpdateTypeInfoIndexAnnotation(&elements);
}
return true;
}
void BytecodeGen::AddTypeInfoIndexForArguments(TypeInfoComponents *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, TypeInfoComponents *elements) const
{
pandasm::LiteralArray::Literal order_tag;
order_tag.tag_ = LiteralTag::TAGVALUE;
order_tag.value_ = static_cast<uint8_t>(LiteralTag::INTEGER);
elements->emplace_back(order_tag);
pandasm::LiteralArray::Literal order_lit;
order_lit.tag_ = LiteralTag::INTEGER;
order_lit.value_ = bit_cast<uint32_t>(order);
elements->emplace_back(order_lit);
pandasm::LiteralArray::Literal type_tag;
type_tag.tag_ = LiteralTag::TAGVALUE;
pandasm::LiteralArray::Literal type_lit;
if (std::holds_alternative<std::string>(type)) {
type_tag.value_ = static_cast<uint8_t>(LiteralTag::LITERALARRAY);
type_lit.tag_ = LiteralTag::LITERALARRAY;
type_lit.value_ = std::get<std::string>(type);
} else {
type_tag.value_ = static_cast<uint8_t>(LiteralTag::BUILTINTYPEINDEX);
type_lit.tag_ = LiteralTag::BUILTINTYPEINDEX;
type_lit.value_ = std::get<BuiltinIndexType>(type);
}
elements->emplace_back(type_tag);
elements->emplace_back(type_lit);
}
void BytecodeGen::AddTypeInfoIndexForIns(int32_t order, size_t id, TypeInfoComponents *elements) const
{
auto type = GetGraph()->GetRuntime()->GetTypeInfoIndexByInstId(id);
if (type != NO_EXPLICIT_TYPE) {
AddOrderAndTypeInfoIndex(order, type, elements);
}
}
void BytecodeGen::UpdateTypeInfoIndexAnnotation(const TypeInfoComponents *elements)
{
#ifndef NDEBUG
LOG(DEBUG, BYTECODE_OPTIMIZER) << "Typeinfo after optimization for function : " << function_->name;
const size_t PAIR_GAP = 4; // 4: tag, order, tag, value, ...
ASSERT(elements->size() % PAIR_GAP == 0);
for (size_t i = 1; i < elements->size(); i += PAIR_GAP) {
auto order = bit_cast<int32_t>(std::get<uint32_t>((*elements)[i].value_));
const auto &element = (*elements)[i + 2]; // 2: gap between order and value
if (element.tag_ == LiteralTag::LITERALARRAY) {
auto type = std::get<std::string>(element.value_);
LOG(DEBUG, BYTECODE_OPTIMIZER) << "[" << order << ", " << type << "], ";
} else {
ASSERT(element.tag_ == LiteralTag::BUILTINTYPEINDEX);
auto type = std::get<BuiltinIndexType>(element.value_);
LOG(DEBUG, BYTECODE_OPTIMIZER) << "[" << order << ", " << type << "], ";
}
}
#endif
const auto &key = *(GetGraph()->GetRuntime()->GetTypeLiteralArrayKey());
auto &litarr_table = GetProgram()->literalarray_table;
ASSERT(litarr_table.find(key) != litarr_table.end());
pandasm::LiteralArray array(*elements);
litarr_table[key] = array;
}
void BytecodeGen::EmitJump(const BasicBlock *bb)
{
BasicBlock *suc_bb = nullptr;

View File

@ -134,18 +134,6 @@ private:
const compiler::BasicBlock *catch_begin, const compiler::BasicBlock *catch_end = nullptr);
void VisitTryBegin(const compiler::BasicBlock *bb);
// TypeInfoIndex typeinfo adaption
using Literal = panda::pandasm::LiteralArray::Literal;
using TypeInfoComponents = std::vector<Literal>;
void AddTypeInfoIndexForArguments(TypeInfoComponents *elements) const;
void AddOrderAndTypeInfoIndex(int32_t order, TypeInfoIndex type, TypeInfoComponents *elements) const;
void AddTypeInfoIndexForIns(int32_t order, size_t id, TypeInfoComponents *elements) const;
void UpdateTypeInfoIndexAnnotation(const TypeInfoComponents *elements);
pandasm::Program *GetProgram() const
{
return program_;
}
private:
pandasm::Function *function_;
const BytecodeOptIrInterface *ir_interface_;

View File

@ -107,80 +107,6 @@ 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 pandasm::Program *prog)
{
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;
}
const auto *key_val = type_elem->GetValue();
ASSERT(key_val != nullptr);
ASSERT(key_val->GetType() == pandasm::Value::Type::LITERALARRAY);
const auto key = key_val->GetAsScalar()->GetValue<std::string>();
adapter->SetTypeLiteralArrayKey(key);
auto array_iter = prog->literalarray_table.find(key);
ASSERT(array_iter != prog->literalarray_table.end());
const auto &array = array_iter->second.literals_;
// 4: size must be multiple of 4 because values consits of tuple of tag, order, tag, type
ASSERT(array.size() % 4 == 0);
size_t i = 1;
while (i < array.size()) {
auto order = bit_cast<int32_t>(std::get<uint32_t>(array[i].value_));
i += 2; // 2: skip tag between order and type
TypeInfoIndex type;
if (array[i].tag_ == panda_file::LiteralTag::LITERALARRAY) {
type = std::get<std::string>(array[i].value_);
} else {
ASSERT(array[i].tag_ == panda_file::LiteralTag::BUILTINTYPEINDEX);
type = std::get<BuiltinIndexType>(array[i].value_);
}
if (order < 0) {
adapter->AddPcTypePair(order, type); // arguments
} else {
order_type_map->emplace(order, type); // instructions
}
i += 2; // 2: skip tag between type and order
}
}
static void BuildMapFromPcToType(const pandasm::Function &function, const compiler::Graph *graph,
compiler::RuntimeInterface::MethodPtr method_ptr, const pandasm::Program *prog)
{
std::unordered_map<int32_t, TypeInfoIndex> tmp_order_type_map;
ExtractTypeInfo(function, graph->GetRuntime(), &tmp_order_type_map, prog);
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;
@ -314,8 +240,6 @@ bool OptimizeFunction(pandasm::Program *prog, const pandasm::AsmEmitter::PandaFi
return false;
}
BuildMapFromPcToType(function, graph, method_ptr, prog);
// build map from pc to pandasm::ins (to re-build line-number info in BytecodeGen)
BuildMapFromPcToIns(function, ir_interface, graph, method_ptr);

View File

@ -147,67 +147,6 @@ public:
return class_name + "::" + method_name;
}
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 IsPcBindType(int32_t pc) const override
{
return pc_type_map_.find(pc) != pc_type_map_.end();
}
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 SetTypeLiteralArrayKey(std::string key) override
{
literalarray_key = key;
return !literalarray_key.empty();
}
const std::string *GetTypeLiteralArrayKey() const override
{
return &literalarray_key;
}
private:
static compiler::DataType::Type ToCompilerType(panda_file::Type type)
{
@ -241,10 +180,6 @@ 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::string literalarray_key;
std::pair<size_t, size_t> anno_elem_idx_ = std::make_pair(INVALID_TYPE_INDEX, INVALID_TYPE_INDEX);
};
} // namespace panda

View File

@ -58,7 +58,6 @@ foreach(file, graph_test_js_files) {
host_unittest_action("BytecodeOptimizerTest") {
module_out_path = module_output_path
sources = [
"bcopt_type_adaption_test.cpp",
"codegen_test.cpp",
"excluded_keys_test.cpp",
"optimize_bytecode_test.cpp",

View File

@ -1,375 +0,0 @@
/*
* 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 <gtest/gtest.h>
#include "assembler/assembly-parser.h"
#include "assembler/meta.h"
#include "bytecode_optimizer/optimize_bytecode.h"
namespace panda::bytecodeopt {
using ArrayValue = panda::pandasm::ArrayValue;
using ScalarValue = panda::pandasm::ScalarValue;
using AnnotationData = panda::pandasm::AnnotationData;
using AnnotationElement = panda::pandasm::AnnotationElement;
using TypeInfoMap = std::unordered_map<int32_t, TypeInfoIndex>;
class TypeAdaptionTest : public testing::Test {
public:
static void SetUpTestCase(void) {}
static void TearDownTestCase(void) {}
void SetUp() {}
void TearDown() {}
TypeInfoMap ExtractTypeinfo(const panda::pandasm::Function &fun, const panda::pandasm::Program &prog) const
{
const auto &annos = fun.metadata->GetAnnotations();
EXPECT_FALSE(annos.empty());
const auto &eles = annos[0].GetElements();
EXPECT_FALSE(eles.empty());
const auto *ele = eles[0].GetValue();
EXPECT_NE(ele, nullptr);
const auto key = ele->GetAsScalar()->GetValue<std::string>();
auto array_liter = prog.literalarray_table.find(key);
EXPECT_NE(array_liter, prog.literalarray_table.end());
const auto &array = array_liter->second.literals_;
// 4: size must be multiple of 4 because values consits of tuple of tag, order, tag, type
EXPECT_EQ(array.size() % 4u, 0u);
TypeInfoMap type_info;
size_t i = 1; // 1: skip tag of order, so start from 1
while (i < array.size()) {
auto order = bit_cast<int32_t>(std::get<uint32_t>(array[i].value_));
i += 2; // 2: skip tag between order and type
TypeInfoIndex type;
if (array[i].tag_ == panda_file::LiteralTag::LITERALARRAY) {
type = std::get<std::string>(array[i].value_);
} else {
EXPECT_EQ(array[i].tag_, panda_file::LiteralTag::BUILTINTYPEINDEX);
type = std::get<BuiltinIndexType>(array[i].value_);
}
type_info.emplace(order, type);
i += 2; // 2: skip tag between order and type
}
return type_info;
}
void CheckTypeExist(const TypeInfoMap &typeinfo, int32_t order, const TypeInfoIndex &type) const
{
auto type_it = typeinfo.find(order);
EXPECT_NE(type_it, typeinfo.end());
EXPECT_EQ(type_it->second, type);
}
void AddTypeinfo(panda::pandasm::LiteralArray &lit_arr, int32_t order, TypeInfoIndex type) const
{
auto &arr = lit_arr.literals_;
panda::pandasm::LiteralArray::Literal order_tag;
order_tag.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
order_tag.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::INTEGER);
arr.emplace_back(order_tag);
panda::pandasm::LiteralArray::Literal order_val;
order_val.tag_ = panda::panda_file::LiteralTag::INTEGER;
order_val.value_ = static_cast<uint32_t>(order);
arr.emplace_back(order_val);
panda::pandasm::LiteralArray::Literal type_tag;
panda::pandasm::LiteralArray::Literal type_val;
type_tag.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
if (std::holds_alternative<uint8_t>(type)) {
type_tag.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::BUILTINTYPEINDEX);
type_val.tag_ = panda::panda_file::LiteralTag::BUILTINTYPEINDEX;
type_val.value_ = std::get<uint8_t>(type);
} else {
EXPECT_TRUE(std::holds_alternative<std::string>(type));
type_tag.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::LITERALARRAY);
type_val.tag_ = panda::panda_file::LiteralTag::LITERALARRAY;
type_val.value_ = std::get<std::string>(type);
}
arr.emplace_back(type_tag);
arr.emplace_back(type_val);
}
void SetTypeAnnotationForFunc(const panda::pandasm::LiteralArray &arr, panda::pandasm::Function &func,
panda::pandasm::Program &program) const
{
auto id = std::to_string(program.literalarray_table.size());
program.literalarray_table.emplace(id, arr);
AnnotationElement element(TSTYPE_ANNO_ELEMENT_NAME, std::make_unique<ScalarValue>(
ScalarValue::Create<panda::pandasm::Value::Type::LITERALARRAY>(id)));
AnnotationData annotation(TSTYPE_ANNO_RECORD_NAME);
annotation.AddElement(std::move(element));
std::vector<AnnotationData> annos;
annos.emplace_back(annotation);
func.metadata->SetAnnotations(std::move(annos));
const auto iterator = program.record_table.find(TSTYPE_ANNO_RECORD_NAME.data());
EXPECT_NE(iterator, program.record_table.end());
iterator->second.metadata->SetAccessFlags(panda::ACC_ANNOTATION);
EXPECT_TRUE(program.record_table.find(TSTYPE_ANNO_RECORD_NAME.data())->second.metadata->IsAnnotation());
}
// add a literalarray as a type
TypeInfoIndex AddAnTypeLiteralArray(panda::pandasm::Program &program) const
{
panda::pandasm::LiteralArray arr;
panda::pandasm::LiteralArray::Literal tag;
tag.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
tag.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::BUILTINTYPEINDEX);
arr.literals_.emplace_back(tag);
panda::pandasm::LiteralArray::Literal val;
val.tag_ = panda::panda_file::LiteralTag::BUILTINTYPEINDEX;
val.value_ = static_cast<uint8_t>(0u);
arr.literals_.emplace_back(val);
const std::string litKey = std::to_string(program.literalarray_table.size());
program.literalarray_table.emplace(litKey, arr);
TypeInfoIndex ret = litKey;
return ret;
}
void EmitAndOptimize(const std::string &abcFileName, panda::pandasm::Program &program) const
{
std::map<std::string, size_t> *statp = nullptr;
panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = &maps;
EXPECT_TRUE(panda::pandasm::AsmEmitter::Emit(abcFileName, program, statp, mapsp, false));
EXPECT_TRUE(panda::bytecodeopt::OptimizeBytecode(&program, mapsp, abcFileName, true));
}
};
HWTEST_F(TypeAdaptionTest, type_adaption_test_001, testing::ext::TestSize.Level1)
{
/* 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, any a3, any a4, any a5) <static> {
mov v5, a5
mov v4, a4
mov v3, a3
mov v2, a2
mov v1, a1
mov v0, a0
ldai 0x64
sta v6
lda v3
sta v9
lda v6
greater 0x0, v9
jeqz jump_label_0
lda v4
return
jump_label_0:
lda v3
sta v9
lda v6
less 0x1, v9
jeqz jump_label_1
lda v5
return
jump_label_1:
lda v4
sta v9
lda v5
add2 0x2, v9
sta v7
lda v7
return
}
)";
panda::pandasm::Parser parser;
auto res = parser.Parse(source);
auto &program = res.Value();
const std::string fun_name = "foo:(any,any,any,any,any,any)";
auto it = program.function_table.find(fun_name);
EXPECT_NE(it, program.function_table.end());
auto &func = it->second;
panda::pandasm::LiteralArray lit_arr;
static const TypeInfoIndex NUM_TYPE = static_cast<uint8_t>(1);
static const TypeInfoIndex STR_TYPE = static_cast<uint8_t>(4);
// set arg type
const auto THIS_TYPE = AddAnTypeLiteralArray(program);
AddTypeinfo(lit_arr, -3, THIS_TYPE); // -3: the arg "this"
AddTypeinfo(lit_arr, -4, NUM_TYPE); // -4: the first arg
AddTypeinfo(lit_arr, -5, STR_TYPE); // -5: the second arg
AddTypeinfo(lit_arr, -6, STR_TYPE); // -6: the third arg
// set ins type
const size_t LDAI_IDX = 6;
EXPECT_EQ(func.ins[LDAI_IDX].opcode, panda::pandasm::Opcode::LDAI);
EXPECT_EQ(func.ins[LDAI_IDX + 1].opcode, panda::pandasm::Opcode::STA);
AddTypeinfo(lit_arr, static_cast<int32_t>(LDAI_IDX + 1), NUM_TYPE);
const size_t ADD_IDX = 27;
EXPECT_EQ(func.ins[ADD_IDX].opcode, panda::pandasm::Opcode::ADD2);
EXPECT_EQ(func.ins[ADD_IDX + 1].opcode, panda::pandasm::Opcode::STA);
int32_t num_invalid = std::count_if(func.ins.begin(), func.ins.begin() + ADD_IDX,
[](const auto &in) { return in.opcode == panda::pandasm::Opcode::INVALID; });
AddTypeinfo(lit_arr, ADD_IDX + 1 - num_invalid, STR_TYPE); // exclude invalid insns because they do not emit
SetTypeAnnotationForFunc(lit_arr, func, program);
EmitAndOptimize("TypeAdaptionTest.abc", program);
// check typeinfo after optimization
it = program.function_table.find(fun_name);
EXPECT_NE(it, program.function_table.end());
const auto &foo = it->second;
const auto typeinfo = ExtractTypeinfo(foo, program);
CheckTypeExist(typeinfo, -3, THIS_TYPE); // -3: the arg "this"
CheckTypeExist(typeinfo, -4, NUM_TYPE); // -4: the first arg
CheckTypeExist(typeinfo, -5, STR_TYPE); // -5: the second arg
CheckTypeExist(typeinfo, -6, STR_TYPE); // -6: the third arg
auto ldai_it = std::find_if(foo.ins.begin(), foo.ins.end(),
[](const auto &in) { return in.opcode == panda::pandasm::Opcode::LDAI; });
EXPECT_NE(ldai_it, foo.ins.end());
const auto opt_ldai_idx = static_cast<size_t>(ldai_it - foo.ins.begin());
EXPECT_EQ(foo.ins[opt_ldai_idx].opcode, panda::pandasm::Opcode::LDAI);
EXPECT_LT(opt_ldai_idx + 1, foo.ins.size());
EXPECT_EQ(foo.ins[opt_ldai_idx + 1].opcode, panda::pandasm::Opcode::STA);
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
auto add_it = std::find_if(foo.ins.begin(), foo.ins.end(),
[](const auto &in) { return in.opcode == panda::pandasm::Opcode::ADD2; });
EXPECT_NE(add_it, foo.ins.end());
const auto opt_add_idx = static_cast<size_t>(add_it - foo.ins.begin());
EXPECT_EQ(foo.ins[opt_add_idx].opcode, panda::pandasm::Opcode::ADD2);
EXPECT_LT(opt_add_idx + 1, foo.ins.size());
EXPECT_NE(foo.ins[opt_add_idx + 1].opcode, panda::pandasm::Opcode::STA);
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 add2 as it does not have sta
}
HWTEST_F(TypeAdaptionTest, unconditional_jump_case_test_001, testing::ext::TestSize.Level1)
{
/* ts source code
function foo(results: number) {
for (let i = 0; i < 1; i++) {
results *= i;
}
let s:number = results + 2;
return s;
}
*/
const auto source = R"(
.language ECMAScript
.record _ESTypeAnnotation <external>
.function any foo(any a0, any a1, any a2, any a3) <static> {
mov v0, a0
mov v1, a1
mov v2, a2
mov v3, a3
ldai 0x0
sta v6
jump_label_1:
lda v6
sta v7
ldai 0x1
less 0x0, v7
jeqz jump_label_0
lda v3
sta v7
lda v6
mul2 0x1, v7
sta v3
lda v6
sta v7
lda v7
inc 0x2
sta v6
lda v7
tonumeric 0x3
jmp jump_label_1
jump_label_0:
lda v3
sta v6
ldai 0x2
add2 0x4, v6
sta v4
lda v4
return
}
)";
panda::pandasm::Parser parser;
auto res = parser.Parse(source);
auto &program = res.Value();
const std::string fun_name = "foo:(any,any,any,any)";
auto it = program.function_table.find(fun_name);
EXPECT_NE(it, program.function_table.end());
auto &func = it->second;
panda::pandasm::LiteralArray lit_arr;
static const TypeInfoIndex NUM_TYPE = static_cast<uint8_t>(1);
static const TypeInfoIndex STR_TYPE = static_cast<uint8_t>(4);
// set arg type
const auto THIS_TYPE = AddAnTypeLiteralArray(program);
AddTypeinfo(lit_arr, -3, THIS_TYPE); // -3: the arg "this"
AddTypeinfo(lit_arr, -4, NUM_TYPE); // -4: the first arg
// set ins type
const size_t ADD_IDX = 29;
EXPECT_EQ(func.ins[ADD_IDX].opcode, panda::pandasm::Opcode::ADD2);
EXPECT_EQ(func.ins[ADD_IDX + 1].opcode, panda::pandasm::Opcode::STA);
int32_t num_invalid = std::count_if(func.ins.begin(), func.ins.begin() + ADD_IDX,
[](const auto &in) { return in.opcode == panda::pandasm::Opcode::INVALID; });
AddTypeinfo(lit_arr, ADD_IDX + 1 - num_invalid, STR_TYPE); // exclude invalid insns because they do not emit
SetTypeAnnotationForFunc(lit_arr, func, program);
EmitAndOptimize("TypeAdaptionTest_UnconditionalJump.abc", program);
// check typeinfo after optimization
it = program.function_table.find(fun_name);
EXPECT_NE(it, program.function_table.end());
const auto &foo = it->second;
const auto typeinfo = ExtractTypeinfo(foo, program);
CheckTypeExist(typeinfo, -3, THIS_TYPE); // -3: the arg "this"
CheckTypeExist(typeinfo, -4, NUM_TYPE); // -4: the first arg
auto add_it = std::find_if(foo.ins.begin(), foo.ins.end(),
[](const auto &in) { return in.opcode == panda::pandasm::Opcode::ADD2; });
EXPECT_NE(add_it, foo.ins.end());
const auto opt_add_idx = static_cast<size_t>(add_it - foo.ins.begin());
EXPECT_EQ(foo.ins[opt_add_idx].opcode, panda::pandasm::Opcode::ADD2);
EXPECT_TRUE(opt_add_idx + 1 < foo.ins.size());
EXPECT_NE(foo.ins[opt_add_idx + 1].opcode, panda::pandasm::Opcode::STA);
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 add2 as it does not have sta
}
} // namespace panda::bytecodeopt::test

View File

@ -526,13 +526,6 @@ HWTEST_F(CodegenTest, codegen_test_015, TestSize.Level1)
&ir_interface, &prog, &status](Graph* graph) {
EXPECT_NE(graph, nullptr);
int32_t pc = -1; // -1: It's a random number
uint8_t id1 = 2; // 2: It's a random number
TypeInfoIndex type = static_cast<BuiltinIndexType>(id1);
graph->GetRuntime()->AddPcTypePair(pc, type);
size_t id = 13; // 13: It's a random number
graph->GetRuntime()->FillInstIdTypePairByPc(id, pc);
for (auto bb : graph->GetBlocksRPO()) {
EXPECT_NE(bb, nullptr);
@ -542,10 +535,6 @@ HWTEST_F(CodegenTest, codegen_test_015, TestSize.Level1)
}
}
EXPECT_TRUE(graph->RunPass<compiler::Cleanup>());
LiteralArray lit;
const auto &key = *(graph->GetRuntime()->GetTypeLiteralArrayKey());
prog.literalarray_table[key] = lit;
EXPECT_FALSE(graph->RunPass<compiler::Cleanup>());
EXPECT_FALSE(graph->RunPass<panda::compiler::ValNum>());
EXPECT_TRUE(graph->RunPass<panda::compiler::Lowering>());

View File

@ -18,7 +18,6 @@
#include <cstdint>
#include <limits>
#include <string>
#include <variant>
namespace panda::compiler {
@ -71,12 +70,4 @@ constexpr uint32_t MAX_SCALE = 3;
constexpr int MAX_SUCCS_NUM = 2;
} // namespace panda::compiler
// TypeInfoIndex adaption
using BuiltinIndexType = uint8_t;
using TypeInfoIndex = std::variant<BuiltinIndexType, std::string>;
const TypeInfoIndex NO_EXPLICIT_TYPE = static_cast<BuiltinIndexType>(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

@ -149,47 +149,6 @@ public:
#include <ecma_intrinsics_enum.inl>
// TypeInfoIndex adaption
virtual TypeInfoIndex GetTypeInfoIndexByInstId([[maybe_unused]] size_t id) const
{
return NO_EXPLICIT_TYPE;
}
virtual bool IsPcBindType([[maybe_unused]] int32_t pc) const
{
return false;
}
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 SetTypeLiteralArrayKey([[maybe_unused]] std::string key)
{
return false;
}
virtual const std::string *GetTypeLiteralArrayKey() const
{
return nullptr;
}
NO_COPY_SEMANTIC(RuntimeInterface);
NO_MOVE_SEMANTIC(RuntimeInterface);

View File

@ -121,12 +121,6 @@ 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 UpdateDefsForCatch();
void UpdateDefsForLoopHead();

View File

@ -116,11 +116,6 @@ 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.acc_and_operands[1].imm?
% if inst.mnemonic == "ldai"
@ -132,19 +127,11 @@ 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
% elsif inst.acc_and_operands[1].id?
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
% else
% raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg?
UpdateDefinitionAcc(GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>()));
@ -153,9 +140,6 @@ templates:
auto imm = bit_cast<double>(instruction->GetImm<<%=inst.get_format%>, 0>());
UpdateDefinitionAcc(FindOrCreateDoubleConstant(imm));
% if inst.properties.include? "dynamic"
if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) {
TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress())));
}
BuildCastToAnyNumber(instruction);
% end
operands: |-
@ -218,10 +202,6 @@ templates:
AddInstruction(jmp_inst);
% else
BuildEcma(instruction);
auto pc = static_cast<int>(GetPc(instruction->GetAddress()));
if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod() && GetGraph()->GetRuntime()->IsPcBindType(pc)) {
TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), pc);
}
% end
nop: |-
unimplemented: |-

View File

@ -966,7 +966,7 @@ HWTEST_F(CompilerInstTest, compiler_inst_test_034, TestSize.Level1)
/**
* @tc.name: compiler_inst_test_035
* @tc.desc: Verify the HasInsTypeinfo function.
* @tc.desc: Verify the ResolveOffsetByIndex function.
* @tc.type: FUNC
* @tc.require: issueNumber
*/
@ -992,18 +992,12 @@ HWTEST_F(CompilerInstTest, compiler_inst_test_035, TestSize.Level1)
EXPECT_EQ(interface.GetMethodRegistersCount(method), 0);
EXPECT_EQ(interface.GetClassNameFromMethod(method), "UnknownClass");
EXPECT_EQ(interface.GetMethodName(method), "UnknownMethod");
EXPECT_FALSE(interface.SetTypeLiteralArrayKey("test"));
EXPECT_EQ(interface.GetMethodCode(method), nullptr);
EXPECT_EQ(interface.GetMethodCodeSize(method), 0);
EXPECT_EQ(interface.GetMethodSourceLanguage(method), SourceLanguage::PANDA_ASSEMBLY);
EXPECT_EQ(interface.GetClass(method), nullptr);
EXPECT_EQ(interface.GetMethodFullName(method, true), "UnknownMethod");
EXPECT_EQ(interface.GetClassIdForMethod(method), 0);
EXPECT_EQ(interface.GetTypeInfoIndexByInstId(0), NO_EXPLICIT_TYPE);
EXPECT_FALSE(interface.IsPcBindType(0));
EXPECT_FALSE(interface.FillInstIdTypePairByPc(0, 0));
EXPECT_EQ(interface.GetTypeLiteralArrayKey(), nullptr);
EXPECT_FALSE(interface.HasInsTypeinfo());
});
EXPECT_TRUE(status);
}