From ec29bb58e31764b19b170f8bbe111cdd6d3a87ea Mon Sep 17 00:00:00 2001 From: aakmaev Date: Mon, 10 Apr 2023 18:18:16 +0300 Subject: [PATCH] Support init obj for string Signed-off-by: Akmaev Alexey --- bytecode_optimizer/runtime_adapter.h | 18 +++++ .../optimizer/analysis/alias_analysis.cpp | 8 ++ compiler/optimizer/analysis/alias_analysis.h | 4 + compiler/optimizer/code_generator/codegen.cpp | 33 ++++++++ compiler/optimizer/code_generator/codegen.h | 6 ++ compiler/optimizer/ir/inst.h | 58 ++++++++++++++ compiler/optimizer/ir/instructions.yaml | 12 +++ compiler/optimizer/ir/runtime_interface.h | 5 ++ .../optimizer/ir_builder/inst_builder-inl.h | 76 ++++++++++++++++++- compiler/optimizer/ir_builder/inst_builder.h | 2 + compiler/tests/inst_generator.cpp | 3 + compiler/tests/ir_builder_test.cpp | 25 ++++++ plugins/ets/tests/checked/string_test.ets | 2 +- .../ets_test_suite/strings/string_api.ets | 3 + runtime/CMakeLists.txt | 1 + runtime/compiler.h | 5 ++ runtime/entrypoints/entrypoints.cpp | 39 ++++++++++ runtime/entrypoints/entrypoints.yaml | 16 ++++ 18 files changed, 312 insertions(+), 4 deletions(-) diff --git a/bytecode_optimizer/runtime_adapter.h b/bytecode_optimizer/runtime_adapter.h index fd05b8b22..c4684868d 100644 --- a/bytecode_optimizer/runtime_adapter.h +++ b/bytecode_optimizer/runtime_adapter.h @@ -173,6 +173,16 @@ public: return static_cast(source_lang.value()); } + SourceLanguage GetClassSourceLanguage(ClassPtr cls) const + { + panda_file::ClassDataAccessor cda(panda_file_, ClassCast(cls)); + + auto source_lang = cda.GetSourceLang(); + ASSERT(source_lang.has_value()); + + return static_cast(source_lang.value()); + } + size_t GetClassIdForField([[maybe_unused]] MethodPtr method, size_t field_id) const override { panda_file::FieldDataAccessor fda(panda_file_, panda_file::File::EntityId(field_id)); @@ -300,6 +310,14 @@ public: return panda_file::IsArrayDescriptor(panda_file_.GetStringData(cid).data); } + bool IsStringClass(MethodPtr method, IdType id) const override + { + panda_file::File::EntityId cid(id); + std::string lang_str_descr = panda_file::GetStringClassDescriptor(GetClassSourceLanguage(GetClass(method))); + std::string id_descr = utf::Mutf8AsCString(panda_file_.GetStringData(cid).data); + return lang_str_descr == id_descr; + } + FieldPtr ResolveField([[maybe_unused]] MethodPtr method, size_t id, [[maybe_unused]] bool allow_external, uint32_t * /* class_id */) override { diff --git a/compiler/optimizer/analysis/alias_analysis.cpp b/compiler/optimizer/analysis/alias_analysis.cpp index 491d3baf3..44b7f5de9 100644 --- a/compiler/optimizer/analysis/alias_analysis.cpp +++ b/compiler/optimizer/analysis/alias_analysis.cpp @@ -758,6 +758,14 @@ void AliasAnalysis::VisitInitObject(GraphVisitor *v, Inst *inst) { static_cast(v)->AddDirectEdge(Pointer::CreateObject(inst)); } +void AliasAnalysis::VisitInitEmptyString(GraphVisitor *v, Inst *inst) +{ + static_cast(v)->AddDirectEdge(Pointer::CreateObject(inst)); +} +void AliasAnalysis::VisitInitString(GraphVisitor *v, Inst *inst) +{ + static_cast(v)->AddDirectEdge(Pointer::CreateObject(inst)); +} void AliasAnalysis::VisitNewObject(GraphVisitor *v, Inst *inst) { static_cast(v)->AddDirectEdge(Pointer::CreateObject(inst)); diff --git a/compiler/optimizer/analysis/alias_analysis.h b/compiler/optimizer/analysis/alias_analysis.h index f558c7270..e82a63025 100644 --- a/compiler/optimizer/analysis/alias_analysis.h +++ b/compiler/optimizer/analysis/alias_analysis.h @@ -163,6 +163,8 @@ private: return true; case Opcode::NewArray: case Opcode::MultiArray: + case Opcode::InitString: + case Opcode::InitEmptyString: case Opcode::NewObject: case Opcode::InitObject: return !IsEscapingAlias(inst); @@ -300,6 +302,8 @@ public: */ static void VisitNullPtr(GraphVisitor *v, Inst *inst); static void VisitInitObject(GraphVisitor *v, Inst *inst); + static void VisitInitEmptyString(GraphVisitor *v, Inst *inst); + static void VisitInitString(GraphVisitor *v, Inst *inst); static void VisitNewObject(GraphVisitor *v, Inst *inst); static void VisitNewArray(GraphVisitor *v, Inst *inst); static void VisitMultiArray(GraphVisitor *v, Inst *inst); diff --git a/compiler/optimizer/code_generator/codegen.cpp b/compiler/optimizer/code_generator/codegen.cpp index 865dd79bd..84973f343 100644 --- a/compiler/optimizer/code_generator/codegen.cpp +++ b/compiler/optimizer/code_generator/codegen.cpp @@ -1182,6 +1182,21 @@ void Codegen::CreateMultiArrayCall(CallInst *call_inst) } } +void Codegen::CreateInitEmptyStringCall(StringInitInst *str_init) +{ + auto dst = ConvertRegister(str_init->GetDstReg(), str_init->GetType()); + CallRuntime(str_init, EntrypointId::CREATE_INIT_EMPTY_STRING, dst, RegMask::GetZeroMask()); +} + +void Codegen::CreateInitStringCall(StringInitInst *str_init) +{ + auto dst = ConvertRegister(str_init->GetDstReg(), str_init->GetType()); + auto ctor_arg = ConvertRegister(str_init->GetSrcReg(0), str_init->GetInputType(0)); + + CallRuntime(str_init, EntrypointId::CREATE_INIT_STRING, dst, RegMask::GetZeroMask(), ctor_arg, + TypedImm(str_init->GetArgTypeAsUint())); +} + void Codegen::CreateJumpToClassResolverPltShared(Inst *inst, Reg tmp_reg, RuntimeInterface::EntrypointId id) { auto encoder = GetEncoder(); @@ -4585,6 +4600,24 @@ void EncodeVisitor::VisitMultiArray(GraphVisitor *visitor, Inst *inst) } } +void EncodeVisitor::VisitInitEmptyString(GraphVisitor *visitor, Inst *inst) +{ + auto *enc = static_cast(visitor); + auto codegen = enc->GetCodegen(); + + auto init_str_inst = inst->CastToInitEmptyString(); + codegen->CreateInitEmptyStringCall(init_str_inst); +} + +void EncodeVisitor::VisitInitString(GraphVisitor *visitor, Inst *inst) +{ + auto *enc = static_cast(visitor); + auto codegen = enc->GetCodegen(); + + auto init_str_inst = inst->CastToInitString(); + codegen->CreateInitStringCall(init_str_inst); +} + void EncodeVisitor::VisitResolveStatic(GraphVisitor *visitor, Inst *inst) { auto *enc = static_cast(visitor); diff --git a/compiler/optimizer/code_generator/codegen.h b/compiler/optimizer/code_generator/codegen.h index 3e76fac24..9d99df7a9 100644 --- a/compiler/optimizer/code_generator/codegen.h +++ b/compiler/optimizer/code_generator/codegen.h @@ -392,6 +392,8 @@ public: void VisitCallIndirect(CallIndirectInst *inst); void VisitCall(CallInst *inst); void CreateCallIntrinsic(IntrinsicInst *inst); + void CreateInitEmptyStringCall(StringInitInst *call_inst); + void CreateInitStringCall(StringInitInst *call_inst); void CreateMultiArrayCall(CallInst *call_inst); void CreateNewObjCall(NewObjectInst *new_obj); void CreateNewObjCallOld(NewObjectInst *new_obj); @@ -980,6 +982,10 @@ protected: static void VisitMultiArray(GraphVisitor *visitor, Inst *inst); + static void VisitInitEmptyString(GraphVisitor *visitor, Inst *inst); + + static void VisitInitString(GraphVisitor *visitor, Inst *inst); + static void VisitCallStatic(GraphVisitor *visitor, Inst *inst); static void VisitResolveStatic(GraphVisitor *visitor, Inst *inst); diff --git a/compiler/optimizer/ir/inst.h b/compiler/optimizer/ir/inst.h index e3b39be92..f6a373261 100644 --- a/compiler/optimizer/ir/inst.h +++ b/compiler/optimizer/ir/inst.h @@ -1024,6 +1024,10 @@ public: { return GetOpcode() == Opcode::MultiArray; } + bool IsInitString() const + { + return GetOpcode() == Opcode::InitString || GetOpcode() == Opcode::InitEmptyString; + } bool IsDynamicCall() const { return GetOpcode() == Opcode::CallDynamic; @@ -3986,6 +3990,60 @@ public: return OPTIONS.GetCompilerSchedLatencyLong(); } }; +/** + * Init string object via specified constructor + */ +class StringInitInst : public FixedInputsInst1 { +public: + DECLARE_INST(StoreInst); + using Base = FixedInputsInst1; + using Base::Base; + + enum class ArgCtorType : uint8_t { STRING = 0x0, CHAR_ARRAY = 0x1 }; + + void SetArgType(ArgCtorType arg_type) + { + arg_type_ = arg_type; + } + ArgCtorType GetArgType() const + { + return arg_type_; + } + uint8_t GetArgTypeAsUint() const + { + return static_cast(arg_type_); + } + bool IsEmpty() const + { + return GetInputType(0) == DataType::NO_TYPE; + } + bool IsFromString() const + { + return arg_type_ == ArgCtorType::STRING; + } + bool IsFromCharArr() const + { + return arg_type_ == ArgCtorType::CHAR_ARRAY; + } + Inst *GetCtorArg() + { + ASSERT(!IsEmpty()); + return GetInput(0U).GetInst(); + } + DataType::Type GetInputType(size_t index) const override + { + ASSERT(index < GetInputsCount()); + if (index == 0) { + auto input_type = GetInput(0).GetInst()->GetType(); + ASSERT(input_type == DataType::ANY || input_type == DataType::REFERENCE || input_type == DataType::NO_TYPE); + return input_type; + } + return DataType::NO_TYPE; + } + +private: + ArgCtorType arg_type_; +}; /** * Store value into array element */ diff --git a/compiler/optimizer/ir/instructions.yaml b/compiler/optimizer/ir/instructions.yaml index f5360cf16..7b5c5841e 100644 --- a/compiler/optimizer/ir/instructions.yaml +++ b/compiler/optimizer/ir/instructions.yaml @@ -291,6 +291,18 @@ instructions: fields: - type_id: TypeId + - opcode: InitEmptyString + base: StringInitInst + signature: [d-ref, save_state] + flags: [can_throw, no_dce, no_hoist, no_cse, alloc, require_state, runtime_call, acc_write] + description: Create and initialize new empty string object. + + - opcode: InitString + base: StringInitInst + signature: [d-ref, ref-nc] + flags: [can_throw, no_dce, no_hoist, no_cse, alloc, runtime_call, acc_write] + description: Create and initialize new string object. + - opcode: LoadArray base: LoadInst signature: [d-real-any, ref-any-nc, int-bc] diff --git a/compiler/optimizer/ir/runtime_interface.h b/compiler/optimizer/ir/runtime_interface.h index d9204e8a5..726e762ef 100644 --- a/compiler/optimizer/ir/runtime_interface.h +++ b/compiler/optimizer/ir/runtime_interface.h @@ -404,6 +404,11 @@ public: return "UnknownMethod"; } + virtual std::string GetMethodArgName([[maybe_unused]] MethodPtr method, [[maybe_unused]] size_t idx) const + { + return "UnknownArg"; + } + std::string GetMethodFullName(MethodPtr method) const { return GetMethodFullName(method, false); diff --git a/compiler/optimizer/ir_builder/inst_builder-inl.h b/compiler/optimizer/ir_builder/inst_builder-inl.h index e67b0bf5f..88165c0b5 100644 --- a/compiler/optimizer/ir_builder/inst_builder-inl.h +++ b/compiler/optimizer/ir_builder/inst_builder-inl.h @@ -1201,6 +1201,73 @@ CallInst *InstBuilder::BuildCallStaticForInitObject(const BytecodeInstruction *b return call; } +// NOLINTNEXTLINE(misc-definitions-in-headers) +void InstBuilder::BuildInitStringIntrinsic(const BytecodeInstruction *bc_inst) +{ + auto method_index = bc_inst->GetId(0).AsIndex(); + auto method_id = GetRuntime()->ResolveMethodIndex(GetMethod(), method_index); + auto pc = GetPc(bc_inst->GetAddress()); + auto save_state = CreateSaveState(Opcode::SaveState, pc); + AddInstruction(save_state); + + size_t args_count = GetMethodArgumentsCount(method_id); + + StringInitInst *inst = nullptr; + if (args_count == 0) { + inst = GetGraph()->CreateInstInitEmptyString(DataType::REFERENCE, pc); + inst->SetInput(0, save_state); + } else if (args_count == 1) { + inst = GetGraph()->CreateInstInitString(DataType::REFERENCE, pc); + auto method = GetRuntime()->GetMethodById(GetMethod(), method_id); + ASSERT(GetRuntime()->GetMethodTotalArgumentType(method, 1) == DataType::REFERENCE); + inst->SetArgType(GetRuntime()->GetMethodArgName(method, 1) == "[C" ? StringInitInst::ArgCtorType::CHAR_ARRAY + : StringInitInst::ArgCtorType::STRING); + auto null_check = graph_->CreateInstNullCheck(DataType::REFERENCE, pc); + null_check->SetInput(0, GetDefinition(bc_inst->GetVReg(0))); + null_check->SetInput(1, save_state); + inst->SetInput(0, null_check); + AddInstruction(null_check); + } + + AddInstruction(inst); + UpdateDefinitionAcc(inst); +} + +// NOLINTNEXTLINE(misc-definitions-in-headers) +void InstBuilder::BuildInitObjectString(const BytecodeInstruction *bc_inst) +{ + auto method_index = bc_inst->GetId(0).AsIndex(); + auto method_id = GetRuntime()->ResolveMethodIndex(GetMethod(), method_index); + auto class_id = GetRuntime()->GetClassIdForMethod(GetMethod(), method_id); + auto pc = GetPc(bc_inst->GetAddress()); + auto save_state = CreateSaveState(Opcode::SaveState, pc); + size_t args_count = GetMethodArgumentsCount(method_id); + + auto *inst = GetGraph()->CreateInstInitObject(DataType::REFERENCE, pc, method_id); + + auto init_class = graph_->CreateInstLoadAndInitClass(DataType::REFERENCE, pc); + init_class->SetInput(0, save_state); + init_class->SetTypeId(class_id); + init_class->SetMethod(GetGraph()->GetMethod()); + init_class->SetClass(GetRuntime()->ResolveType(GetGraph()->GetMethod(), class_id)); + inst->ReserveInputs(ONE_FOR_OBJECT + args_count + ONE_FOR_SSTATE); + inst->AllocateInputTypes(GetGraph()->GetAllocator(), ONE_FOR_OBJECT + args_count + ONE_FOR_SSTATE); + inst->AppendInput(init_class); + inst->AddInputType(DataType::REFERENCE); + + if (args_count == 1) { + inst->AppendInput(GetDefinition(bc_inst->GetVReg(0))); + inst->AddInputType(GetMethodArgumentType(method_id, 0)); + } + inst->AppendInput(save_state); + inst->AddInputType(DataType::NO_TYPE); + + inst->SetCallMethod(GetRuntime()->GetMethodById(GetGraph()->GetMethod(), method_id)); + + AddInstruction(save_state, init_class, inst); + UpdateDefinitionAcc(inst); +} + // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildInitObject(const BytecodeInstruction *bc_inst, bool is_range) { @@ -1215,9 +1282,12 @@ void InstBuilder::BuildInitObject(const BytecodeInstruction *bc_inst, bool is_ra } return; } - // TODO (pishin) support InitObj for string - if (GetRuntime()->IsStringClass(GetMethod(), type_id) && !GetGraph()->IsBytecodeOptimizer()) { - failed_ = true; + if (GetRuntime()->IsStringClass(GetMethod(), type_id)) { + if (GetGraph()->IsBytecodeOptimizer()) { + BuildInitObjectString(bc_inst); + } else { + BuildInitStringIntrinsic(bc_inst); + } return; } diff --git a/compiler/optimizer/ir_builder/inst_builder.h b/compiler/optimizer/ir_builder/inst_builder.h index 98373c88e..40733c356 100644 --- a/compiler/optimizer/ir_builder/inst_builder.h +++ b/compiler/optimizer/ir_builder/inst_builder.h @@ -373,6 +373,8 @@ private: void BuildBinaryOperationIntrinsic(const BytecodeInstruction *bc_inst, bool acc_read); void BuildSqrtIntrinsic(const BytecodeInstruction *bc_inst, bool acc_read); void BuildIsNanIntrinsic(const BytecodeInstruction *bc_inst, bool acc_read); + void BuildInitStringIntrinsic(const BytecodeInstruction *bc_inst); + void BuildInitObjectString(const BytecodeInstruction *bc_inst); void BuildMonitorIntrinsic(const BytecodeInstruction *bc_inst, bool is_enter, bool acc_read); void BuildDefaultStaticIntrinsic(const BytecodeInstruction *bc_inst, bool is_range, bool acc_read); void BuildDefaultVirtualCallIntrinsic(const BytecodeInstruction *bc_inst, bool is_range, bool acc_read); diff --git a/compiler/tests/inst_generator.cpp b/compiler/tests/inst_generator.cpp index b07a37f7d..6efe8f122 100644 --- a/compiler/tests/inst_generator.cpp +++ b/compiler/tests/inst_generator.cpp @@ -1085,6 +1085,9 @@ std::vector &InstGenerator::Generate(Opcode op_code) return GenerateOperations(op_code); case Opcode::NewObject: return GenerateOperations(op_code); + case Opcode::InitEmptyString: + case Opcode::InitString: + return GenerateOperations(op_code); case Opcode::If: return GenerateOperations(op_code); case Opcode::IfImm: diff --git a/compiler/tests/ir_builder_test.cpp b/compiler/tests/ir_builder_test.cpp index 5ed807b13..94e8f98a1 100644 --- a/compiler/tests/ir_builder_test.cpp +++ b/compiler/tests/ir_builder_test.cpp @@ -4315,6 +4315,31 @@ TEST_F(IrBuilderTest, Initobj) ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); } +TEST_F(IrBuilderTest, InitEmptyString) +{ + auto source = R"( + .record panda.String + + .function panda.String main(){ + initobj.short panda.String.ctor + return + } + .function void panda.String.ctor() + )"; + ASSERT_TRUE(ParseToGraph(source, "main")); + auto graph = CreateGraphWithDefaultRuntime(); + GRAPH(graph) + { + BASIC_BLOCK(2, -1) + { + INST(0, Opcode::SaveState).Inputs().SrcVregs({}); + INST(1, Opcode::InitEmptyString).ref().Inputs(0); + INST(2, Opcode::Return).ref().Inputs(1); + } + } + ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); +} + // Enable after supporting MultiArray in panda assembly TEST_F(IrBuilderTest, DISABLED_MultiArray) { diff --git a/plugins/ets/tests/checked/string_test.ets b/plugins/ets/tests/checked/string_test.ets index e6c6e478b..b52ffa860 100644 --- a/plugins/ets/tests/checked/string_test.ets +++ b/plugins/ets/tests/checked/string_test.ets @@ -1,6 +1,6 @@ //! CHECKER Test check initobj for string in compiler //! RUN force_jit: true, options: "--compiler-ignore-failures=true", entry: "ETSGLOBAL::main" -//! EVENT /Compilation,ETSGLOBAL::main,.*,FAILED/ +//! EVENT /Compilation,ETSGLOBAL::main,.*,COMPILED/ function main(): void { let str1: String = new String(); assert str1.length() == 0: "String is not empty"; diff --git a/plugins/ets/tests/ets_test_suite/strings/string_api.ets b/plugins/ets/tests/ets_test_suite/strings/string_api.ets index 0fdb04ede..f7a5fdbad 100644 --- a/plugins/ets/tests/ets_test_suite/strings/string_api.ets +++ b/plugins/ets/tests/ets_test_suite/strings/string_api.ets @@ -11,6 +11,9 @@ function main(): void { assert str2.charAt(8) == 'z': "Wrong str2.charAt(8)"; assert str2.charAt(8) != 'Z': "Wrong str2.charAt(8): invalid character case"; + let strstr: String = new String(str2); + assert strstr.equals(str2): "Strings `" + strstr + "` and `" + str2 + "` must be equal"; + let cb: StringBuilder = new StringBuilder("abc123"); let str3: String = "abc123"; assert str3.contentEquals(cb): "contentEquals is wrong"; diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index ba54c9362..23269ee3e 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -379,6 +379,7 @@ elseif (PANDA_LLVMAOT AND PANDA_LLVMAOT_IR_INLINING) PRIVATE ${PANDA_BINARY_ROOT}/compiler/generated PRIVATE ${PANDA_BINARY_ROOT}/libpandafile/include PRIVATE ${PANDA_BINARY_ROOT}/libpandabase/generated + PRIVATE ${PANDA_BINARY_ROOT}/cross_values PRIVATE ${VERIFIER_INCLUDE_DIR} PRIVATE ${PANDA_BINARY_ROOT} ) diff --git a/runtime/compiler.h b/runtime/compiler.h index e93580738..972f8a82d 100644 --- a/runtime/compiler.h +++ b/runtime/compiler.h @@ -349,6 +349,11 @@ public: return std::string(MethodCast(method)->GetFullName(with_signature)); } + std::string GetMethodArgName(MethodPtr method, size_t idx) const override + { + return panda::ClassHelper::GetName(MethodCast(method)->GetRefArgType(idx).data); + } + ClassPtr GetClass(MethodPtr method) const override { ScopedMutatorLock lock; diff --git a/runtime/entrypoints/entrypoints.cpp b/runtime/entrypoints/entrypoints.cpp index 9f6f27f9a..9b612552d 100644 --- a/runtime/entrypoints/entrypoints.cpp +++ b/runtime/entrypoints/entrypoints.cpp @@ -202,6 +202,20 @@ extern "C" coretypes::Array *CreateMultiArrayRecEntrypoint(ManagedThread *thread return handle.GetPtr(); } +extern "C" coretypes::String *CreateInitStringRecEntrypoint(ObjectHeader *obj, uint8_t is_array) +{ + LanguageContext ctx = Runtime::GetCurrent()->GetPandaVM()->GetLanguageContext(); + if (is_array) { + auto *array = reinterpret_cast(obj); + return coretypes::String::CreateNewStringFromChars(0, array->GetLength(), array, ctx, + Runtime::GetCurrent()->GetPandaVM()); + } else { + return coretypes::String::CreateFromString(reinterpret_cast(obj), ctx, + Runtime::GetCurrent()->GetPandaVM()); + } + return nullptr; +} + extern "C" coretypes::Array *ResolveLiteralArrayEntrypoint(const Method *caller, uint32_t type_id) { BEGIN_ENTRYPOINT(); @@ -226,6 +240,31 @@ extern "C" coretypes::Array *CreateMultiArrayEntrypoint(Class *klass, uint32_t n return arr; } +extern "C" coretypes::String *CreateInitEmptyStringEntrypoint() +{ + BEGIN_ENTRYPOINT(); + + auto *vm = Runtime::GetCurrent()->GetPandaVM(); + auto str = coretypes::String::CreateEmptyString(vm->GetLanguageContext(), vm); + if (UNLIKELY(str == nullptr)) { + HandlePendingException(); + UNREACHABLE(); + } + return str; +} + +extern "C" coretypes::String *CreateInitStringEntrypoint(panda::ObjectHeader *obj, uint8_t is_array) +{ + BEGIN_ENTRYPOINT(); + + auto str = CreateInitStringRecEntrypoint(obj, is_array); + if (UNLIKELY(str == nullptr)) { + HandlePendingException(); + UNREACHABLE(); + } + return str; +} + extern "C" ObjectHeader *CreateObjectByClassEntrypoint(Class *klass) { BEGIN_ENTRYPOINT(); diff --git a/runtime/entrypoints/entrypoints.yaml b/runtime/entrypoints/entrypoints.yaml index afb3aae96..6e3c4013c 100644 --- a/runtime/entrypoints/entrypoints.yaml +++ b/runtime/entrypoints/entrypoints.yaml @@ -237,6 +237,22 @@ entrypoints: signature: - void +- name: CreateInitEmptyString + entrypoint: CreateInitEmptyStringEntrypoint + bridge: none + properties: [] + signature: + - panda::coretypes::String* + +- name: CreateInitString + entrypoint: CreateInitStringEntrypoint + bridge: none + properties: [] + signature: + - panda::coretypes::String* + - panda::ObjectHeader* + - uint8_t + - name: CreateMultiArray entrypoint: CreateMultiArrayEntrypoint bridge: entrypoint -- Gitee