mirror of
https://gitee.com/openharmony/arkcompiler_runtime_core
synced 2024-11-27 00:41:14 +00:00
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:
parent
dce65ed901
commit
1f6508d032
@ -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;
|
||||
|
@ -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_;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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
|
@ -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>());
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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: |-
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user