mirror of
https://gitee.com/openharmony/arkcompiler_runtime_core
synced 2024-10-06 21:34:16 +00:00
ISA-Refactor for ecmascript
ISA-Refactor for ecmascript Issue: I5QWXL Signed-off-by: qiuyu <qiuyu22@huawei.com>
This commit is contained in:
parent
5071676ae9
commit
46397a5114
@ -95,7 +95,7 @@ def assembler_signature(group, is_jump)
|
||||
o.type, o.name = is_jump ? ['const std::string &', 'label'] : ['int64_t', o.name]
|
||||
end
|
||||
elsif o.name.start_with?('id')
|
||||
o.type, o.name = ['const std::string &', 'id']
|
||||
o.type, o.name = ['const std::string &', o.name]
|
||||
else
|
||||
o.type = 'uint16_t'
|
||||
end
|
||||
|
@ -733,78 +733,45 @@ bool AsmEmitter::AddAnnotations(T *item, ItemContainer *container, const Annotat
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void AddBytecodeIndexDependencies(MethodItem *method, const Ins &insn,
|
||||
const std::unordered_map<std::string, T *> &items)
|
||||
static void AddDependencyByIndex(MethodItem *method, const Ins &insn,
|
||||
const std::unordered_map<std::string, T *> &items, size_t idx = 0)
|
||||
{
|
||||
ASSERT(!insn.ids.empty());
|
||||
|
||||
for (const auto &id : insn.ids) {
|
||||
auto it = items.find(id);
|
||||
ASSERT(it != items.cend());
|
||||
|
||||
auto *item = it->second;
|
||||
ASSERT(item->GetIndexType() != panda_file::IndexType::NONE);
|
||||
method->AddIndexDependency(item);
|
||||
}
|
||||
}
|
||||
|
||||
static void IncreaseInsLiteralArrayIdByBase(panda::pandasm::Ins &insn, size_t base)
|
||||
{
|
||||
switch (insn.opcode) {
|
||||
case panda::pandasm::Opcode::ECMA_CREATEARRAYWITHBUFFER:
|
||||
case panda::pandasm::Opcode::ECMA_CREATEOBJECTWITHBUFFER:
|
||||
case panda::pandasm::Opcode::ECMA_CREATEOBJECTHAVINGMETHOD:
|
||||
case panda::pandasm::Opcode::ECMA_DEFINECLASSWITHBUFFER:
|
||||
insn.imms[0] = std::get<int64_t>(insn.imms[0]) + static_cast<int64_t>(base);
|
||||
return;
|
||||
case panda::pandasm::Opcode::ECMA_NEWLEXENVWITHNAMEDYN:
|
||||
insn.imms[1] = std::get<int64_t>(insn.imms[1]) + static_cast<int64_t>(base);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
ASSERT(idx < insn.ids.size());
|
||||
const auto &id = insn.ids[idx];
|
||||
auto it = items.find(id);
|
||||
ASSERT(it != items.cend());
|
||||
auto *item = it->second;
|
||||
ASSERT(item->GetIndexType() != panda_file::IndexType::NONE);
|
||||
method->AddIndexDependency(item);
|
||||
}
|
||||
|
||||
static void AddBytecodeIndexDependencies(MethodItem *method, const Function &func,
|
||||
const AsmEmitter::AsmEntityCollections &entities, uint32_t base)
|
||||
{
|
||||
for (const auto &insn : func.ins) {
|
||||
// correct literal array id, need to remove after isa refactoring
|
||||
if (base != 0) {
|
||||
IncreaseInsLiteralArrayIdByBase(const_cast<pandasm::Ins &>(insn), base);
|
||||
}
|
||||
|
||||
if (insn.opcode == Opcode::INVALID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (insn.opcode == Opcode::DEFINECLASSWITHBUFFER) {
|
||||
AddDependencyByIndex(method, insn, entities.method_items);
|
||||
AddDependencyByIndex(method, insn, entities.literalarray_items, 1);
|
||||
continue;
|
||||
}
|
||||
if (insn.HasFlag(InstFlags::METHOD_ID)) {
|
||||
AddBytecodeIndexDependencies(method, insn, entities.method_items);
|
||||
AddDependencyByIndex(method, insn, entities.method_items);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (insn.HasFlag(InstFlags::FIELD_ID)) {
|
||||
AddBytecodeIndexDependencies(method, insn, entities.field_items);
|
||||
if (insn.HasFlag(InstFlags::STRING_ID)) {
|
||||
AddDependencyByIndex(method, insn, entities.string_items);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (insn.HasFlag(InstFlags::TYPE_ID)) {
|
||||
AddBytecodeIndexDependencies(method, insn, entities.class_items);
|
||||
continue;
|
||||
if (insn.HasFlag(InstFlags::LITERALARRAY_ID)) {
|
||||
AddDependencyByIndex(method, insn, entities.literalarray_items);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &catch_block : func.catch_blocks) {
|
||||
if (catch_block.exception_record.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = entities.class_items.find(catch_block.exception_record);
|
||||
ASSERT(it != entities.class_items.cend());
|
||||
auto *item = it->second;
|
||||
ASSERT(item->GetIndexType() != panda_file::IndexType::NONE);
|
||||
method->AddIndexDependency(item);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -1239,6 +1206,7 @@ bool AsmEmitter::CreateMethodItem(ItemContainer *items, AsmEmitter::AsmEntityCol
|
||||
method = items->CreateItem<ForeignMethodItem>(area, method_name, proto, access_flags);
|
||||
} else {
|
||||
method = area->AddMethod(method_name, proto, access_flags, params);
|
||||
method->SetFunctionKind(func.GetFunctionKind());
|
||||
}
|
||||
} else {
|
||||
if (!func.metadata->IsForeign()) {
|
||||
@ -1248,7 +1216,7 @@ bool AsmEmitter::CreateMethodItem(ItemContainer *items, AsmEmitter::AsmEntityCol
|
||||
method = items->CreateItem<ForeignMethodItem>(foreign_area, method_name, proto, access_flags);
|
||||
}
|
||||
entities.method_items.insert({mangled_name, method});
|
||||
if (!func.metadata->IsForeign() && func.metadata->HasImplementation()) {
|
||||
if (!func.metadata->IsForeign()) {
|
||||
if (!func.source_file.empty()) {
|
||||
items->GetOrCreateStringItem(func.source_file);
|
||||
}
|
||||
@ -1379,22 +1347,6 @@ void AsmEmitter::SetCodeAndDebugInfo(ItemContainer *items, MethodItem *method, c
|
||||
method->SetDebugInfo(debug_info);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void AsmEmitter::SetMethodSourceLang(const Program &program, MethodItem *method, const Function &func,
|
||||
const std::string &name)
|
||||
{
|
||||
std::string record_name = GetOwnerName(name);
|
||||
if (record_name.empty()) {
|
||||
method->SetSourceLang(func.language);
|
||||
return;
|
||||
}
|
||||
|
||||
auto &rec = program.record_table.find(record_name)->second;
|
||||
if (rec.language != func.language) {
|
||||
method->SetSourceLang(func.language);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool AsmEmitter::AddMethodAndParamsAnnotations(ItemContainer *items, const Program &program,
|
||||
const AsmEmitter::AsmEntityCollections &entities, MethodItem *method,
|
||||
@ -1442,12 +1394,10 @@ bool AsmEmitter::MakeFunctionDebugInfoAndAnnotations(ItemContainer *items, const
|
||||
|
||||
auto *method = static_cast<MethodItem *>(Find(entities.method_items, name));
|
||||
|
||||
if (func.metadata->HasImplementation()) {
|
||||
SetCodeAndDebugInfo(items, method, func, emit_debug_info);
|
||||
AddBytecodeIndexDependencies(method, func, entities, GetBase());
|
||||
}
|
||||
SetCodeAndDebugInfo(items, method, func, emit_debug_info);
|
||||
AddBytecodeIndexDependencies(method, func, entities, GetBase());
|
||||
|
||||
SetMethodSourceLang(program, method, func, name);
|
||||
method->SetSourceLang(func.language);
|
||||
|
||||
if (!AddMethodAndParamsAnnotations(items, program, entities, method, func)) {
|
||||
return false;
|
||||
@ -1520,7 +1470,7 @@ bool AsmEmitter::EmitFunctions(ItemContainer *items, const Program &program,
|
||||
for (const auto &f : program.function_table) {
|
||||
const auto &[name, func] = f;
|
||||
|
||||
if (func.metadata->IsForeign() || !func.metadata->HasImplementation()) {
|
||||
if (func.metadata->IsForeign()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1578,8 +1528,44 @@ bool AsmEmitter::MakeItemsForSingleProgram(ItemContainer *items, const Program &
|
||||
return true;
|
||||
}
|
||||
|
||||
// temp plan for ic slot number, should be deleted after method refactoring
|
||||
static void MakeSlotNumberRecord(Program *prog)
|
||||
{
|
||||
static const std::string SLOT_NUMBER = "_ESSlotNumberAnnotation";
|
||||
pandasm::Record record(SLOT_NUMBER, pandasm::extensions::Language::ECMASCRIPT);
|
||||
record.metadata->SetAccessFlags(panda::ACC_ANNOTATION);
|
||||
prog->record_table.emplace(SLOT_NUMBER, std::move(record));
|
||||
}
|
||||
|
||||
// temp plan for ic slot number, should be deleted after method refactoring
|
||||
static void MakeSlotNumberAnnotation(Program *prog)
|
||||
{
|
||||
static const std::string SLOT_NUMBER = "_ESSlotNumberAnnotation";
|
||||
static const std::string ELEMENT_NAME = "SlotNumber";
|
||||
for (auto &[name, func] : prog->function_table) {
|
||||
for (const auto &an : func.metadata->GetAnnotations()) {
|
||||
if (an.GetName() == SLOT_NUMBER) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
pandasm::AnnotationData anno(SLOT_NUMBER);
|
||||
pandasm::AnnotationElement ele(ELEMENT_NAME, std::make_unique<pandasm::ScalarValue>(
|
||||
pandasm::ScalarValue::Create<pandasm::Value::Type::U32>(static_cast<uint32_t>(func.GetSlotsNum()))));
|
||||
anno.AddElement(std::move(ele));
|
||||
std::vector<pandasm::AnnotationData> annos;
|
||||
annos.emplace_back(anno);
|
||||
func.metadata->AddAnnotations(annos);
|
||||
}
|
||||
}
|
||||
|
||||
bool AsmEmitter::EmitPrograms(const std::string &filename, const std::vector<Program *> &progs, bool emit_debug_info)
|
||||
{
|
||||
ASSERT(!progs.empty());
|
||||
for (auto *prog : progs) {
|
||||
MakeSlotNumberRecord(prog);
|
||||
MakeSlotNumberAnnotation(prog);
|
||||
}
|
||||
|
||||
auto items = ItemContainer {};
|
||||
auto primitive_types = CreatePrimitiveTypes(&items);
|
||||
auto entities = AsmEmitter::AsmEntityCollections {};
|
||||
@ -1624,6 +1610,8 @@ bool AsmEmitter::EmitPrograms(const std::string &filename, const std::vector<Pro
|
||||
bool AsmEmitter::Emit(ItemContainer *items, const Program &program, PandaFileToPandaAsmMaps *maps, bool emit_debug_info,
|
||||
panda::panda_file::pgo::ProfileOptimizer *profile_opt)
|
||||
{
|
||||
MakeSlotNumberRecord(const_cast<Program *>(&program));
|
||||
MakeSlotNumberAnnotation(const_cast<Program *>(&program));
|
||||
auto primitive_types = CreatePrimitiveTypes(items);
|
||||
|
||||
auto entities = AsmEmitter::AsmEntityCollections {};
|
||||
@ -1734,7 +1722,7 @@ bool Function::Emit(BytecodeEmitter &emitter, panda_file::MethodItem *method,
|
||||
const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
|
||||
const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
|
||||
const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
|
||||
const std::unordered_map<std::string_view, panda_file::StringItem *> &strings,
|
||||
const std::unordered_map<std::string, panda_file::StringItem *> &strings,
|
||||
const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays) const
|
||||
{
|
||||
auto labels = std::unordered_map<std::string_view, panda::Label> {};
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
std::unordered_map<std::string, panda_file::BaseMethodItem *> method_items;
|
||||
std::unordered_map<std::string, panda_file::BaseFieldItem *> field_items;
|
||||
std::unordered_map<std::string, panda_file::BaseClassItem *> class_items;
|
||||
std::unordered_map<std::string_view, panda_file::StringItem *> string_items;
|
||||
std::unordered_map<std::string, panda_file::StringItem *> string_items;
|
||||
std::unordered_map<std::string, panda_file::LiteralArrayItem *> literalarray_items;
|
||||
};
|
||||
|
||||
@ -124,8 +124,6 @@ private:
|
||||
const AsmEntityCollections &entities);
|
||||
static void SetCodeAndDebugInfo(panda_file::ItemContainer *items, panda_file::MethodItem *method,
|
||||
const Function &func, bool emit_debug_info);
|
||||
static void SetMethodSourceLang(const Program &program, panda_file::MethodItem *method, const Function &func,
|
||||
const std::string &name);
|
||||
static bool AddMethodAndParamsAnnotations(panda_file::ItemContainer *items, const Program &program,
|
||||
const AsmEmitter::AsmEntityCollections &entities,
|
||||
panda_file::MethodItem *method, const Function &func);
|
||||
|
@ -86,6 +86,28 @@ struct Function {
|
||||
Type return_type;
|
||||
SourceLocation body_location;
|
||||
std::optional<FileLocation> file_location;
|
||||
panda::panda_file::FunctionKind function_kind = panda::panda_file::FunctionKind::NONE;
|
||||
size_t slots_num = 0;
|
||||
|
||||
void SetSlotsNum(size_t num)
|
||||
{
|
||||
slots_num = num;
|
||||
}
|
||||
|
||||
size_t GetSlotsNum() const
|
||||
{
|
||||
return slots_num;
|
||||
}
|
||||
|
||||
void SetFunctionKind(panda::panda_file::FunctionKind kind)
|
||||
{
|
||||
function_kind = kind;
|
||||
}
|
||||
|
||||
panda::panda_file::FunctionKind GetFunctionKind() const
|
||||
{
|
||||
return function_kind;
|
||||
}
|
||||
|
||||
void SetInsDebug(const std::vector<debuginfo::Ins> &ins_debug)
|
||||
{
|
||||
@ -133,7 +155,7 @@ struct Function {
|
||||
const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
|
||||
const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
|
||||
const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
|
||||
const std::unordered_map<std::string_view, panda_file::StringItem *> &strings,
|
||||
const std::unordered_map<std::string, panda_file::StringItem *> &strings,
|
||||
const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays) const;
|
||||
|
||||
size_t GetLineNumber(size_t i) const;
|
||||
@ -170,7 +192,7 @@ struct Function {
|
||||
|
||||
bool HasImplementation() const
|
||||
{
|
||||
return !metadata->IsForeign() && metadata->HasImplementation();
|
||||
return !metadata->IsForeign();
|
||||
}
|
||||
|
||||
bool IsParameter(uint32_t reg_number) const
|
||||
|
@ -59,7 +59,7 @@ enum InstFlags {
|
||||
|
||||
constexpr int INVALID_REG_IDX = -1;
|
||||
|
||||
constexpr size_t MAX_NUMBER_OF_SRC_REGS = 5; // TODO(mbolshov): auto-generate
|
||||
constexpr size_t MAX_NUMBER_OF_SRC_REGS = 4; // TODO(mbolshov): auto-generate
|
||||
|
||||
constexpr InstFlags operator|(InstFlags a, InstFlags b)
|
||||
{
|
||||
@ -111,7 +111,7 @@ struct Ins {
|
||||
const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
|
||||
const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
|
||||
const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
|
||||
const std::unordered_map<std::string_view, panda_file::StringItem *> &strings,
|
||||
const std::unordered_map<std::string, panda_file::StringItem *> &strings,
|
||||
const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays,
|
||||
const std::unordered_map<std::string_view, panda::Label> &labels) const;
|
||||
|
||||
|
@ -698,23 +698,13 @@ void Parser::ParseResetFunctionTable()
|
||||
Error::ErrorType::ERR_BAD_ID_FUNCTION, "", k.second.file_location->bound_left,
|
||||
k.second.file_location->bound_right, k.second.file_location->whole_line);
|
||||
SetError();
|
||||
} else if (k.second.HasImplementation() != k.second.body_presence) {
|
||||
context_.err = Error("Inconsistency of the definition of the function and its metadata.",
|
||||
k.second.file_location->line_number, Error::ErrorType::ERR_BAD_DEFINITION_FUNCTION, "",
|
||||
k.second.file_location->bound_left, k.second.file_location->bound_right,
|
||||
k.second.file_location->whole_line);
|
||||
SetError();
|
||||
} else {
|
||||
for (auto insn_it = k.second.ins.begin(); insn_it != k.second.ins.end(); ++insn_it) {
|
||||
bool is_calli = insn_it->opcode == Opcode::CALLI_DYN || insn_it->opcode == Opcode::CALLI_DYN_SHORT ||
|
||||
insn_it->opcode == Opcode::CALLI_DYN_RANGE;
|
||||
if (is_calli || !(insn_it->IsCall() || insn_it->IsCallRange())) {
|
||||
if (!(insn_it->IsCall() || insn_it->IsCallRange())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_initobj = insn_it->opcode == Opcode::INITOBJ || insn_it->opcode == Opcode::INITOBJ_SHORT ||
|
||||
insn_it->opcode == Opcode::INITOBJ_RANGE;
|
||||
size_t diff = is_initobj ? 0 : 1;
|
||||
size_t diff = 1;
|
||||
auto func_name = insn_it->ids[0];
|
||||
|
||||
if (!IsSignatureOrMangled(func_name)) {
|
||||
@ -987,7 +977,7 @@ Expected<Program, Error> Parser::ParseAfterMainLoop(const std::string &file_name
|
||||
}
|
||||
|
||||
for (auto &func : program_.function_table) {
|
||||
if (func.second.metadata->HasImplementation()) {
|
||||
if (func.second.HasImplementation()) {
|
||||
func.second.source_file = file_name;
|
||||
}
|
||||
}
|
||||
|
@ -466,11 +466,6 @@ bool RecordMetadata::IsRuntimeTypeAnnotation() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FunctionMetadata::HasImplementation() const
|
||||
{
|
||||
return !(ACC_ABSTRACT & GetAccessFlags()) && !(ACC_NATIVE & GetAccessFlags());
|
||||
}
|
||||
|
||||
bool FunctionMetadata::IsCtor() const
|
||||
{
|
||||
return GetAttribute("ctor");
|
||||
|
@ -562,8 +562,6 @@ private:
|
||||
|
||||
class FunctionMetadata : public ItemMetadata {
|
||||
public:
|
||||
virtual bool HasImplementation() const;
|
||||
|
||||
virtual bool IsCtor() const;
|
||||
|
||||
virtual bool IsCctor() const;
|
||||
|
@ -21,7 +21,7 @@ bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method,
|
||||
const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
|
||||
const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
|
||||
const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
|
||||
const std::unordered_map<std::string_view, panda_file::StringItem *> &strings,
|
||||
const std::unordered_map<std::string, panda_file::StringItem *> &strings,
|
||||
const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays,
|
||||
const std::unordered_map<std::string_view, panda::Label>& labels) const {
|
||||
if (!IsValidToEmit()) {
|
||||
@ -47,6 +47,8 @@ bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method,
|
||||
% ops = []
|
||||
% nr = 0
|
||||
% ni = 0
|
||||
% property_idx_start = 0
|
||||
% num_id = 0
|
||||
% insn.operands.each do |op|
|
||||
% if op.reg?
|
||||
% ops << "#{regs}[#{nr}]"
|
||||
@ -66,50 +68,58 @@ bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method,
|
||||
% end
|
||||
% ni += 1
|
||||
% elsif op.id?
|
||||
% if insn.properties.include?('method_id')
|
||||
% ops << 'methods.find(ids[0])->second->GetIndex(method)'
|
||||
% elsif insn.properties.include?('field_id')
|
||||
% ops << 'fields.find(ids[0])->second->GetIndex(method)'
|
||||
% elsif insn.properties.include?('type_id')
|
||||
% ops << 'classes.find(ids[0])->second->GetIndex(method)'
|
||||
% elsif insn.properties.include?('string_id')
|
||||
% ops << 'strings.find(ids[0])->second->GetOffset()'
|
||||
% elsif insn.properties.include?('literalarray_id')
|
||||
% ops << 'static_cast<uint32_t>(literalarrays.find(ids[0])->second->GetOffset())'
|
||||
% else
|
||||
% raise "Unexpected ID type"
|
||||
% id_properties = insn.properties.slice(property_idx_start, insn.properties.length - property_idx_start)
|
||||
% id_properties.each_with_index do |prop, prop_idx|
|
||||
% if prop == 'method_id'
|
||||
% ops << "methods.find(ids[#{num_id}])->second->GetIndex(method)"
|
||||
% property_idx_start += prop_idx + 1
|
||||
% num_id += 1
|
||||
% break
|
||||
% elsif prop == 'string_id'
|
||||
% ops << "strings.find(ids[#{num_id}])->second->GetIndex(method)"
|
||||
% property_idx_start += prop_idx + 1
|
||||
% num_id += 1
|
||||
% break
|
||||
% elsif prop == 'literalarray_id'
|
||||
% ops << "literalarrays.find(ids[#{num_id}])->second->GetIndex(method)"
|
||||
% property_idx_start += prop_idx + 1
|
||||
% num_id += 1
|
||||
% break
|
||||
% else
|
||||
% next
|
||||
% end
|
||||
% end
|
||||
% else
|
||||
% raise "Unexpected operand type"
|
||||
% end
|
||||
% end
|
||||
% if insn.call? && insn.properties.include?('method_id')
|
||||
% ops << ops.shift
|
||||
% end
|
||||
% ops
|
||||
% end
|
||||
case Opcode::<%= insn.asm_token %>: {
|
||||
% if insn.properties.include?('method_id')
|
||||
if ((ids.size() == 0) || (methods.find(ids[0]) == methods.cend())) {
|
||||
return false;
|
||||
}
|
||||
% elsif insn.properties.include?('field_id')
|
||||
if ((ids.size() == 0) || (fields.find(ids[0]) == fields.cend())) {
|
||||
return false;
|
||||
}
|
||||
% elsif insn.properties.include?('type_id')
|
||||
if ((ids.size() == 0) || (classes.find(ids[0]) == classes.cend())) {
|
||||
return false;
|
||||
}
|
||||
% elsif insn.properties.include?('string_id')
|
||||
if ((ids.size() == 0) || (strings.find(ids[0]) == strings.cend())) {
|
||||
return false;
|
||||
}
|
||||
% elsif insn.jump?
|
||||
% if insn.jump?
|
||||
if ((ids.size() == 0) || (labels.find(ids[0]) == labels.cend())) {
|
||||
return false;
|
||||
}
|
||||
% end
|
||||
% num_id = 0
|
||||
% insn.properties.each do |prop|
|
||||
% if prop == 'method_id'
|
||||
if ((ids.size() == 0) || (methods.find(ids[<%= num_id %>]) == methods.cend())) {
|
||||
return false;
|
||||
}
|
||||
% num_id += 1
|
||||
% elsif prop == 'string_id'
|
||||
if ((ids.size() == 0) || (strings.find(ids[<%= num_id %>]) == strings.cend())) {
|
||||
return false;
|
||||
}
|
||||
% num_id += 1
|
||||
% elsif prop == 'literalarray_id'
|
||||
if ((ids.size() == 0) || (literalarrays.find(ids[<%= num_id %>]) == literalarrays.cend())) {
|
||||
return false;
|
||||
}
|
||||
% num_id += 1
|
||||
% end
|
||||
% end
|
||||
% regs_num = 0
|
||||
% imms_num = 0
|
||||
% insn.operands.each do |op|
|
||||
|
@ -311,174 +311,6 @@ end
|
||||
# Wrap all `insn` declaration in a function to call from template
|
||||
# (because Panda::instructions is initialized only in templates)
|
||||
def call_me_from_template
|
||||
%w[and xor or shl shr].each do |op|
|
||||
visit(op.capitalize) do
|
||||
switch(type,
|
||||
[case_switch(i32_types, if_acc?(r(0)),
|
||||
[case_true("#{op}2", r(1)),
|
||||
case_false("#{op}", r(0), r(1))]),
|
||||
case_(i64_types, "#{op}2.64", r(1))]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
visit('AShr') do
|
||||
switch(type,
|
||||
[case_switch(i32_types, if_acc?(r(0)),
|
||||
[case_true("ashr2", r(1)),
|
||||
case_false("ashr", r(0), r(1))]),
|
||||
case_(i64_types, 'ashr2.64', r(1))]
|
||||
)
|
||||
end
|
||||
|
||||
%w[add sub mul div mod].each do |op|
|
||||
visit(op.capitalize) do
|
||||
switch(type,
|
||||
[case_switch(i32_types, if_acc?(r(0)),
|
||||
[case_true("#{op}2", r(1)),
|
||||
case_false("#{op}", r(0), r(1))]),
|
||||
case_(i64_types, "#{op}2.64", r(1)),
|
||||
case_(f32_types, "f#{op}2", r(1)),
|
||||
case_(f64_types, "f#{op}2.64", r(1))]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
visit('AddI') do
|
||||
switch(type,
|
||||
[case_switch(i32_types, if_inci?,
|
||||
[case_true('inci', r(0), imm),
|
||||
case_false('addi', imm)])]
|
||||
)
|
||||
end
|
||||
|
||||
visit('SubI') do
|
||||
switch(type,
|
||||
[case_switch(i32_types, if_inci?,
|
||||
[case_true('inci', r(0), "-(#{imm})"),
|
||||
case_false('subi', imm)])]
|
||||
)
|
||||
end
|
||||
|
||||
visit('Not') do
|
||||
switch(type,
|
||||
[case_(i32_types, 'not'),
|
||||
case_(i64_types, 'not.64')]
|
||||
)
|
||||
end
|
||||
|
||||
visit('Neg') do
|
||||
switch(type,
|
||||
[case_(i32_types, 'neg'),
|
||||
case_(i64_types, 'neg.64'),
|
||||
case_(f32_types, 'fneg'),
|
||||
case_(f64_types, 'fneg.64')]
|
||||
)
|
||||
end
|
||||
|
||||
visit('Cmp') do
|
||||
switch('inst->GetOperandsType()',
|
||||
[case_(%w[UINT8 UINT16 UINT32], 'ucmp', r(1)),
|
||||
case_(%w[INT64], 'cmp.64', r(1)),
|
||||
case_(%w[UINT64], 'ucmp.64', r(1)),
|
||||
case_switch(['FLOAT32'], if_fcmpg?,
|
||||
[case_true('fcmpg', r(1)),
|
||||
case_false('fcmpl', r(1))]),
|
||||
case_switch(['FLOAT64'], if_fcmpg?,
|
||||
[case_true('fcmpg.64', r(1)),
|
||||
case_false('fcmpl.64', r(1))])]
|
||||
)
|
||||
end
|
||||
|
||||
visit('ReturnVoid') do
|
||||
plain('return.void')
|
||||
end
|
||||
|
||||
visit('Throw') do
|
||||
plain('throw', r(0))
|
||||
end
|
||||
|
||||
visit('NullPtr') do
|
||||
switch(if_acc?(dst_r),
|
||||
[case_true('lda.null'),
|
||||
case_false('mov.null', dst_r)]
|
||||
)
|
||||
end
|
||||
|
||||
visit('LoadConstArray') do
|
||||
plain('lda.const', dst_r, literalarray_id)
|
||||
end
|
||||
|
||||
visit('NewArray') do
|
||||
plain('newarr', dst_r, r(1), type_id)
|
||||
end
|
||||
|
||||
visit('LenArray') do
|
||||
plain('lenarr', r(0))
|
||||
end
|
||||
|
||||
visit('LoadArray') do
|
||||
switch(type,
|
||||
[case_(['INT8'], 'ldarr.8', r(0)),
|
||||
case_(['UINT8'], 'ldarru.16', r(0)),
|
||||
case_(['INT16'], 'ldarr.16', r(0)),
|
||||
case_(['UINT16'], 'ldarru.16', r(0)),
|
||||
case_(['INT32', 'UINT32'], 'ldarr', r(0)),
|
||||
case_(['INT64', 'UINT64'], 'ldarr.64', r(0)),
|
||||
case_(['REFERENCE'], 'ldarr.obj', r(0)),
|
||||
case_(['FLOAT32'], 'fldarr.32', r(0)),
|
||||
case_(['FLOAT64'], 'fldarr.64', r(0))]
|
||||
)
|
||||
end
|
||||
|
||||
visit('StoreArray') do
|
||||
switch(type,
|
||||
[case_(['INT8', 'UINT8'], 'starr.8', r(0), r(1)),
|
||||
case_(['INT16', 'UINT16'], 'starr.16', r(0), r(1)),
|
||||
case_(['INT32', 'UINT32'], 'starr', r(0), r(1)),
|
||||
case_(['INT64', 'UINT64'], 'starr.64', r(0), r(1)),
|
||||
case_(['REFERENCE'], 'starr.obj', r(0), r(1)),
|
||||
case_(['FLOAT32'], 'fstarr.32', r(0), r(1)),
|
||||
case_(['FLOAT64'], 'fstarr.64', r(0), r(1))]
|
||||
)
|
||||
end
|
||||
|
||||
visit('LoadStatic') do
|
||||
switch(type,
|
||||
[case_(i32_types, 'ldstatic', field_id),
|
||||
case_(i64_types, 'ldstatic.64', field_id),
|
||||
case_(f32_types, 'ldstatic', field_id),
|
||||
case_(f64_types, 'ldstatic.64', field_id),
|
||||
case_(['REFERENCE'], 'ldstatic.obj', field_id)]
|
||||
)
|
||||
end
|
||||
|
||||
visit('StoreStatic') do
|
||||
switch(type,
|
||||
[case_(i32_types, 'ststatic', field_id),
|
||||
case_(i64_types, 'ststatic.64', field_id),
|
||||
case_(f32_types, 'ststatic', field_id),
|
||||
case_(f64_types, 'ststatic.64', field_id),
|
||||
case_(['REFERENCE'], 'ststatic.obj', field_id)]
|
||||
)
|
||||
end
|
||||
|
||||
visit('CheckCast') do
|
||||
plain('checkcast', type_id)
|
||||
end
|
||||
|
||||
visit('IsInstance') do
|
||||
plain('isinstance', type_id)
|
||||
end
|
||||
|
||||
visit('LoadType') do
|
||||
plain('lda.type', type_id)
|
||||
end
|
||||
|
||||
visit('NewObject') do
|
||||
plain('newobj', dst_r, type_id)
|
||||
end
|
||||
|
||||
# Empty visitors for IR instructions we want to ignore
|
||||
# (Add missing IRs on demand)
|
||||
%w[NullCheck BoundsCheck ZeroCheck NegativeCheck SafePoint
|
||||
@ -488,12 +320,4 @@ def call_me_from_template
|
||||
empty
|
||||
end
|
||||
end
|
||||
|
||||
%w[MulI DivI ModI ShlI ShrI AShrI AndI OrI XorI].each do |op|
|
||||
visit(op) do
|
||||
switch(type,
|
||||
[case_(i32_types, "#{op.downcase}", imm)]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -33,13 +33,8 @@ using compiler::BasicBlock;
|
||||
using compiler::Inst;
|
||||
using compiler::Opcode;
|
||||
|
||||
void DoLdaObj(compiler::Register reg, std::vector<pandasm::Ins> &result);
|
||||
void DoLda(compiler::Register reg, std::vector<pandasm::Ins> &result);
|
||||
void DoLda64(compiler::Register reg, std::vector<pandasm::Ins> &result);
|
||||
void DoSta(compiler::Register reg, std::vector<pandasm::Ins> &result);
|
||||
void DoSta64(compiler::Register reg, std::vector<pandasm::Ins> &result);
|
||||
void DoLdaDyn(compiler::Register reg, std::vector<pandasm::Ins> &result);
|
||||
void DoStaDyn(compiler::Register reg, std::vector<pandasm::Ins> &result);
|
||||
|
||||
class BytecodeGen : public compiler::Optimization, public compiler::GraphVisitor {
|
||||
public:
|
||||
@ -119,8 +114,6 @@ public:
|
||||
static void IfImm64(GraphVisitor *v, Inst *inst_base);
|
||||
static void VisitIntrinsic(GraphVisitor *v, Inst *inst_base);
|
||||
static void CallHandler(GraphVisitor *visitor, Inst *inst);
|
||||
static void VisitStoreObject(GraphVisitor *v, Inst *inst_base);
|
||||
static void VisitLoadObject(GraphVisitor *v, Inst *inst_base);
|
||||
static void VisitLoadString(GraphVisitor *v, Inst *inst_base);
|
||||
static void VisitReturn(GraphVisitor *v, Inst *inst_base);
|
||||
|
||||
|
@ -49,6 +49,14 @@ public:
|
||||
return std::string(it->second);
|
||||
}
|
||||
|
||||
virtual std::string GetLiteralArrayByOffset(uint32_t offset) const
|
||||
{
|
||||
auto it = maps_->literalarrays.find(offset);
|
||||
ASSERT(it != maps_->strings.cend());
|
||||
|
||||
return std::string(it->second);
|
||||
}
|
||||
|
||||
std::optional<std::string> GetLiteralArrayIdByOffset(uint32_t offset) const
|
||||
{
|
||||
ASSERT(prog_ != nullptr);
|
||||
|
@ -402,7 +402,7 @@ bool OptimizePandaFile(pandasm::Program *prog, const pandasm::AsmEmitter::PandaF
|
||||
|
||||
panda_file::ClassDataAccessor cda {*pfile, record_id};
|
||||
cda.EnumerateMethods([prog, maps, is_dynamic, &result](panda_file::MethodDataAccessor &mda) {
|
||||
if (!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative()) {
|
||||
if (!mda.IsExternal()) {
|
||||
result = OptimizeFunction(prog, maps, mda, is_dynamic) && result;
|
||||
}
|
||||
});
|
||||
|
@ -26,18 +26,19 @@ static bool IsIntrinsicRange(Inst *inst)
|
||||
}
|
||||
#ifdef ENABLE_BYTECODE_OPT
|
||||
switch (inst->CastToIntrinsic()->GetIntrinsicId()) {
|
||||
#ifdef ARK_INTRINSIC_SET
|
||||
case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_CALLI_RANGE_DYN:
|
||||
case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_CALLI_THIS_RANGE_DYN:
|
||||
case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_NEWOBJ_DYNRANGE:
|
||||
case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_SUPER_CALL:
|
||||
#else
|
||||
case compiler::RuntimeInterface::IntrinsicId::ECMA_CALLIRANGEDYN_PREF_IMM16_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::ECMA_CALLITHISRANGEDYN_PREF_IMM16_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::ECMA_NEWOBJDYNRANGE_PREF_IMM16_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::ECMA_SUPERCALL_PREF_IMM16_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::ECMA_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8:
|
||||
#endif
|
||||
case compiler::RuntimeInterface::IntrinsicId::CALLRANGE_IMM8_IMM8_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::WIDE_CALLRANGE_PREF_IMM16_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::CALLTHISRANGE_IMM8_IMM8_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::NEWOBJRANGE_IMM8_IMM8_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::NEWOBJRANGE_IMM16_IMM8_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::WIDE_NEWOBJRANGE_PREF_IMM16_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::SUPERCALLARROWRANGE_IMM8_IMM8_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::CREATEOBJECTWITHEXCLUDEDKEYS_IMM8_V8_V8:
|
||||
case compiler::RuntimeInterface::IntrinsicId::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -49,10 +50,6 @@ static bool IsIntrinsicRange(Inst *inst)
|
||||
static bool CanHoldRange(Inst *inst)
|
||||
{
|
||||
switch (inst->GetOpcode()) {
|
||||
case compiler::Opcode::CallStatic:
|
||||
case compiler::Opcode::CallVirtual:
|
||||
case compiler::Opcode::InitObject:
|
||||
return true;
|
||||
case compiler::Opcode::Intrinsic:
|
||||
return IsIntrinsicRange(inst);
|
||||
default:
|
||||
@ -70,10 +67,6 @@ static compiler::Register CalculateNumNeededRangeTemps(const compiler::Graph *gr
|
||||
continue;
|
||||
}
|
||||
auto nargs = inst->GetInputsCount() - (inst->RequireState() ? 1 : 0);
|
||||
if (inst->GetOpcode() == compiler::Opcode::InitObject) {
|
||||
ASSERT(nargs > 0);
|
||||
nargs -= 1; // exclude LoadAndInitClass
|
||||
}
|
||||
if (ret < nargs) {
|
||||
if (nargs > MAX_NUM_NON_RANGE_ARGS || IsIntrinsicRange(inst)) {
|
||||
ret = nargs;
|
||||
@ -634,6 +627,5 @@ void RegEncoder::VisitLoadString([[maybe_unused]] GraphVisitor *v, [[maybe_unuse
|
||||
void RegEncoder::VisitReturn([[maybe_unused]] GraphVisitor *v, [[maybe_unused]] Inst *inst) {}
|
||||
void RegEncoder::VisitCatchPhi([[maybe_unused]] GraphVisitor *v, [[maybe_unused]] Inst *inst) {}
|
||||
void RegEncoder::VisitCastValueToAnyType([[maybe_unused]] GraphVisitor *v, [[maybe_unused]] Inst *inst) {}
|
||||
|
||||
#include "generated/check_width.cpp"
|
||||
} // namespace panda::bytecodeopt
|
||||
|
@ -46,6 +46,11 @@ public:
|
||||
return panda_file_.ResolveMethodIndex(MethodCast(parent_method), index).GetOffset();
|
||||
}
|
||||
|
||||
uint32_t ResolveOffsetByIndex(MethodPtr parent_method, uint16_t index) const override
|
||||
{
|
||||
return panda_file_.ResolveOffsetByIndex(MethodCast(parent_method), index).GetOffset();
|
||||
}
|
||||
|
||||
FieldId ResolveFieldIndex(MethodPtr parent_method, FieldIndex index) const override
|
||||
{
|
||||
return panda_file_.ResolveFieldIndex(MethodCast(parent_method), index).GetOffset();
|
||||
@ -103,7 +108,7 @@ public:
|
||||
{
|
||||
panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
|
||||
|
||||
ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative());
|
||||
ASSERT(!mda.IsExternal());
|
||||
panda_file::CodeDataAccessor cda(panda_file_, mda.GetCodeId().value());
|
||||
|
||||
return cda.GetNumArgs();
|
||||
@ -126,7 +131,7 @@ public:
|
||||
{
|
||||
panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
|
||||
|
||||
ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative());
|
||||
ASSERT(!mda.IsExternal());
|
||||
panda_file::CodeDataAccessor cda(panda_file_, mda.GetCodeId().value());
|
||||
|
||||
return cda.GetNumVregs();
|
||||
@ -136,7 +141,7 @@ public:
|
||||
{
|
||||
panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
|
||||
|
||||
ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative());
|
||||
ASSERT(!mda.IsExternal());
|
||||
panda_file::CodeDataAccessor cda(panda_file_, mda.GetCodeId().value());
|
||||
|
||||
return cda.GetInstructions();
|
||||
@ -146,7 +151,7 @@ public:
|
||||
{
|
||||
panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
|
||||
|
||||
ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative());
|
||||
ASSERT(!mda.IsExternal());
|
||||
panda_file::CodeDataAccessor cda(panda_file_, mda.GetCodeId().value());
|
||||
|
||||
return cda.GetCodeSize();
|
||||
@ -156,7 +161,7 @@ public:
|
||||
{
|
||||
panda_file::MethodDataAccessor mda(panda_file_, MethodCast(method));
|
||||
|
||||
ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative());
|
||||
ASSERT(!mda.IsExternal());
|
||||
|
||||
auto source_lang = mda.GetSourceLang();
|
||||
ASSERT(source_lang.has_value());
|
||||
|
@ -185,6 +185,7 @@ ohos_shared_library("libarkcompiler") {
|
||||
":irtoc_builder_cpp",
|
||||
":irtoc_generate_ir_inline",
|
||||
":isa_gen_libarkcompiler_inst_builder_gen_cpp",
|
||||
":libarkcompiler_ecma_intrinsics_enum_inl",
|
||||
":libarkcompiler_generate_ecma_inl",
|
||||
":libarkcompiler_intrinsics_gen_inl_can_encode_builtin_inl",
|
||||
":libarkcompiler_intrinsics_gen_inl_generate_operations_intrinsic_graph_inl",
|
||||
@ -256,6 +257,7 @@ ohos_static_library("libarkcompiler_frontend_static") {
|
||||
":irtoc_builder_cpp",
|
||||
":irtoc_generate_ir_inline",
|
||||
":isa_gen_libarkcompiler_inst_builder_gen_cpp",
|
||||
":libarkcompiler_ecma_intrinsics_enum_inl",
|
||||
":libarkcompiler_generate_ecma_inl",
|
||||
":libarkcompiler_intrinsics_gen_inl_can_encode_builtin_inl",
|
||||
":libarkcompiler_intrinsics_gen_inl_generate_operations_intrinsic_graph_inl",
|
||||
@ -333,7 +335,10 @@ ark_gen("libarkcompiler_intrinsics_gen_inl") {
|
||||
}
|
||||
|
||||
ark_isa_gen("libarkcompiler") {
|
||||
template_files = [ "generate_ecma.inl.erb" ]
|
||||
template_files = [
|
||||
"generate_ecma.inl.erb",
|
||||
"ecma_intrinsics_enum.inl.erb",
|
||||
]
|
||||
sources = "optimizer/templates"
|
||||
requires = [ "$ark_root//assembler/asm_isapi.rb" ]
|
||||
destination = "$target_gen_dir/generated"
|
||||
|
@ -61,6 +61,8 @@ public:
|
||||
using MethodIndex = uint16_t;
|
||||
using FieldIndex = uint16_t;
|
||||
using TypeIndex = uint16_t;
|
||||
using StringIndex = uint16_t;
|
||||
using LiteralArrayIndex = uint16_t;
|
||||
|
||||
static const uintptr_t RESOLVE_STRING_AOT_COUNTER_LIMIT = PANDA_32BITS_HEAP_START_ADDRESS;
|
||||
|
||||
@ -102,6 +104,12 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual uint32_t ResolveOffsetByIndex([[maybe_unused]] MethodPtr parent_method,
|
||||
[[maybe_unused]] uint16_t index) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual FieldId ResolveFieldIndex([[maybe_unused]] MethodPtr parent_method, [[maybe_unused]] FieldIndex index) const
|
||||
{
|
||||
return 0;
|
||||
|
@ -1333,7 +1333,7 @@ void InstBuilder::BuildLoadFromPool(const BytecodeInstruction *bc_inst)
|
||||
} else {
|
||||
// NOLINTNEXTLINE(readability-magic-numbers)
|
||||
static_assert(opcode == Opcode::LoadString);
|
||||
type_id = bc_inst->GetId(0).AsFileId().GetOffset();
|
||||
type_id = GetRuntime()->ResolveOffsetByIndex(GetGraph()->GetMethod(), bc_inst->GetId(0).AsIndex());
|
||||
inst = GetGraph()->CreateInstLoadString(DataType::REFERENCE, GetPc(bc_inst->GetAddress()));
|
||||
}
|
||||
inst->SetTypeId(type_id);
|
||||
|
@ -158,13 +158,8 @@ templates:
|
||||
UpdateDefinitionAcc(GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>()));
|
||||
% end
|
||||
fldai: |-
|
||||
% if inst.mnemonic == "fldai"
|
||||
auto imm = bit_cast<float>(instruction->GetImm<<%=inst.get_format%>, 0>());
|
||||
UpdateDefinitionAcc(FindOrCreateFloatConstant(imm));
|
||||
% else
|
||||
auto imm = bit_cast<double>(instruction->GetImm<<%=inst.get_format%>, 0>());
|
||||
UpdateDefinitionAcc(FindOrCreateDoubleConstant(imm));
|
||||
% end
|
||||
% if inst.properties.include? "dynamic"
|
||||
if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) {
|
||||
TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress())));
|
||||
|
@ -449,7 +449,7 @@ BasicBlock *IrBuilder::GetBlockToJump(BytecodeInstruction *inst, size_t pc)
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BYTECODE_OPT
|
||||
if (inst->GetOpcode() == BytecodeInstruction::Opcode::ECMA_RETURNUNDEFINED_PREF_NONE) {
|
||||
if (inst->GetOpcode() == BytecodeInstruction::Opcode::RETURNUNDEFINED) {
|
||||
return GetGraph()->GetEndBlock();
|
||||
}
|
||||
#endif
|
||||
|
20
compiler/optimizer/templates/ecma_intrinsics_enum.inl.erb
Normal file
20
compiler/optimizer/templates/ecma_intrinsics_enum.inl.erb
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Autogenerated file -- DO NOT EDIT!
|
||||
|
||||
% Panda.instructions.select{|x| x.namespace == "ecmascript"}.each do |insn|
|
||||
<%= insn.opcode.upcase %>,
|
||||
% end
|
@ -34,19 +34,15 @@ void panda::bytecodeopt::BytecodeGen::VisitEcma(panda::compiler::GraphVisitor *v
|
||||
% next if inst.properties.include?("jump")
|
||||
% opcode = inst.opcode.upcase
|
||||
% params_arr = inst.operands
|
||||
#ifdef ARK_INTRINSIC_SET
|
||||
case compiler::RuntimeInterface::IntrinsicId::<%= intrinsic_name %>: {
|
||||
#else
|
||||
% group.each do |i|
|
||||
% intr_id = i.opcode.upcase
|
||||
case compiler::RuntimeInterface::IntrinsicId::<%= intr_id %>:
|
||||
% end
|
||||
{
|
||||
#endif // ARK_INTRINSIC_SET
|
||||
% if inst.acc.include?("in")
|
||||
auto acc_src = inst->GetSrcReg(inst->GetInputsCount() - 2);
|
||||
if (acc_src != compiler::ACC_REG_ID) {
|
||||
DoLdaDyn(acc_src, enc->result_);
|
||||
DoLda(acc_src, enc->result_);
|
||||
}
|
||||
% end
|
||||
% params_str = ""
|
||||
@ -61,16 +57,21 @@ void panda::bytecodeopt::BytecodeGen::VisitEcma(panda::compiler::GraphVisitor *v
|
||||
% vreg_index = vreg_index + 1
|
||||
% input_index = input_index + 1
|
||||
% elsif param.id?
|
||||
% if inst.properties.include?("method_id")
|
||||
% if param.method_id?
|
||||
ASSERT(inst->HasImms() && inst->GetImms().size() > <%= imm_index %>); // NOLINTNEXTLINE(readability-container-size-empty)
|
||||
auto ir_id<%= id_index %> = static_cast<uint32_t>(inst->GetImms()[<%= imm_index %>]);
|
||||
auto bc_id<%= id_index %> = enc->ir_interface_->GetMethodIdByOffset(ir_id<%= id_index %>);
|
||||
% params_str = params_str + "bc_id#{id_index}, "
|
||||
% elsif inst.properties.include?("string_id")
|
||||
% elsif param.string_id?
|
||||
ASSERT(inst->HasImms() && inst->GetImms().size() > <%= imm_index %>); // NOLINTNEXTLINE(readability-container-size-empty)
|
||||
auto ir_id<%= id_index %> = static_cast<uint32_t>(inst->GetImms()[<%= imm_index %>]);
|
||||
auto bc_id<%= id_index %> = enc->ir_interface_->GetStringIdByOffset(ir_id<%= id_index %>);
|
||||
% params_str = params_str + "bc_id#{id_index}, "
|
||||
% elsif param.literalarray_id?
|
||||
ASSERT(inst->HasImms() && inst->GetImms().size() > <%= imm_index %>); // NOLINTNEXTLINE(readability-container-size-empty)
|
||||
auto ir_id<%= id_index %> = static_cast<uint32_t>(inst->GetImms()[<%= imm_index %>]);
|
||||
auto bc_id<%= id_index %> = enc->ir_interface_->GetLiteralArrayByOffset(ir_id<%= id_index %>);
|
||||
% params_str = params_str + "bc_id#{id_index}, "
|
||||
% end
|
||||
% id_index = id_index + 1
|
||||
% imm_index = imm_index + 1
|
||||
@ -93,7 +94,7 @@ void panda::bytecodeopt::BytecodeGen::VisitEcma(panda::compiler::GraphVisitor *v
|
||||
% if inst.acc.include?("out")
|
||||
auto acc_dst = inst->GetDstReg();
|
||||
if (acc_dst != compiler::ACC_REG_ID) {
|
||||
DoStaDyn(inst->GetDstReg(), enc->result_);
|
||||
DoSta(inst->GetDstReg(), enc->result_);
|
||||
}
|
||||
% end
|
||||
break;
|
||||
|
@ -81,8 +81,17 @@ def get_type(type)
|
||||
'f64[]' => 'DataType::FLOAT64',
|
||||
'ref[]' => 'DataType::REFERENCE',
|
||||
'none' => 'DataType::NO_TYPE'}
|
||||
raise "Unknown type #{type}" if @type_map[type].nil?
|
||||
@type_map[type]
|
||||
return 'DataType::ANY' if @type_map[type].nil?
|
||||
# raise "Unknown type #{type}" if @type_map[type].nil?
|
||||
return @type_map[type]
|
||||
end
|
||||
|
||||
def get_template_by_inst(inst)
|
||||
if (inst.namespace == "ecmascript")
|
||||
return "ecma"
|
||||
else
|
||||
return get_template(inst.stripped_mnemonic)
|
||||
end
|
||||
end
|
||||
|
||||
def get_template(mn)
|
||||
@ -92,7 +101,7 @@ def get_template(mn)
|
||||
/^return.*/ => "return",
|
||||
/^[uf]?cmp/ => "cmp",
|
||||
/^[ifu][813264]{1,2}to[ifu][813264]{1,2}$/ => "cast",
|
||||
/^j(eq|ne|lt|gt|le|ge)z?$/ => "if",
|
||||
/^j(eq|ne|lt|gt|le|ge|stricteq|nstricteq)(z|null|undefined)?$/ => "if",
|
||||
/^jmp.*/ => "jump",
|
||||
/(fdiv|fmod|add|sub|mul|and|or|xor|ashr|shr|shl|neg|not)[2i]?$/ => "binop",
|
||||
/^(div|mod)u?[2i]?$/ => "binop_z",
|
||||
@ -138,6 +147,8 @@ def get_cc(inst)
|
||||
return 'ConditionCode::CC_GT' if inst.opcode.start_with? 'jgt'
|
||||
return 'ConditionCode::CC_LE' if inst.opcode.start_with? 'jle'
|
||||
return 'ConditionCode::CC_GE' if inst.opcode.start_with? 'jge'
|
||||
return 'ConditionCode::CC_EQ' if inst.opcode.start_with? 'jstricteq'
|
||||
return 'ConditionCode::CC_NE' if inst.opcode.start_with? 'jnstricteq'
|
||||
raise 'get_cc: wrong opcode #{inst.opcode}'
|
||||
end
|
||||
|
||||
@ -159,7 +170,7 @@ namespace panda::compiler {
|
||||
void InstBuilder::BuildInstruction(const BytecodeInstruction* instruction) {
|
||||
switch(instruction->GetOpcode()) {
|
||||
% Panda::instructions.each_with_index do |inst, idx|
|
||||
% tmpl = inst.mnemonic.include?('polymorphic') ? 'unimplemented' : get_template(inst.stripped_mnemonic)
|
||||
% tmpl = inst.mnemonic.include?('polymorphic') ? 'unimplemented' : get_template_by_inst(inst)
|
||||
// NOLINTNEXTLINE(bugprone-branch-clone)
|
||||
case BytecodeInstruction::Opcode::<%= inst.opcode.upcase %>: {
|
||||
% if tmpl == 'unimplemented'
|
||||
@ -292,7 +303,7 @@ void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInstruction* bc_inst) // N
|
||||
switch (bc_inst->GetOpcode()) {
|
||||
% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst|
|
||||
% opc = inst.opcode.upcase
|
||||
% name = opc.split('_')[1]
|
||||
% name = opc
|
||||
% acc_read = inst.acc.include?("in")
|
||||
% acc_write = inst.acc.include?("out")
|
||||
% ret_type = acc_write ? "compiler::DataType::ANY" : "compiler::DataType::VOID"
|
||||
@ -315,9 +326,9 @@ void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInstruction* bc_inst) // N
|
||||
% end
|
||||
% params_arr = inst.operands
|
||||
% format = "BytecodeInstruction::Format::" + inst.format.pretty.upcase
|
||||
% range_should_exclude_last = name == "NEWOBJDYNRANGE" || name == "SUPERCALL" || name == "CREATEOBJECTWITHEXCLUDEDKEYS"
|
||||
% is_range_call = name == "CALLIRANGEDYN" || name == "CALLITHISRANGEDYN" || range_should_exclude_last
|
||||
% need_newtarget = name == "SUPERCALLSPREAD" || name == "SUPERCALL"
|
||||
% range_should_exclude_last = (name.include? "NEWOBJRANGE") || (name.include? "SUPERCALLTHISRANGE") || (name.include? "CREATEOBJECTWITHEXCLUDEDKEYS") || (name.include? "SUPERCALLARROWRANGE") || (name.include? "CALLRANGE")
|
||||
% is_range_call = (name.include? "CALLTHISRANGE") || range_should_exclude_last
|
||||
% need_newtarget = (name.include? "SUPERCALLSPREAD") || (name.include? "SUPERCALL")
|
||||
% num_vregs = params_arr.select{|b| b.reg?}.length
|
||||
% num_imms = params_arr.select{|b| b.imm?}.length
|
||||
% num_ids = params_arr.select{|b| b.id?}.length
|
||||
@ -329,8 +340,9 @@ void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInstruction* bc_inst) // N
|
||||
% if need_newtarget
|
||||
% num_inputs = num_inputs + 1
|
||||
% end
|
||||
% has_ic_slot = inst.properties.include?('ic_slot') || inst.properties.include?('jit_ic_slot')
|
||||
% if is_range_call
|
||||
size_t args_count = <%= num_inputs %>U + static_cast<size_t>(bc_inst->GetImm<<%= format %>, 0>());
|
||||
size_t args_count = <%= num_inputs %>U + static_cast<size_t>(bc_inst->GetImm<<%= format %>, <%= has_ic_slot ? 1 : 0 %>>());
|
||||
% else
|
||||
size_t args_count {<%= num_inputs %>U};
|
||||
% end
|
||||
@ -355,7 +367,6 @@ void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInstruction* bc_inst) // N
|
||||
% imm_index = 0
|
||||
% vreg_index = 0
|
||||
% id16_index = 0
|
||||
% id32_index = 0
|
||||
auto inst_save_state = CreateSaveState(Opcode::SaveState, GetPc(bc_inst->GetAddress()));
|
||||
AddInstruction(inst_save_state);
|
||||
% params_arr.each do |param|
|
||||
@ -376,17 +387,19 @@ void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInstruction* bc_inst) // N
|
||||
% vreg_index = vreg_index + 1
|
||||
% elsif param.id?
|
||||
% if inst.properties.include?("method_id")
|
||||
auto m_idx<%= id16_index %> = bc_inst->template GetId<<%= format %>>().AsRawValue();
|
||||
if (GetGraph()->IsBytecodeOptimizer()) {
|
||||
m_idx<%= id16_index %> = GetRuntime()->ResolveMethodIndex(GetGraph()->GetMethod(), m_idx<%= id16_index %>);
|
||||
}
|
||||
auto m_idx<%= id16_index %> = bc_inst->template GetId<<%= format %>, <%= id16_index %>>().AsRawValue();
|
||||
m_idx<%= id16_index %> = GetRuntime()->ResolveOffsetByIndex(GetGraph()->GetMethod(), m_idx<%= id16_index %>);
|
||||
inst->AddImm(GetGraph()->GetAllocator(), m_idx<%= id16_index %>);
|
||||
% id16_index = id16_index + 1
|
||||
% elsif inst.properties.include?("string_id")
|
||||
auto string_id<%= id32_index %> = bc_inst->template GetId<<%= format %>>().AsFileId().GetOffset();
|
||||
inst->AddImm(GetGraph()->GetAllocator(), string_id<%= id32_index %>);
|
||||
% id32_index = id32_index + 1
|
||||
auto string_id<%= id16_index %> = bc_inst->template GetId<<%= format %>, <%= id16_index %>>().AsRawValue();
|
||||
string_id<%= id16_index %> = GetRuntime()->ResolveOffsetByIndex(GetGraph()->GetMethod(), string_id<%= id16_index %>);
|
||||
inst->AddImm(GetGraph()->GetAllocator(), string_id<%= id16_index %>);
|
||||
% elsif inst.properties.include?("literalarray_id")
|
||||
auto literalarray_id<%= id16_index %> = bc_inst->template GetId<<%= format %>, <%= id16_index %>>().AsRawValue();
|
||||
literalarray_id<%= id16_index %> = GetRuntime()->ResolveOffsetByIndex(GetGraph()->GetMethod(), literalarray_id<%= id16_index %>);
|
||||
inst->AddImm(GetGraph()->GetAllocator(), literalarray_id<%= id16_index %>);
|
||||
% end
|
||||
% id16_index = id16_index + 1
|
||||
% end
|
||||
% end
|
||||
% if need_newtarget
|
||||
@ -401,8 +414,9 @@ void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInstruction* bc_inst) // N
|
||||
}
|
||||
% end
|
||||
% if is_range_call
|
||||
% range_reg_idx = name == "CREATEOBJECTWITHEXCLUDEDKEYS" ? 1 : 0
|
||||
% num_actual_vregs = range_should_exclude_last ? "imm0" : "imm0 + 1"
|
||||
% range_reg_idx = (name.include? "CREATEOBJECTWITHEXCLUDEDKEYS") ? 1 : 0
|
||||
% imm_arg_num = has_ic_slot ? 'imm1' : 'imm0'
|
||||
% num_actual_vregs = range_should_exclude_last ? imm_arg_num : imm_arg_num + " + 1"
|
||||
size_t start_reg = bc_inst->GetVReg<<%= format %>, <%= range_reg_idx %>>();
|
||||
for (uint32_t i = 1; i < <%= num_actual_vregs %>; ++i) {
|
||||
auto input = GetDefinition(start_reg + i);
|
||||
|
@ -21,6 +21,7 @@
|
||||
% end
|
||||
|
||||
enum class IntrinsicId {
|
||||
#include "ecma_intrinsics_enum.inl"
|
||||
% Compiler::intrinsics.select{ |x| !x.is_irtoc? }.each do |intrinsic|
|
||||
<%= intrinsic.entrypoint_name %>,
|
||||
% end
|
||||
@ -34,179 +35,4 @@ enum class IntrinsicId {
|
||||
% Compiler::intrinsics.select(&:is_irtoc?).each do |intrinsic|
|
||||
<%= intrinsic.entrypoint_name %>,
|
||||
% end
|
||||
|
||||
ECMA_LDNAN_PREF_NONE,
|
||||
ECMA_LDINFINITY_PREF_NONE,
|
||||
ECMA_LDGLOBALTHIS_PREF_NONE,
|
||||
ECMA_LDUNDEFINED_PREF_NONE,
|
||||
ECMA_LDNULL_PREF_NONE,
|
||||
ECMA_LDSYMBOL_PREF_NONE,
|
||||
ECMA_LDGLOBAL_PREF_NONE,
|
||||
ECMA_LDTRUE_PREF_NONE,
|
||||
ECMA_LDFALSE_PREF_NONE,
|
||||
ECMA_THROWDYN_PREF_NONE,
|
||||
ECMA_RETHROWDYN_PREF_NONE,
|
||||
ECMA_TYPEOFDYN_PREF_NONE,
|
||||
ECMA_LDLEXENVDYN_PREF_NONE,
|
||||
ECMA_POPLEXENVDYN_PREF_NONE,
|
||||
ECMA_GETUNMAPPEDARGS_PREF_NONE,
|
||||
ECMA_GETPROPITERATOR_PREF_NONE,
|
||||
ECMA_ASYNCFUNCTIONENTER_PREF_NONE,
|
||||
ECMA_LDHOLE_PREF_NONE,
|
||||
ECMA_RETURNUNDEFINED_PREF_NONE,
|
||||
ECMA_CREATEEMPTYOBJECT_PREF_NONE,
|
||||
ECMA_CREATEEMPTYARRAY_PREF_NONE,
|
||||
ECMA_GETITERATOR_PREF_V8_V8,
|
||||
ECMA_GETITERATOR_PREF_NONE,
|
||||
ECMA_GETASYNCITERATOR_PREF_NONE,
|
||||
ECMA_THROWTHROWNOTEXISTS_PREF_NONE,
|
||||
ECMA_THROWPATTERNNONCOERCIBLE_PREF_NONE,
|
||||
ECMA_LDHOMEOBJECT_PREF_NONE,
|
||||
ECMA_THROWDELETESUPERPROPERTY_PREF_NONE,
|
||||
ECMA_DEBUGGER_PREF_NONE,
|
||||
ECMA_ADD2DYN_PREF_V8,
|
||||
ECMA_SUB2DYN_PREF_V8,
|
||||
ECMA_MUL2DYN_PREF_V8,
|
||||
ECMA_DIV2DYN_PREF_V8,
|
||||
ECMA_MOD2DYN_PREF_V8,
|
||||
ECMA_EQDYN_PREF_V8,
|
||||
ECMA_NOTEQDYN_PREF_V8,
|
||||
ECMA_LESSDYN_PREF_V8,
|
||||
ECMA_LESSEQDYN_PREF_V8,
|
||||
ECMA_GREATERDYN_PREF_V8,
|
||||
ECMA_GREATEREQDYN_PREF_V8,
|
||||
ECMA_SHL2DYN_PREF_V8,
|
||||
ECMA_SHR2DYN_PREF_V8,
|
||||
ECMA_ASHR2DYN_PREF_V8,
|
||||
ECMA_AND2DYN_PREF_V8,
|
||||
ECMA_OR2DYN_PREF_V8,
|
||||
ECMA_XOR2DYN_PREF_V8,
|
||||
ECMA_TONUMBER_PREF_V8,
|
||||
ECMA_TONUMERIC_PREF_V8,
|
||||
ECMA_NEGDYN_PREF_V8,
|
||||
ECMA_NOTDYN_PREF_V8,
|
||||
ECMA_INCDYN_PREF_V8,
|
||||
ECMA_DECDYN_PREF_V8,
|
||||
ECMA_EXPDYN_PREF_V8,
|
||||
ECMA_ISINDYN_PREF_V8,
|
||||
ECMA_INSTANCEOFDYN_PREF_V8,
|
||||
ECMA_STRICTNOTEQDYN_PREF_V8,
|
||||
ECMA_STRICTEQDYN_PREF_V8,
|
||||
ECMA_RESUMEGENERATOR_PREF_V8,
|
||||
ECMA_GETRESUMEMODE_PREF_V8,
|
||||
ECMA_CREATEGENERATOROBJ_PREF_V8,
|
||||
ECMA_SETGENERATORSTATE_PREF_V8_IMM8,
|
||||
ECMA_CREATEASYNCGENERATOROBJ_PREF_V8,
|
||||
ECMA_THROWCONSTASSIGNMENT_PREF_V8,
|
||||
ECMA_GETMETHOD_PREF_ID32_V8,
|
||||
ECMA_GETTEMPLATEOBJECT_PREF_V8,
|
||||
ECMA_GETNEXTPROPNAME_PREF_V8,
|
||||
ECMA_CALLARG0DYN_PREF_V8,
|
||||
ECMA_THROWIFNOTOBJECT_PREF_V8,
|
||||
ECMA_CLOSEITERATOR_PREF_V8,
|
||||
ECMA_COPYMODULE_PREF_V8,
|
||||
ECMA_SUPERCALLSPREAD_PREF_V8,
|
||||
ECMA_DELOBJPROP_PREF_V8_V8,
|
||||
ECMA_NEWOBJSPREADDYN_PREF_V8_V8,
|
||||
ECMA_CREATEITERRESULTOBJ_PREF_V8_V8,
|
||||
ECMA_SUSPENDGENERATOR_PREF_V8_V8,
|
||||
ECMA_SUSPENDASYNCGENERATOR_PREF_V8,
|
||||
ECMA_ASYNCFUNCTIONAWAITUNCAUGHT_PREF_V8_V8,
|
||||
ECMA_THROWUNDEFINEDIFHOLE_PREF_V8_V8,
|
||||
ECMA_CALLARG1DYN_PREF_V8_V8,
|
||||
ECMA_COPYDATAPROPERTIES_PREF_V8_V8,
|
||||
ECMA_STARRAYSPREAD_PREF_V8_V8,
|
||||
ECMA_SETOBJECTWITHPROTO_PREF_V8_V8,
|
||||
ECMA_LDOBJBYVALUE_PREF_V8_V8,
|
||||
ECMA_STOBJBYVALUE_PREF_V8_V8,
|
||||
ECMA_STOWNBYVALUE_PREF_V8_V8,
|
||||
ECMA_LDSUPERBYVALUE_PREF_V8_V8,
|
||||
ECMA_STSUPERBYVALUE_PREF_V8_V8,
|
||||
ECMA_LDOBJBYINDEX_PREF_IMM8_V8,
|
||||
ECMA_LDOBJBYINDEX_PREF_IMM16_V8,
|
||||
ECMA_LDOBJBYINDEX_PREF_V8_IMM32,
|
||||
ECMA_STOBJBYINDEX_PREF_IMM8_V8,
|
||||
ECMA_STOBJBYINDEX_PREF_IMM16_V8,
|
||||
ECMA_STOBJBYINDEX_PREF_V8_IMM32,
|
||||
ECMA_STOWNBYINDEX_PREF_IMM8_V8,
|
||||
ECMA_STOWNBYINDEX_PREF_IMM16_V8,
|
||||
ECMA_STOWNBYINDEX_PREF_V8_IMM32,
|
||||
ECMA_CALLSPREADDYN_PREF_V8_V8_V8,
|
||||
ECMA_ASYNCFUNCTIONRESOLVE_PREF_V8_V8_V8,
|
||||
ECMA_ASYNCFUNCTIONREJECT_PREF_V8_V8_V8,
|
||||
ECMA_ASYNCGENERATORRESOLVE_PREF_V8,
|
||||
ECMA_ASYNCGENERATORREJECT_PREF_V8,
|
||||
ECMA_CALLARGS2DYN_PREF_V8_V8_V8,
|
||||
ECMA_CALLARGS3DYN_PREF_V8_V8_V8_V8,
|
||||
ECMA_DEFINEGETTERSETTERBYVALUE_PREF_V8_V8_V8_V8,
|
||||
ECMA_NEWOBJDYNRANGE_PREF_IMM16_V8,
|
||||
ECMA_CALLIRANGEDYN_PREF_IMM16_V8,
|
||||
ECMA_CALLITHISRANGEDYN_PREF_IMM16_V8,
|
||||
ECMA_SUPERCALL_PREF_IMM16_V8,
|
||||
ECMA_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8,
|
||||
ECMA_DEFINEFUNCDYN_PREF_ID16_IMM16_V8,
|
||||
ECMA_DEFINENCFUNCDYN_PREF_ID16_IMM16_V8,
|
||||
ECMA_DEFINEGENERATORFUNC_PREF_ID16_IMM16_V8,
|
||||
ECMA_DEFINEASYNCFUNC_PREF_ID16_IMM16_V8,
|
||||
ECMA_DEFINEASYNCGENERATORFUNC_PREF_ID16_V8,
|
||||
ECMA_DEFINEMETHOD_PREF_ID16_IMM16_V8,
|
||||
ECMA_NEWLEXENVDYN_PREF_IMM16,
|
||||
ECMA_COPYLEXENVDYN_PREF_NONE,
|
||||
ECMA_COPYRESTARGS_PREF_IMM16,
|
||||
ECMA_CREATEARRAYWITHBUFFER_PREF_IMM16,
|
||||
ECMA_CREATEOBJECTHAVINGMETHOD_PREF_IMM16,
|
||||
ECMA_THROWIFSUPERNOTCORRECTCALL_PREF_IMM16,
|
||||
ECMA_CREATEOBJECTWITHBUFFER_PREF_IMM16,
|
||||
ECMA_LDLEXVARDYN_PREF_IMM4_IMM4,
|
||||
ECMA_LDLEXVARDYN_PREF_IMM8_IMM8,
|
||||
ECMA_LDLEXVARDYN_PREF_IMM16_IMM16,
|
||||
ECMA_STLEXVARDYN_PREF_IMM4_IMM4_V8,
|
||||
ECMA_STLEXVARDYN_PREF_IMM8_IMM8_V8,
|
||||
ECMA_STLEXVARDYN_PREF_IMM16_IMM16_V8,
|
||||
ECMA_DEFINECLASSWITHBUFFER_PREF_ID16_IMM16_IMM16_V8_V8,
|
||||
ECMA_IMPORTMODULE_PREF_ID32,
|
||||
ECMA_STMODULEVAR_PREF_ID32,
|
||||
ECMA_TRYLDGLOBALBYNAME_PREF_ID32,
|
||||
ECMA_TRYSTGLOBALBYNAME_PREF_ID32,
|
||||
ECMA_LDGLOBALVAR_PREF_ID32,
|
||||
ECMA_STGLOBALVAR_PREF_ID32,
|
||||
ECMA_STGLOBALLET_PREF_ID32,
|
||||
ECMA_LDOBJBYNAME_PREF_ID32_V8,
|
||||
ECMA_STOBJBYNAME_PREF_ID32_V8,
|
||||
ECMA_STOWNBYNAME_PREF_ID32_V8,
|
||||
ECMA_LDSUPERBYNAME_PREF_ID32_V8,
|
||||
ECMA_STSUPERBYNAME_PREF_ID32_V8,
|
||||
ECMA_LDMODVARBYNAME_PREF_ID32_V8,
|
||||
ECMA_TOBOOLEAN_PREF_NONE,
|
||||
ECMA_NEGATE_PREF_NONE,
|
||||
ECMA_ISTRUE_PREF_NONE,
|
||||
ECMA_ISFALSE_PREF_NONE,
|
||||
ECMA_ISUNDEFINED_PREF_NONE,
|
||||
ECMA_ISCOERCIBLE_PREF_NONE,
|
||||
ECMA_JFALSE_PREF_IMM8,
|
||||
ECMA_JFALSE_PREF_IMM16,
|
||||
ECMA_JFALSE_PREF_IMM32,
|
||||
ECMA_JTRUE_PREF_IMM8,
|
||||
ECMA_JTRUE_PREF_IMM16,
|
||||
ECMA_JTRUE_PREF_IMM32,
|
||||
ECMA_RETURN_DYN_PREF_NONE,
|
||||
ECMA_ITERNEXT_PREF_V8,
|
||||
ECMA_GETMODULENAMESPACE_PREF_ID32,
|
||||
ECMA_LDMODULEVAR_PREF_ID32_IMM8,
|
||||
ECMA_STCONSTTOGLOBALRECORD_PREF_ID32,
|
||||
ECMA_STLETTOGLOBALRECORD_PREF_ID32,
|
||||
ECMA_GETITERATORNEXT_PREF_V8_V8,
|
||||
ECMA_CREATEREGEXPWITHLITERAL_PREF_ID32_IMM8,
|
||||
ECMA_STCLASSTOGLOBALRECORD_PREF_ID32,
|
||||
ECMA_STOWNBYVALUEWITHNAMESET_PREF_V8_V8,
|
||||
ECMA_LDFUNCTION_PREF_NONE,
|
||||
ECMA_NEWLEXENVWITHNAMEDYN_PREF_IMM16_IMM16,
|
||||
ECMA_LDBIGINT_PREF_ID32,
|
||||
ECMA_STOWNBYNAMEWITHNAMESET_PREF_ID32_V8,
|
||||
ECMA_ASYNCGENERATORRESOLVE_PREF_V8_V8_V8,
|
||||
ECMA_DEFINEASYNCGENERATORFUNC_PREF_ID16_IMM16_V8,
|
||||
ECMA_DYNAMICIMPORT_PREF_V8,
|
||||
ECMA_LDPATCHVAR_PREF_IMM16,
|
||||
ECMA_STPATCHVAR_PREF_IMM16,
|
||||
ECMA_ASYNCGENERATORREJECT_PREF_V8_V8,
|
||||
};
|
||||
|
@ -180,10 +180,6 @@ void Disassembler::GetMethod(pandasm::Function *method, const panda_file::File::
|
||||
GetParams(method, method_accessor.GetProtoId());
|
||||
GetMetaData(method, method_id);
|
||||
|
||||
if (!method->HasImplementation()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (method_accessor.GetCodeId().has_value()) {
|
||||
const IdList id_list = GetInstructions(method, method_id, method_accessor.GetCodeId().value());
|
||||
|
||||
@ -200,7 +196,7 @@ void Disassembler::GetMethod(pandasm::Function *method, const panda_file::File::
|
||||
|
||||
template <typename T>
|
||||
void Disassembler::FillLiteralArrayData(pandasm::LiteralArray *lit_array, const panda_file::LiteralTag &tag,
|
||||
const panda_file::LiteralDataAccessor::LiteralValue &value)
|
||||
const panda_file::LiteralDataAccessor::LiteralValue &value) const
|
||||
{
|
||||
panda_file::File::EntityId id(std::get<uint32_t>(value));
|
||||
auto sp = file_->GetSpanFromId(id);
|
||||
@ -268,15 +264,12 @@ void Disassembler::FillLiteralData(pandasm::LiteralArray *lit_array,
|
||||
lit_array->literals_.push_back(lit);
|
||||
}
|
||||
|
||||
void Disassembler::GetLiteralArray(pandasm::LiteralArray *lit_array, const size_t index)
|
||||
void Disassembler::GetLiteralArrayByOffset(pandasm::LiteralArray *lit_array, panda_file::File::EntityId offset) const
|
||||
{
|
||||
LOG(DEBUG, DISASSEMBLER) << "\n[getting literal array]\nindex: " << index;
|
||||
|
||||
panda_file::LiteralDataAccessor lit_array_accessor(*file_, file_->GetLiteralArraysId());
|
||||
|
||||
lit_array_accessor.EnumerateLiteralVals(
|
||||
index, [this, lit_array](const panda_file::LiteralDataAccessor::LiteralValue &value,
|
||||
const panda_file::LiteralTag &tag) {
|
||||
offset, [this, lit_array](const panda_file::LiteralDataAccessor::LiteralValue &value,
|
||||
const panda_file::LiteralTag &tag) {
|
||||
switch (tag) {
|
||||
case panda_file::LiteralTag::ARRAY_U1: {
|
||||
FillLiteralArrayData<bool>(lit_array, tag, value);
|
||||
@ -322,6 +315,14 @@ void Disassembler::GetLiteralArray(pandasm::LiteralArray *lit_array, const size_
|
||||
});
|
||||
}
|
||||
|
||||
void Disassembler::GetLiteralArray(pandasm::LiteralArray *lit_array, const size_t index) const
|
||||
{
|
||||
LOG(DEBUG, DISASSEMBLER) << "\n[getting literal array]\nindex: " << index;
|
||||
|
||||
panda_file::LiteralDataAccessor lit_array_accessor(*file_, file_->GetLiteralArraysId());
|
||||
GetLiteralArrayByOffset(lit_array, lit_array_accessor.GetLiteralArrayId(index));
|
||||
}
|
||||
|
||||
void Disassembler::GetLiteralArrays()
|
||||
{
|
||||
const auto lit_arrays_id = file_->GetLiteralArraysId();
|
||||
@ -652,14 +653,6 @@ void Disassembler::GetMetaData(pandasm::Function *method, const panda_file::File
|
||||
method->metadata->SetAttribute("external");
|
||||
}
|
||||
|
||||
if (method_accessor.IsNative()) {
|
||||
method->metadata->SetAttribute("native");
|
||||
}
|
||||
|
||||
if (method_accessor.IsAbstract()) {
|
||||
method->metadata->SetAttribute("noimpl");
|
||||
}
|
||||
|
||||
std::string ctor_name = panda::panda_file::GetCtorName(file_language_);
|
||||
std::string cctor_name = panda::panda_file::GetCctorName(file_language_);
|
||||
|
||||
@ -1019,27 +1012,33 @@ static bool IsArray(const panda_file::LiteralTag &tag)
|
||||
}
|
||||
}
|
||||
|
||||
void Disassembler::Serialize(size_t index, const pandasm::LiteralArray &lit_array, std::ostream &os) const
|
||||
std::string Disassembler::SerializeLiteralArray(const pandasm::LiteralArray &lit_array) const
|
||||
{
|
||||
std::stringstream ret;
|
||||
if (lit_array.literals_.empty()) {
|
||||
return;
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
const auto &tag = lit_array.literals_[0].tag_;
|
||||
if (IsArray(tag)) {
|
||||
os << ".array array_";
|
||||
ret << "{array: ";
|
||||
} else {
|
||||
os << ".literal literal_";
|
||||
ret << "{literal: ";
|
||||
}
|
||||
os << index << " " << LiteralTagToString(tag);
|
||||
ret << LiteralTagToString(tag);
|
||||
if (IsArray(tag)) {
|
||||
os << " " << lit_array.literals_.size();
|
||||
ret << " " << lit_array.literals_.size();
|
||||
}
|
||||
os << " { ";
|
||||
ret << " [ ";
|
||||
SerializeValues(lit_array, ret);
|
||||
ret << "]}";
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
SerializeValues(lit_array, os);
|
||||
|
||||
os << "}\n";
|
||||
void Disassembler::Serialize(size_t index, const pandasm::LiteralArray &lit_array, std::ostream &os) const
|
||||
{
|
||||
os << "literal_index " << index << " ";
|
||||
os << SerializeLiteralArray(lit_array);
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
std::string Disassembler::LiteralTagToString(const panda_file::LiteralTag &tag) const
|
||||
@ -1082,14 +1081,15 @@ std::string Disassembler::LiteralTagToString(const panda_file::LiteralTag &tag)
|
||||
return "method_affiliate";
|
||||
case panda_file::LiteralTag::NULLVALUE:
|
||||
return "null_value";
|
||||
case panda_file::LiteralTag::TAGVALUE:
|
||||
return "tagvalue";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void Disassembler::SerializeValues(const pandasm::LiteralArray &lit_array, std::ostream &os) const
|
||||
template <typename T>
|
||||
void Disassembler::SerializeValues(const pandasm::LiteralArray &lit_array, T &os) const
|
||||
{
|
||||
switch (lit_array.literals_[0].tag_) {
|
||||
case panda_file::LiteralTag::ARRAY_U1: {
|
||||
@ -1300,11 +1300,6 @@ void Disassembler::Serialize(const pandasm::Function &method, std::ostream &os,
|
||||
Serialize(*method.metadata, {}, os);
|
||||
}
|
||||
|
||||
if (!method.HasImplementation()) {
|
||||
os << "\n\n";
|
||||
return;
|
||||
}
|
||||
|
||||
auto method_info_it = prog_info_.methods_info.find(signature);
|
||||
bool print_method_info = print_information && method_info_it != prog_info_.methods_info.end();
|
||||
if (print_method_info) {
|
||||
@ -1489,43 +1484,18 @@ pandasm::Opcode Disassembler::BytecodeOpcodeToPandasmOpcode(uint8_t o) const
|
||||
std::string Disassembler::IDToString(BytecodeInstruction bc_ins, panda_file::File::EntityId method_id) const
|
||||
{
|
||||
std::stringstream name;
|
||||
const auto offset = file_->ResolveOffsetByIndex(method_id, bc_ins.GetId().AsIndex());
|
||||
|
||||
if (bc_ins.HasFlag(BytecodeInstruction::Flags::TYPE_ID)) {
|
||||
auto idx = bc_ins.GetId().AsIndex();
|
||||
auto id = file_->ResolveClassIndex(method_id, idx);
|
||||
auto type = pandasm::Type::FromDescriptor(StringDataToString(file_->GetStringData(id)));
|
||||
|
||||
name.str("");
|
||||
name << type.GetPandasmName();
|
||||
} else if (bc_ins.HasFlag(BytecodeInstruction::Flags::METHOD_ID)) {
|
||||
auto idx = bc_ins.GetId().AsIndex();
|
||||
auto id = file_->ResolveMethodIndex(method_id, idx);
|
||||
|
||||
name << GetMethodSignature(id);
|
||||
if (bc_ins.HasFlag(BytecodeInstruction::Flags::METHOD_ID)) {
|
||||
name << GetMethodSignature(offset);
|
||||
} else if (bc_ins.HasFlag(BytecodeInstruction::Flags::STRING_ID)) {
|
||||
name << '\"';
|
||||
|
||||
if (skip_strings_ || quiet_) {
|
||||
name << std::hex << "0x" << bc_ins.GetId().AsFileId();
|
||||
} else {
|
||||
name << StringDataToString(file_->GetStringData(bc_ins.GetId().AsFileId()));
|
||||
}
|
||||
|
||||
name << StringDataToString(file_->GetStringData(offset));
|
||||
name << '\"';
|
||||
} else if (bc_ins.HasFlag(BytecodeInstruction::Flags::FIELD_ID)) {
|
||||
auto idx = bc_ins.GetId().AsIndex();
|
||||
auto id = file_->ResolveFieldIndex(method_id, idx);
|
||||
panda_file::FieldDataAccessor field_accessor(*file_, id);
|
||||
|
||||
name << GetFullRecordName(field_accessor.GetClassId());
|
||||
name << '.';
|
||||
name << StringDataToString(file_->GetStringData(field_accessor.GetNameId()));
|
||||
} else if (bc_ins.HasFlag(BytecodeInstruction::Flags::LITERALARRAY_ID)) {
|
||||
panda_file::LiteralDataAccessor lit_array_accessor(*file_, file_->GetLiteralArraysId());
|
||||
auto idx = bc_ins.GetId().AsFileId();
|
||||
auto index = lit_array_accessor.ResolveLiteralArrayIndex(idx);
|
||||
|
||||
name << "array_" << index;
|
||||
pandasm::LiteralArray lit_array;
|
||||
GetLiteralArrayByOffset(&lit_array, panda_file::File::EntityId(offset));
|
||||
name << SerializeLiteralArray(lit_array);
|
||||
}
|
||||
|
||||
return name.str();
|
||||
|
@ -65,10 +65,10 @@ public:
|
||||
void GetRecord(pandasm::Record *record, const panda_file::File::EntityId &record_id);
|
||||
void AddMethodToTables(const panda_file::File::EntityId &method_id);
|
||||
void GetMethod(pandasm::Function *method, const panda_file::File::EntityId &method_id);
|
||||
void GetLiteralArray(pandasm::LiteralArray *lit_array, const size_t index);
|
||||
void GetLiteralArray(pandasm::LiteralArray *lit_array, const size_t index) const;
|
||||
template <typename T>
|
||||
void FillLiteralArrayData(pandasm::LiteralArray *lit_array, const panda_file::LiteralTag &tag,
|
||||
const panda_file::LiteralDataAccessor::LiteralValue &value);
|
||||
const panda_file::LiteralDataAccessor::LiteralValue &value) const;
|
||||
|
||||
const ProgInfo &GetProgInfo() const
|
||||
{
|
||||
@ -116,7 +116,8 @@ private:
|
||||
void GetInsInfo(const panda_file::File::EntityId &code_id, MethodInfo *method_info) const;
|
||||
|
||||
void Serialize(size_t index, const pandasm::LiteralArray &lit_array, std::ostream &os) const;
|
||||
void SerializeValues(const pandasm::LiteralArray &lit_array, std::ostream &os) const;
|
||||
template <typename T>
|
||||
void SerializeValues(const pandasm::LiteralArray &lit_array, T &os) const;
|
||||
std::string LiteralTagToString(const panda_file::LiteralTag &tag) const;
|
||||
void Serialize(const pandasm::Record &record, std::ostream &os, bool print_information = false) const;
|
||||
void SerializeFields(const pandasm::Record &record, std::ostream &os, bool print_information) const;
|
||||
@ -152,6 +153,10 @@ private:
|
||||
|
||||
panda::panda_file::SourceLang GetRecordLanguage(panda_file::File::EntityId class_id) const;
|
||||
|
||||
std::string SerializeLiteralArray(const pandasm::LiteralArray &lit_array) const;
|
||||
|
||||
void GetLiteralArrayByOffset(pandasm::LiteralArray *lit_array, panda_file::File::EntityId offset) const;
|
||||
|
||||
std::unique_ptr<const panda_file::File> file_;
|
||||
pandasm::Program prog_;
|
||||
|
||||
|
@ -71,22 +71,11 @@ pandasm::Ins Disassembler::BytecodeInstructionToPandasmInstruction(BytecodeInstr
|
||||
|
||||
int overhead;
|
||||
|
||||
const bool is_initobj = ins.opcode == pandasm::Opcode::INITOBJ_SHORT ||
|
||||
ins.opcode == pandasm::Opcode::INITOBJ_RANGE || ins.opcode == pandasm::Opcode::INITOBJ;
|
||||
|
||||
const bool is_acc = ins.opcode == pandasm::Opcode::CALL_ACC_SHORT || ins.opcode == pandasm::Opcode::CALL_ACC ||
|
||||
ins.opcode == pandasm::Opcode::CALL_VIRT_ACC_SHORT ||
|
||||
ins.opcode == pandasm::Opcode::CALL_VIRT_ACC;
|
||||
|
||||
if (mda.IsStatic() || is_initobj) {
|
||||
if (mda.IsStatic()) {
|
||||
overhead = ins.regs.size() - pda.GetNumArgs();
|
||||
} else {
|
||||
overhead = ins.regs.size() - pda.GetNumArgs() - 1;
|
||||
}
|
||||
// call.acc recieves fixed amount of registers
|
||||
if (is_acc) {
|
||||
return ins;
|
||||
}
|
||||
if (overhead < 0 || overhead > static_cast<int>(ins.regs.size())) {
|
||||
LOG(ERROR, DISASSEMBLER)
|
||||
<< "> error encountered in code of " << std::dec << method_id.GetOffset() << " ("
|
||||
|
39
docs/2022-08-18-isa-changelog.md
Normal file
39
docs/2022-08-18-isa-changelog.md
Normal file
@ -0,0 +1,39 @@
|
||||
# 2022-08-18-isa-changelog
|
||||
|
||||
This document describes change log with the following modifications:
|
||||
|
||||
* ISA refactoring
|
||||
* Function Kind and Header index
|
||||
* MethodId, StringId and LiteralArrayId
|
||||
|
||||
## ISA refactoring
|
||||
The bytecode size and runtime performance have been suffering for a long time as the all the
|
||||
ecmascript specific bytecode are prefixed and their opcode were encoded with two bytes.
|
||||
1. We delete all original java specific opcodes and delete java specific opcode prefix.
|
||||
2. We remove the prefix of ecmascript specific opcodes, such that most of the bytecode opcode can be encoded with one byte.
|
||||
3. We add prefix "deprecated" and keep the many old isa as "deprecated"-prefixed opcodes (for compatibility). These prefixed opcode will be deleted once we do not need to concern compatibility.
|
||||
4. We add prefix "throw" and make all throwing opcodes be prefixed by "throw".
|
||||
5. We add prefix "wide" to support opcodes which need larger immediate number.
|
||||
6. We adjust the format of some opcodes (about immediate number and accumulator), so that the bytecode can be more compact.
|
||||
7. We change the semantics of some opcodes.
|
||||
8. We add 8-bit or 16-bit imm as inline cache slot for some specific opcodes.
|
||||
|
||||
## Function Kind and Header index
|
||||
As we merge some "define-function" opcodes as one opcode, in function we add one field which records the function kind,
|
||||
such that runtime can distinguish the "define-function" operations of different kinds.
|
||||
We also add header index in function such that runtime can access IndexHeader more efficiently.
|
||||
We reuse the field 32-bit field `access_flags_` to encode Function Kind and Header index.
|
||||
This will not introduce compatibility issue because the later 24-bit of `access_flags_` is unused indeed.
|
||||
Now the layout is:
|
||||
|
||||
|<- 16-bit header index ->|<- 8-bit function kind ->|<- 8-bit original access flag ->|
|
||||
|
||||
## MethodId, StringId and LiteralArrayId
|
||||
To adapt runtime design, we put string and literal array into the index header of methods,
|
||||
such that the instructions can get consective indexes for methodId, stringId and literalarrayId.
|
||||
This will help runtime to build constant pool more efficiently.
|
||||
As the method number in a class is not limited, we release the constraint that all methodId,
|
||||
stringId and literalarrayId in a class should be put in a same index header.
|
||||
Instead, we only ask that all methodId, stringId and literalarrayId in a method should be put in one index header.
|
||||
As we use 16-bit to encode methodId, stringId and literalarrayId, the number of these Ids in one method cannot exceed 65536 for now.
|
||||
This released constraint suits for most of application scenarios.
|
@ -15,8 +15,8 @@ import("//arkcompiler/runtime_core/ark_config.gni")
|
||||
|
||||
isa_paths = [
|
||||
rebase_path("$ark_root/isa/isa.yaml", root_build_dir),
|
||||
rebase_path("$ark_root/../ets_runtime/ecmascript/ecma_isa.yaml",
|
||||
root_build_dir),
|
||||
# rebase_path("$ark_root/../ets_runtime/ecmascript/ecma_isa.yaml",
|
||||
# root_build_dir),
|
||||
]
|
||||
|
||||
foreach(plugin, enabled_plugins) {
|
||||
@ -44,10 +44,7 @@ foreach(plugin, enabled_plugins) {
|
||||
action("isa_combine") {
|
||||
script = "$ark_root/isa/combine.rb"
|
||||
input_args = string_join(",", isa_paths)
|
||||
inputs = [
|
||||
"$ark_root/isa/isa.yaml",
|
||||
"$ark_root/../ets_runtime/ecmascript/ecma_isa.yaml",
|
||||
]
|
||||
inputs = [ "$ark_root/isa/isa.yaml" ]
|
||||
outputs = [ "$root_gen_dir/isa/isa.yaml" ]
|
||||
args = [
|
||||
"-d",
|
||||
|
3357
isa/isa.yaml
3357
isa/isa.yaml
File diff suppressed because it is too large
Load Diff
45
isa/isapi.rb
45
isa/isapi.rb
@ -157,10 +157,25 @@ class Instruction < SimpleDelegator
|
||||
operands = operands.split(', ')
|
||||
ops_encoding = format.encoding
|
||||
|
||||
count = 0
|
||||
operands.map do |operand|
|
||||
name, srcdst, type = Util.parse_operand_signature(operand)
|
||||
if name.end_with?('id')
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
|
||||
id_count = 1
|
||||
operands.map do |operand|
|
||||
name, srcdst, type = Util.parse_operand_signature(operand)
|
||||
key = name
|
||||
key = 'id' if name.end_with?('id')
|
||||
if name.end_with?('id')
|
||||
key = 'id'
|
||||
if count > 1
|
||||
key += id_count.to_s
|
||||
id_count = id_count + 1
|
||||
end
|
||||
end
|
||||
Operand.new(name, srcdst, type, ops_encoding[key].width, ops_encoding[key].offset)
|
||||
end
|
||||
end
|
||||
@ -190,6 +205,20 @@ class Instruction < SimpleDelegator
|
||||
props + add_props
|
||||
end
|
||||
|
||||
cached def real_properties
|
||||
filter = []
|
||||
properties.each do |p|
|
||||
if p != 'acc_write' && p != 'acc_read' && p != 'acc_none'
|
||||
filter << p
|
||||
end
|
||||
end
|
||||
filter << 'acc_write' if acc_write?
|
||||
filter << 'acc_read' if acc_read?
|
||||
filter << 'acc_none' if acc_none?
|
||||
return filter
|
||||
end
|
||||
|
||||
|
||||
def type(index)
|
||||
acc_and_operands.select(&:src?)[index].type || 'none'
|
||||
end
|
||||
@ -263,7 +292,7 @@ class Format
|
||||
end
|
||||
|
||||
cached def pretty
|
||||
name.sub('op_', '').gsub(/imm[0-9]?/, 'imm').gsub(/v[0-9]?/, 'v').gsub(/_([0-9]+)/, '\1')
|
||||
name.sub('op_', '').gsub(/id[0-9]?/, 'id').gsub(/imm[0-9]?/, 'imm').gsub(/v[0-9]?/, 'v').gsub(/_([0-9]+)/, '\1')
|
||||
end
|
||||
|
||||
def prefixed?
|
||||
@ -335,6 +364,18 @@ class Operand
|
||||
%i[method_id type_id field_id string_id literalarray_id].include?(@name)
|
||||
end
|
||||
|
||||
def method_id?
|
||||
%i[method_id].include?(@name)
|
||||
end
|
||||
|
||||
def string_id?
|
||||
%i[string_id].include?(@name)
|
||||
end
|
||||
|
||||
def literalarray_id?
|
||||
%i[literalarray_id].include?(@name)
|
||||
end
|
||||
|
||||
def dst?
|
||||
%i[inout out].include?(@srcdst)
|
||||
end
|
||||
|
@ -391,7 +391,14 @@ public:
|
||||
|
||||
static constexpr bool HasImm(Format format, size_t idx);
|
||||
|
||||
static constexpr Format GetFormat(Opcode opcode);
|
||||
|
||||
static constexpr size_t Size(Format format);
|
||||
|
||||
static constexpr size_t Size(Opcode opcode)
|
||||
{
|
||||
return Size(GetFormat(opcode));
|
||||
}
|
||||
};
|
||||
|
||||
template <const BytecodeInstMode Mode>
|
||||
|
@ -301,6 +301,12 @@ public:
|
||||
return index[idx];
|
||||
}
|
||||
|
||||
EntityId ResolveOffsetByIndex(EntityId id, Index idx) const
|
||||
{
|
||||
auto index = GetMethodIndex(id);
|
||||
return index[idx];
|
||||
}
|
||||
|
||||
EntityId ResolveFieldIndex(EntityId id, Index idx) const
|
||||
{
|
||||
auto index = GetFieldIndex(id);
|
||||
|
@ -524,34 +524,36 @@ void ItemContainer::ReorderItems(panda::panda_file::pgo::ProfileOptimizer *profi
|
||||
profile_opt->ProfileGuidedRelayout(items_);
|
||||
}
|
||||
|
||||
void ItemContainer::ProcessIndexDependecies(BaseItem *item)
|
||||
void ItemContainer::AddIndexDependecies(BaseItem *item)
|
||||
{
|
||||
auto deps = item->GetIndexDependencies();
|
||||
|
||||
item->Visit([&deps](BaseItem *param_item) {
|
||||
const auto &item_deps = param_item->GetIndexDependencies();
|
||||
deps.insert(deps.end(), item_deps.cbegin(), item_deps.cend());
|
||||
return true;
|
||||
});
|
||||
|
||||
if (index_section_item_.IsEmpty()) {
|
||||
index_section_item_.AddHeader();
|
||||
index_section_item_.GetCurrentHeader()->SetStart(item);
|
||||
}
|
||||
|
||||
if (index_section_item_.GetCurrentHeader()->Add(deps)) {
|
||||
return;
|
||||
const auto &item_deps = item->GetIndexDependencies();
|
||||
if (!index_section_item_.GetCurrentHeader()->Add(item_deps)) {
|
||||
index_section_item_.GetCurrentHeader()->SetEnd(item);
|
||||
index_section_item_.AddHeader();
|
||||
index_section_item_.GetCurrentHeader()->SetStart(item);
|
||||
if (!index_section_item_.GetCurrentHeader()->Add(item_deps)) {
|
||||
LOG(FATAL, PANDAFILE) << "Cannot add " << item_deps.size() << " items to index";
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
index_section_item_.GetCurrentHeader()->SetEnd(item);
|
||||
index_section_item_.AddHeader();
|
||||
index_section_item_.GetCurrentHeader()->SetStart(item);
|
||||
|
||||
if (!index_section_item_.GetCurrentHeader()->Add(deps)) {
|
||||
LOG(FATAL, PANDAFILE) << "Cannot add " << deps.size() << " items to index";
|
||||
if (item->GetName() == "method_item") {
|
||||
static_cast<BaseMethodItem *>(item)->SetHeaderIndex(index_section_item_.GetNumHeaders() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemContainer::ProcessIndexDependecies(BaseItem *item)
|
||||
{
|
||||
AddIndexDependecies(item);
|
||||
item->Visit([&](BaseItem *param_item) {
|
||||
AddIndexDependecies(param_item);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool ItemContainer::WriteHeaderIndexInfo(Writer *writer)
|
||||
{
|
||||
if (!writer->Write<uint32_t>(class_map_.size())) {
|
||||
@ -883,7 +885,7 @@ ItemTypes ItemContainer::IndexItem::GetItemType() const
|
||||
switch (type_) {
|
||||
case IndexType::CLASS:
|
||||
return ItemTypes::CLASS_INDEX_ITEM;
|
||||
case IndexType::METHOD:
|
||||
case IndexType::METHOD_STRING_LITERAL:
|
||||
return ItemTypes::METHOD_INDEX_ITEM;
|
||||
case IndexType::FIELD:
|
||||
return ItemTypes::FIELD_INDEX_ITEM;
|
||||
|
@ -516,6 +516,8 @@ private:
|
||||
|
||||
void UpdateOrderIndexes();
|
||||
|
||||
void AddIndexDependecies(BaseItem *item);
|
||||
|
||||
void ProcessIndexDependecies(BaseItem *item);
|
||||
|
||||
size_t GetForeignOffset() const;
|
||||
|
@ -71,6 +71,16 @@ enum class FieldTag : uint8_t {
|
||||
TYPE_ANNOTATION = 0x06
|
||||
};
|
||||
|
||||
enum class FunctionKind : uint8_t {
|
||||
NONE = 0x0,
|
||||
FUNCTION = 0x1,
|
||||
NC_FUNCTION = 0x2,
|
||||
GENERATOR_FUNCTION = 0x3,
|
||||
ASYNC_FUNCTION = 0x4,
|
||||
ASYNC_GENERATOR_FUNCTION = 0x5,
|
||||
ASYNC_NC_FUNCTION = 0x6
|
||||
};
|
||||
|
||||
bool IsDynamicLanguage(panda::panda_file::SourceLang lang);
|
||||
std::optional<panda::panda_file::SourceLang> LanguageFromString(std::string_view lang);
|
||||
const char *LanguageToString(panda::panda_file::SourceLang lang);
|
||||
@ -85,6 +95,10 @@ static constexpr uint32_t INVALID_OFFSET = std::numeric_limits<uint32_t>::max();
|
||||
static constexpr uint32_t INVALID_INDEX = std::numeric_limits<uint32_t>::max();
|
||||
static constexpr uint32_t MAX_INDEX_16 = std::numeric_limits<uint16_t>::max();
|
||||
static constexpr uint32_t MAX_INDEX_32 = std::numeric_limits<uint32_t>::max();
|
||||
static constexpr uint32_t FLAG_WIDTH = 8;
|
||||
static constexpr uint32_t FUNTION_KIND_WIDTH = 8;
|
||||
static constexpr uint32_t FUNCTION_KIND_MASK = 0xFF00;
|
||||
static constexpr uint32_t FLAG_MASK = 0xFF;
|
||||
|
||||
constexpr uint32_t PGO_STRING_DEFAULT_COUNT = 5;
|
||||
constexpr uint32_t PGO_CLASS_DEFAULT_COUNT = 3;
|
||||
@ -128,11 +142,10 @@ constexpr std::string_view CODE_ITEM = "code_item";
|
||||
enum class IndexType {
|
||||
// 16-bit indexes
|
||||
CLASS = 0x0,
|
||||
METHOD = 0x1,
|
||||
METHOD_STRING_LITERAL = 0x1,
|
||||
FIELD = 0x2,
|
||||
PROTO = 0x3,
|
||||
LAST_16 = PROTO,
|
||||
|
||||
// 32-bit indexes
|
||||
LINE_NUMBER_PROG = 0x04,
|
||||
LAST_32 = LINE_NUMBER_PROG,
|
||||
@ -419,7 +432,7 @@ public:
|
||||
DEFAULT_COPY_SEMANTIC(PrimitiveTypeItem);
|
||||
};
|
||||
|
||||
class StringItem : public BaseItem {
|
||||
class StringItem : public IndexedItem {
|
||||
public:
|
||||
explicit StringItem(std::string str);
|
||||
|
||||
@ -446,6 +459,11 @@ public:
|
||||
return utf16_length_;
|
||||
}
|
||||
|
||||
IndexType GetIndexType() const override
|
||||
{
|
||||
return IndexType::METHOD_STRING_LITERAL;
|
||||
}
|
||||
|
||||
DEFAULT_MOVE_SEMANTIC(StringItem);
|
||||
DEFAULT_COPY_SEMANTIC(StringItem);
|
||||
|
||||
@ -723,7 +741,7 @@ public:
|
||||
|
||||
IndexType GetIndexType() const override
|
||||
{
|
||||
return IndexType::METHOD;
|
||||
return IndexType::METHOD_STRING_LITERAL;
|
||||
}
|
||||
|
||||
StringItem *GetNameItem() const
|
||||
@ -736,6 +754,18 @@ public:
|
||||
return class_;
|
||||
}
|
||||
|
||||
void SetFunctionKind(FunctionKind kind)
|
||||
{
|
||||
access_flags_ &= (~FUNCTION_KIND_MASK);
|
||||
access_flags_ |= (static_cast<uint8_t>(kind) << FLAG_WIDTH);
|
||||
}
|
||||
|
||||
void SetHeaderIndex(uint16_t idx)
|
||||
{
|
||||
access_flags_ &= (FUNCTION_KIND_MASK | FLAG_MASK);
|
||||
access_flags_ |= (idx << (FUNTION_KIND_WIDTH + FLAG_WIDTH));
|
||||
}
|
||||
|
||||
~BaseMethodItem() override = default;
|
||||
|
||||
DEFAULT_MOVE_SEMANTIC(BaseMethodItem);
|
||||
@ -752,7 +782,7 @@ private:
|
||||
BaseClassItem *class_;
|
||||
StringItem *name_;
|
||||
ProtoItem *proto_;
|
||||
uint32_t access_flags_;
|
||||
uint32_t access_flags_; // layout: |<- 16-bit header index ->|<- 8-bit FunctionKind ->|<- 8-bit flag ->|
|
||||
};
|
||||
|
||||
class MethodParamItem {
|
||||
@ -1428,7 +1458,7 @@ private:
|
||||
class ScalarValueItem;
|
||||
class ArrayValueItem;
|
||||
|
||||
class ValueItem : public BaseItem {
|
||||
class ValueItem : public IndexedItem {
|
||||
public:
|
||||
enum class Type { INTEGER, LONG, FLOAT, DOUBLE, ID, ARRAY };
|
||||
|
||||
@ -1614,6 +1644,11 @@ public:
|
||||
|
||||
bool Write(Writer *writer) override;
|
||||
|
||||
IndexType GetIndexType() const override
|
||||
{
|
||||
return IndexType::METHOD_STRING_LITERAL;
|
||||
}
|
||||
|
||||
ItemTypes GetItemType() const override
|
||||
{
|
||||
return ItemTypes::LITERAL_ARRAY_ITEM;
|
||||
|
70
libpandafile/index_accessor.h
Normal file
70
libpandafile/index_accessor.h
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LIBPANDAFILE_INDEX_ACCESSOR_H_
|
||||
#define LIBPANDAFILE_INDEX_ACCESSOR_H_
|
||||
|
||||
#include "file.h"
|
||||
#include "file_items.h"
|
||||
|
||||
namespace panda::panda_file {
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
|
||||
class IndexAccessor {
|
||||
public:
|
||||
IndexAccessor(const File &pf, File::EntityId method_id)
|
||||
{
|
||||
constexpr size_t SKIP_NUM = 3; // 3 : skip class_idx and proto_idx and name
|
||||
auto sp = pf.GetSpanFromId(method_id).SubSpan(IDX_SIZE * (SKIP_NUM - 1) + ID_SIZE);
|
||||
access_flags_ = helpers::ReadULeb128(&sp);
|
||||
header_index_ = access_flags_ >> (FUNTION_KIND_WIDTH + FLAG_WIDTH);
|
||||
num_headers_ = pf.GetHeader()->num_indexes;
|
||||
const auto *header = &(pf.GetIndexHeaders()[header_index_]);
|
||||
indexes_ = pf.GetMethodIndex(header);
|
||||
}
|
||||
|
||||
~IndexAccessor() = default;
|
||||
|
||||
// quick way to resolve offset by 16-bit id in method's instructions
|
||||
uint32_t GetOffsetById(uint16_t idx) const
|
||||
{
|
||||
return indexes_[idx].GetOffset();
|
||||
}
|
||||
|
||||
FunctionKind GetFunctionKind() const
|
||||
{
|
||||
return static_cast<FunctionKind>((access_flags_ & FUNCTION_KIND_MASK) >> FLAG_WIDTH);
|
||||
}
|
||||
|
||||
uint16_t GetHeaderIndex() const
|
||||
{
|
||||
return header_index_;
|
||||
}
|
||||
|
||||
uint32_t GetNumHeaders() const
|
||||
{
|
||||
return num_headers_;
|
||||
}
|
||||
|
||||
private:
|
||||
Span<const File::EntityId> indexes_;
|
||||
uint32_t access_flags_;
|
||||
uint16_t header_index_;
|
||||
uint32_t num_headers_;
|
||||
};
|
||||
|
||||
} // namespace panda::panda_file
|
||||
|
||||
#endif // LIBPANDAFILE_INDEX_ACCESSOR_H_
|
@ -31,6 +31,12 @@ inline size_t LiteralDataAccessor::GetLiteralValsNum(size_t index)
|
||||
return num;
|
||||
}
|
||||
|
||||
inline size_t LiteralDataAccessor::GetLiteralValsNum(File::EntityId id) const
|
||||
{
|
||||
auto sp = panda_file_.GetSpanFromId(id);
|
||||
return helpers::Read<LEN_SIZE>(&sp);
|
||||
}
|
||||
|
||||
template <class Callback>
|
||||
inline void LiteralDataAccessor::EnumerateLiteralVals(size_t index, const Callback &cb)
|
||||
{
|
||||
|
@ -71,6 +71,7 @@ public:
|
||||
void EnumerateLiteralVals(File::EntityId id, const Callback &cb);
|
||||
|
||||
size_t GetLiteralValsNum(size_t index);
|
||||
size_t GetLiteralValsNum(File::EntityId id) const;
|
||||
|
||||
uint32_t GetLiteralNum() const
|
||||
{
|
||||
|
@ -102,9 +102,13 @@ inline BytecodeId BytecodeInst<Mode>::GetId() const {
|
||||
// Disable check due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
|
||||
// NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
|
||||
if (format == Format::<%= fmt.pretty.upcase %>) {
|
||||
constexpr std::array<uint8_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<uint8_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
% if offsets.length == 1 && widths.length == 1
|
||||
return BytecodeId(static_cast<uint32_t>(Read<<%= offsets[0] %>, <%= widths[0] %>>()));
|
||||
% else
|
||||
constexpr std::array<size_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
return BytecodeId(static_cast<uint32_t>(Read<OFFSETS[idx], WIDTHS[idx]>()));
|
||||
% end
|
||||
}
|
||||
|
||||
% end
|
||||
@ -132,8 +136,8 @@ inline void BytecodeInst<Mode>::UpdateId(BytecodeId new_id, uint32_t idx /* = 0
|
||||
// Disable check due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
|
||||
// NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
|
||||
if (format == Format::<%= fmt.pretty.upcase %>) {
|
||||
constexpr std::array<uint8_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<uint8_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
this->Write(new_id.AsRawValue(), OFFSETS[idx] / 8, WIDTHS[idx] / 8);
|
||||
return;
|
||||
}
|
||||
@ -162,8 +166,8 @@ inline BytecodeId BytecodeInst<Mode>::GetId(size_t idx /* = 0 */) const {
|
||||
% widths = id_ops.map(&:width)
|
||||
%
|
||||
case Format::<%= fmt.pretty.upcase %>: {
|
||||
constexpr std::array<uint8_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<uint8_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
return BytecodeId(static_cast<uint32_t>(Read64(OFFSETS[idx], WIDTHS[idx])));
|
||||
}
|
||||
% end
|
||||
@ -193,8 +197,8 @@ ALWAYS_INLINE inline uint16_t BytecodeInst<Mode>::GetVReg() const { // NOLINTNE
|
||||
// Disable check due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
|
||||
// NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
|
||||
if constexpr (format == Format::<%= fmt.pretty.upcase %>) {
|
||||
constexpr std::array<uint8_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<uint8_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
return static_cast<uint16_t>(Read<OFFSETS[idx], WIDTHS[idx]>());
|
||||
}
|
||||
|
||||
@ -223,8 +227,8 @@ ALWAYS_INLINE inline uint16_t BytecodeInst<Mode>::GetVReg(size_t idx /* = 0 */)
|
||||
% widths = reg_ops.map(&:width)
|
||||
%
|
||||
case Format::<%= fmt.pretty.upcase %>: {
|
||||
constexpr std::array<uint8_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<uint8_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
if (idx > <%= n - 1 %>) {
|
||||
break;
|
||||
}
|
||||
@ -256,8 +260,8 @@ inline auto BytecodeInst<Mode>::GetImm() const { // NOLINTNEXTLINE(readability-
|
||||
// Disable check due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
|
||||
// NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
|
||||
if constexpr (format == Format::<%= fmt.pretty.upcase %>) {
|
||||
constexpr std::array<uint8_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<uint8_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
return Read<OFFSETS[idx], WIDTHS[idx], true>();
|
||||
}
|
||||
|
||||
@ -285,8 +289,8 @@ inline auto BytecodeInst<Mode>::GetImm64(size_t idx /* = 0 */) const {
|
||||
% widths = imm_ops.map(&:width)
|
||||
%
|
||||
case Format::<%= fmt.pretty.upcase %>: {
|
||||
constexpr std::array<uint8_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<uint8_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> OFFSETS{<%= offsets.join(", ") %>};
|
||||
constexpr std::array<size_t, <%= n %>> WIDTHS{<%= widths.join(", ") %>};
|
||||
return Read64<true>(OFFSETS[idx], WIDTHS[idx]);
|
||||
}
|
||||
% end
|
||||
@ -327,7 +331,13 @@ inline bool BytecodeInst<Mode>::IsPrefixed() const {
|
||||
|
||||
template <const BytecodeInstMode Mode>
|
||||
inline typename BytecodeInst<Mode>::Format BytecodeInst<Mode>::GetFormat() const { // NOLINT(readability-function-size)
|
||||
switch(GetOpcode()) {
|
||||
return GetFormat(GetOpcode());
|
||||
}
|
||||
|
||||
/* static */
|
||||
template <const BytecodeInstMode Mode>
|
||||
constexpr typename BytecodeInst<Mode>::Format BytecodeInst<Mode>::GetFormat(Opcode opcode) { // NOLINT(readability-function-size)
|
||||
switch(opcode) {
|
||||
% Panda::instructions.each do |i|
|
||||
case BytecodeInst<Mode>::Opcode::<%= i.opcode.upcase %>:
|
||||
return BytecodeInst<Mode>::Format::<%= i.format.pretty.upcase %>;
|
||||
@ -343,7 +353,7 @@ inline typename BytecodeInst<Mode>::Format BytecodeInst<Mode>::GetFormat() const
|
||||
template<const BytecodeInstMode Mode> inline bool BytecodeInst<Mode>::HasFlag(Flags flag) const {
|
||||
switch(GetOpcode()) {
|
||||
% Panda::instructions.each do |i|
|
||||
% flag_array = i.properties.map {|prop| "Flags::" + prop.upcase}
|
||||
% flag_array = i.real_properties.map {|prop| "Flags::" + prop.upcase}
|
||||
% flag_array += ['0'] if flag_array.empty?
|
||||
% flags = flag_array.join(' | ')
|
||||
case BytecodeInst<Mode>::Opcode::<%= i.opcode.upcase %>:
|
||||
|
Loading…
Reference in New Issue
Block a user