From 192be3ed1c62e7eca49fc0d0bf588661a39e45df Mon Sep 17 00:00:00 2001 From: Ishin Pavel Date: Thu, 26 Oct 2023 18:35:12 +0300 Subject: [PATCH] Support Parametr instruction in Object Type propogation Signed-off-by: Ishin Pavel --- .../analysis/object_type_propagation.cpp | 27 ++++++++++++ .../analysis/object_type_propagation.h | 1 + compiler/optimizer/ir/inst.h | 10 +++++ compiler/optimizer/ir/runtime_interface.h | 10 +++++ .../optimizer/ir_builder/inst_builder.cpp | 10 ++++- runtime/compiler.cpp | 41 +++++++++++++++++++ runtime/compiler.h | 2 + 7 files changed, 100 insertions(+), 1 deletion(-) diff --git a/compiler/optimizer/analysis/object_type_propagation.cpp b/compiler/optimizer/analysis/object_type_propagation.cpp index a13e8c4b3..8be029e52 100644 --- a/compiler/optimizer/analysis/object_type_propagation.cpp +++ b/compiler/optimizer/analysis/object_type_propagation.cpp @@ -116,6 +116,33 @@ void ObjectTypePropagation::VisitRefTypeCheck([[maybe_unused]] GraphVisitor *v, inst->SetObjectTypeInfo(inst->GetInput(0).GetInst()->GetObjectTypeInfo()); } +void ObjectTypePropagation::VisitParameter([[maybe_unused]] GraphVisitor *v, Inst *i) +{ + auto inst = i->CastToParameter(); + auto graph = i->GetBasicBlock()->GetGraph(); + if (inst->GetType() != DataType::REFERENCE || graph->IsBytecodeOptimizer() || inst->HasObjectTypeInfo()) { + return; + } + auto ref_num = inst->GetArgRefNumber(); + auto runtime = graph->GetRuntime(); + auto method = graph->GetMethod(); + RuntimeInterface::ClassPtr klass; + if (ref_num == ParameterInst::INVALID_ARG_REF_NUM) { + // This parametr doesn't have ArgRefNumber + if (inst->GetArgNumber() != 0 || runtime->IsMethodStatic(method)) { + return; + } + klass = runtime->GetClass(method); + } else { + auto type_id = runtime->GetMethodArgReferenceTypeId(method, ref_num); + klass = runtime->GetClass(method, type_id); + } + if (klass != nullptr) { + auto is_exact = runtime->GetClassType(klass) == ClassType::FINAL_CLASS; + inst->SetObjectTypeInfo({klass, is_exact}); + } +} + void ObjectTypePropagation::ProcessManagedCall(GraphVisitor *v, CallInst *inst) { if (inst->GetType() != DataType::REFERENCE) { diff --git a/compiler/optimizer/analysis/object_type_propagation.h b/compiler/optimizer/analysis/object_type_propagation.h index 1e85b86bc..40c6e7c17 100644 --- a/compiler/optimizer/analysis/object_type_propagation.h +++ b/compiler/optimizer/analysis/object_type_propagation.h @@ -45,6 +45,7 @@ public: protected: static void VisitNewObject(GraphVisitor *v, Inst *inst); + static void VisitParameter(GraphVisitor *v, Inst *inst); static void VisitNewArray(GraphVisitor *v, Inst *inst); static void VisitLoadArray(GraphVisitor *v, Inst *inst); static void VisitLoadString(GraphVisitor *v, Inst *inst); diff --git a/compiler/optimizer/ir/inst.h b/compiler/optimizer/ir/inst.h index d8df2419b..b1407c4ba 100644 --- a/compiler/optimizer/ir/inst.h +++ b/compiler/optimizer/ir/inst.h @@ -3791,6 +3791,7 @@ public: DECLARE_INST(ParameterInst); using Inst::Inst; static constexpr uint16_t DYNAMIC_NUM_ARGS = std::numeric_limits::max(); + static constexpr uint16_t INVALID_ARG_REF_NUM = std::numeric_limits::max(); explicit ParameterInst(Opcode /* unused */, uint16_t arg_number, DataType::Type type = DataType::NO_TYPE) : Inst(Opcode::Parameter, type, INVALID_PC), arg_number_(arg_number) @@ -3805,13 +3806,22 @@ public: { arg_number_ = arg_number; } + uint16_t GetArgRefNumber() const + { + return arg_ref_number_; + } + void SetArgRefNumber(uint16_t arg_ref_number) + { + arg_ref_number_ = arg_ref_number; + } bool DumpInputs(std::ostream * /* out */) const override; Inst *Clone(const Graph *target_graph) const override; private: uint16_t arg_number_ {0}; + uint16_t arg_ref_number_ {INVALID_ARG_REF_NUM}; }; inline bool IsZeroConstant(const Inst *inst) diff --git a/compiler/optimizer/ir/runtime_interface.h b/compiler/optimizer/ir/runtime_interface.h index f0f4a51cc..550bd2cea 100644 --- a/compiler/optimizer/ir/runtime_interface.h +++ b/compiler/optimizer/ir/runtime_interface.h @@ -205,6 +205,11 @@ public: return 0; } + virtual IdType GetMethodArgReferenceTypeId([[maybe_unused]] MethodPtr method, [[maybe_unused]] uint16_t num) const + { + return 0; + } + virtual void CleanObjectHandles([[maybe_unused]] MethodPtr method) {} // Return this argument type for index == 0 in case of instance method @@ -711,6 +716,11 @@ public: return ClassType::UNRESOLVED_CLASS; } + virtual ClassType GetClassType([[maybe_unused]] ClassPtr klass_ptr) const + { + return ClassType::UNRESOLVED_CLASS; + } + virtual bool IsArrayClass([[maybe_unused]] MethodPtr method, [[maybe_unused]] IdType id) const { return false; diff --git a/compiler/optimizer/ir_builder/inst_builder.cpp b/compiler/optimizer/ir_builder/inst_builder.cpp index 60dd9124c..4e46b54dd 100644 --- a/compiler/optimizer/ir_builder/inst_builder.cpp +++ b/compiler/optimizer/ir_builder/inst_builder.cpp @@ -73,8 +73,12 @@ void InstBuilder::Prepare(bool is_inlined_graph) param_inst->SetType(DataType::UINT32); param_inst->SetLocationData(GetGraph()->GetDataForNativeParam(DataType::UINT32)); } - + size_t arg_ref_num = 0; + if (GetRuntime()->GetMethodReturnType(GetMethod()) == DataType::REFERENCE) { + arg_ref_num = 1; + } auto num_args = GetRuntime()->GetMethodTotalArgumentsCount(GetMethod()); + bool is_static = GetRuntime()->IsMethodStatic(GetMethod()); // Create Parameter instructions for all arguments for (size_t i = 0; i < num_args; i++) { auto param_inst = GetGraph()->AddNewParameter(i); @@ -83,6 +87,10 @@ void InstBuilder::Prepare(bool is_inlined_graph) ASSERT(!GetGraph()->IsBytecodeOptimizer() || reg_num != INVALID_REG); param_inst->SetType(type); + // This parameter in virtaul method is implicit, so skipped + if (type == DataType::REFERENCE && (is_static || i > 0)) { + param_inst->SetArgRefNumber(arg_ref_num++); + } SetParamSpillFill(GetGraph(), param_inst, num_args, i, type); UpdateDefinition(reg_num, param_inst); diff --git a/runtime/compiler.cpp b/runtime/compiler.cpp index 29c26661f..4a83fd253 100644 --- a/runtime/compiler.cpp +++ b/runtime/compiler.cpp @@ -123,6 +123,15 @@ compiler::RuntimeInterface::IdType PandaRuntimeInterface::GetMethodReturnTypeId( return pda.GetReferenceType(0).GetOffset(); } +compiler::RuntimeInterface::IdType PandaRuntimeInterface::GetMethodArgReferenceTypeId(MethodPtr method, + uint16_t num) const +{ + auto *pf = MethodCast(method)->GetPandaFile(); + panda_file::ProtoDataAccessor pda(*pf, + panda_file::MethodDataAccessor::GetProtoId(*pf, MethodCast(method)->GetFileId())); + return pda.GetReferenceType(num).GetOffset(); +} + compiler::RuntimeInterface::ClassPtr PandaRuntimeInterface::GetClass(MethodPtr method, IdType id) const { ScopedMutatorLock lock; @@ -141,6 +150,38 @@ compiler::RuntimeInterface::ClassPtr PandaRuntimeInterface::GetStringClass(Metho return Runtime::GetCurrent()->GetClassLinker()->GetExtension(ctx)->GetClassRoot(ClassRoot::STRING); } +compiler::ClassType PandaRuntimeInterface::GetClassType(ClassPtr klass_ptr) const +{ + if (klass_ptr == nullptr) { + return compiler::ClassType::UNRESOLVED_CLASS; + } + auto klass = ClassCast(klass_ptr); + if (klass == nullptr) { + return compiler::ClassType::UNRESOLVED_CLASS; + } + if (klass->IsObjectClass()) { + return compiler::ClassType::OBJECT_CLASS; + } + if (klass->IsInterface()) { + return compiler::ClassType::INTERFACE_CLASS; + } + if (klass->IsArrayClass()) { + auto component_class = klass->GetComponentType(); + ASSERT(component_class != nullptr); + if (component_class->IsObjectClass()) { + return compiler::ClassType::ARRAY_OBJECT_CLASS; + } + if (component_class->IsPrimitive()) { + return compiler::ClassType::FINAL_CLASS; + } + return compiler::ClassType::ARRAY_CLASS; + } + if (klass->IsFinal()) { + return compiler::ClassType::FINAL_CLASS; + } + return compiler::ClassType::OTHER_CLASS; +} + compiler::ClassType PandaRuntimeInterface::GetClassType(MethodPtr method, IdType id) const { if (method == nullptr) { diff --git a/runtime/compiler.h b/runtime/compiler.h index 2b16398e7..86de89745 100644 --- a/runtime/compiler.h +++ b/runtime/compiler.h @@ -152,6 +152,7 @@ public: } IdType GetMethodReturnTypeId(MethodPtr method) const override; + IdType GetMethodArgReferenceTypeId(MethodPtr method, uint16_t num) const override; compiler::DataType::Type GetMethodTotalArgumentType(MethodPtr method, size_t index) const override { @@ -421,6 +422,7 @@ public: ClassPtr GetClass(MethodPtr method, IdType id) const override; compiler::ClassType GetClassType(MethodPtr method, IdType id) const override; + compiler::ClassType GetClassType(ClassPtr klass_ptr) const override; bool IsArrayClass(MethodPtr method, IdType id) const override; -- Gitee