diff --git a/static_core/assembler/assembly-emitter.cpp b/static_core/assembler/assembly-emitter.cpp index a7532ae94409cf2610ede8c8eff4f2dc6dd5e5d6..cb0e94137b474852173f709c264caab346e2e579 100644 --- a/static_core/assembler/assembly-emitter.cpp +++ b/static_core/assembler/assembly-emitter.cpp @@ -841,7 +841,8 @@ static void AddBytecodeIndexDependencies(MethodItem *method, const Function &fun continue; } - if (insn.HasFlag(InstFlags::METHOD_ID)) { + bool isDevirtualCall = insn.IsDevirtual() && insn.HasFlag(InstFlags::STATIC_METHOD_ID); + if (insn.HasFlag(InstFlags::METHOD_ID) || isDevirtualCall) { AddBytecodeIndexDependencies(method, insn, entities.methodItems, entities); continue; } @@ -1628,6 +1629,7 @@ void AsmEmitter::FillMap(PandaFileToPandaAsmMaps *maps, AsmEmitter::AsmEntityCol for (const auto &[name, method] : entities.staticMethodItems) { maps->methods.insert({method->GetFileId().GetOffset(), std::string(name)}); + maps->staticMethods.insert(method->GetFileId().GetOffset()); } for (const auto &[name, field] : entities.fieldItems) { diff --git a/static_core/assembler/assembly-emitter.h b/static_core/assembler/assembly-emitter.h index 52b3525bba6c03115128fff806c46ecf68ec9a64..65bde23eab456dfd7ba7038f4c0c69fdb931b2a5 100644 --- a/static_core/assembler/assembly-emitter.h +++ b/static_core/assembler/assembly-emitter.h @@ -40,6 +40,7 @@ public: std::unordered_map classes; std::unordered_map strings; std::unordered_map literalarrays; + std::unordered_set staticMethods; }; struct AsmEntityCollections { diff --git a/static_core/assembler/assembly-ins.h b/static_core/assembler/assembly-ins.h index 862e2ff5d4d46679c86dc3eae2914e66edc630f2..831102b59781e18146241e62576ec09fe020e637 100644 --- a/static_core/assembler/assembly-ins.h +++ b/static_core/assembler/assembly-ins.h @@ -560,6 +560,16 @@ public: return insDebug.LineNumber() != 0U; } + bool IsDevirtual() const + { + return isDevirtual_; + } + + void SetIsDevirtual() + { + isDevirtual_ = true; + } + private: std::string OperandsToString(bool printArgs = false, size_t firstArgIdx = 0) const; std::string RegsToString(bool &first, bool printArgs = false, size_t firstArgIdx = 0) const; @@ -569,6 +579,7 @@ private: std::string IdToString(size_t idx, bool isFirst) const; std::string ImmToString(size_t idx, bool isFirst) const; std::string RegToString(size_t idx, bool isFirst, bool printArgs = false, size_t firstArgIdx = 0) const; + bool isDevirtual_ = false; }; // NOLINTEND(misc-non-private-member-variables-in-classes) diff --git a/static_core/assembler/templates/ins_emit.h.erb b/static_core/assembler/templates/ins_emit.h.erb index c80f200158a3791722b2a305d70d8de1d159f8c2..8bdfcc2ce9f4e62b06e6158bf7949a865ac73d5d 100644 --- a/static_core/assembler/templates/ins_emit.h.erb +++ b/static_core/assembler/templates/ins_emit.h.erb @@ -137,7 +137,7 @@ bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method, if (IDEmpty()) { return false; } - auto *foundMethod = GetMethodForHybridOpcode(GetID(0), staticMethods, methods); + auto *foundMethod = GetMethodForHybridOpcode(GetID(0), IsDevirtual() ? methods : staticMethods, methods); if (foundMethod == nullptr) { return false; } diff --git a/static_core/bytecode_optimizer/codegen.cpp b/static_core/bytecode_optimizer/codegen.cpp index 5cd4604fecdbec7e5aaf563f8143f576ede5f385..caf22b155ce150ecb2736ef4fef48cc5579d7ab3 100644 --- a/static_core/bytecode_optimizer/codegen.cpp +++ b/static_core/bytecode_optimizer/codegen.cpp @@ -493,7 +493,7 @@ static ark::compiler::CallInst *CastToCall(ark::compiler::Inst *inst) } } -void BytecodeGen::CallHandler(GraphVisitor *visitor, Inst *inst, std::string methodId) +void BytecodeGen::CallHandler(GraphVisitor *visitor, Inst *inst, std::string methodId, bool isDevirtual) { auto op = inst->GetOpcode(); ASSERT(op == compiler::Opcode::CallStatic || op == compiler::Opcode::CallVirtual || @@ -507,6 +507,9 @@ void BytecodeGen::CallHandler(GraphVisitor *visitor, Inst *inst, std::string met size_t start = op == compiler::Opcode::InitObject ? 1U : 0U; // exclude LoadAndInitClass auto nargs = sfCount - start; // exclude LoadAndInitClass pandasm::Ins ins {}; + if (isDevirtual) { + ins.SetIsDevirtual(); + } ins.opcode = ChooseCallOpcode(op, nargs); @@ -544,7 +547,8 @@ void BytecodeGen::CallHandler(GraphVisitor *visitor, Inst *inst) { auto *enc = static_cast(visitor); auto methodOffset = CastToCall(inst)->GetCallMethodId(); - CallHandler(visitor, inst, enc->irInterface_->GetMethodIdByOffset(methodOffset)); + bool isDevirtual = !enc->irInterface_->IsMethodStatic(methodOffset); + CallHandler(visitor, inst, enc->irInterface_->GetMethodIdByOffset(methodOffset), isDevirtual); } void BytecodeGen::VisitCallStatic(GraphVisitor *visitor, Inst *inst) diff --git a/static_core/bytecode_optimizer/codegen.h b/static_core/bytecode_optimizer/codegen.h index 5f7b32dd8531a671ba7bc08b3f8a838f9d98db40..7c410e2096263db5ebe6aae65c38a00d9b6999fc 100644 --- a/static_core/bytecode_optimizer/codegen.h +++ b/static_core/bytecode_optimizer/codegen.h @@ -125,7 +125,7 @@ public: static void IfImmNonZero(GraphVisitor *v, Inst *instBase); static void IfImm64(GraphVisitor *v, Inst *instBase); static void VisitIntrinsic(GraphVisitor *v, Inst *instBase); - static void CallHandler(GraphVisitor *visitor, Inst *inst, std::string methodId); + static void CallHandler(GraphVisitor *visitor, Inst *inst, std::string methodId, bool isDevirtual = false); static void CallHandler(GraphVisitor *visitor, Inst *inst); static void VisitStoreObject(GraphVisitor *v, Inst *instBase); static void VisitStoreStatic(GraphVisitor *v, Inst *instBase); diff --git a/static_core/bytecode_optimizer/ir_interface.h b/static_core/bytecode_optimizer/ir_interface.h index c0e07485c1fee935e05601a3a5cba27cf0293583..a741585e4e5ea3b0218854e1d4abfb4ac118aa49 100644 --- a/static_core/bytecode_optimizer/ir_interface.h +++ b/static_core/bytecode_optimizer/ir_interface.h @@ -33,6 +33,11 @@ public: NO_COPY_SEMANTIC(BytecodeOptIrInterface); NO_MOVE_SEMANTIC(BytecodeOptIrInterface); + virtual bool IsMethodStatic(uint32_t offset) const + { + return maps_->staticMethods.find(offset) != maps_->staticMethods.end(); + } + virtual std::string GetMethodIdByOffset(uint32_t offset) const { auto it = maps_->methods.find(offset); diff --git a/static_core/bytecode_optimizer/tests/common.h b/static_core/bytecode_optimizer/tests/common.h index 2b9f11808b66f2694c020f04bd48a1ce1a7fd20e..6900c4c171f57ec46f17ec6155b51115c47c48d9 100644 --- a/static_core/bytecode_optimizer/tests/common.h +++ b/static_core/bytecode_optimizer/tests/common.h @@ -103,6 +103,11 @@ public: { return ""; } + + bool IsMethodStatic(uint32_t offset) const override + { + return IsMapsSet() && BytecodeOptIrInterface::IsMethodStatic(offset); + } }; namespace test {