diff --git a/assembler/templates/ins_emit.h.erb b/assembler/templates/ins_emit.h.erb index 88dcce950993fec82946cc09132195234eb42ac6..748bdce8382a331689ffecdc94a3069d08e02f52 100644 --- a/assembler/templates/ins_emit.h.erb +++ b/assembler/templates/ins_emit.h.erb @@ -88,7 +88,7 @@ bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method, % end % end % ops << "profile_id" if insn.profiled? -% if insn.call? && insn.properties.include?('method_id') +% if insn.properties.include?('short_long_range') % ops << ops.shift % end % ops @@ -151,7 +151,7 @@ bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method, } % end % end -% if insn.simple_call? +% if insn.properties.include?('short_long_range') && !insn.mnemonic.include?('range') auto registers = regs; % call_mnemonics = if insn.mnemonic.end_with?('.short') % [insn.mnemonic] diff --git a/irtoc/templates/plugins.txt.erb b/irtoc/templates/plugins.txt.erb index 6c67fbbfbcf3af68b0188e82fce0a5bd66a2a11b..c0aff30a75bb5f7944d84fdb37cd7377be33dd82 100644 --- a/irtoc/templates/plugins.txt.erb +++ b/irtoc/templates/plugins.txt.erb @@ -14,8 +14,8 @@ %> % Common::plugins.each do |plugin_lang, plugin_opts| -% next unless plugin_opts["irtoc_files"] -% next unless plugin_opts["irtoc_files"].each do |name, file| +% next unless plugin_opts["irtoc_files"] +% plugin_opts["irtoc_files"].each do |name, file| <%= file %> +% end % end -% end \ No newline at end of file diff --git a/isa/isa.yaml b/isa/isa.yaml index a432b7374618e6440041d458f9b016f86fb65e2e..9ea99d37aa6d3ec39f6e519e57971d98736c2cfb 100644 --- a/isa/isa.yaml +++ b/isa/isa.yaml @@ -120,6 +120,8 @@ properties: description: Use an id which resolves into a constant literalarray. - tag: field_id description: Use an id which resolves into a field reference. + - tag: short_long_range + description: Instruction is used to pass arguments, exists in short, long and range forms. - tag: call description: Pass control to the callee method. - tag: call_virt @@ -1827,6 +1829,7 @@ groups: - call - initialize_type - init_obj + - short_long_range pseudo: | init, type = resolve(method_id) if not initialized(type) @@ -2213,7 +2216,6 @@ groups: be discarded and corresponding registers will not be passed to the callee). For methods with more arguments range kind of instruction is to be used, which takes the needed number of arguments starting from 'vs' register. - In dynamically-typed language context accept 'any' values in source registers. verification: - method_id_static - method_id_non_abstract @@ -2221,8 +2223,8 @@ groups: properties: - method_id - call - - maybe_dynamic - initialize_type + - short_long_range exceptions: - x_call pseudo: | @@ -2256,7 +2258,6 @@ groups: Arguments are passed in source registers in the same order as in method signature. Non-range instructions can be used to pass up to 4 arguments (unused register slot values will be discarded and corresponding registers will not be passed to the callee). - In dynamically-typed language context accept 'any' values in source registers. Immediate operand encodes a position starting from 0 on which accumulator is passed. verification: - method_id_static @@ -2265,7 +2266,7 @@ groups: properties: - method_id - call - - maybe_dynamic + - short_long_range exceptions: - x_call pseudo: | @@ -2319,6 +2320,7 @@ groups: - method_id - call - call_virt + - short_long_range pseudo: | if args[0] == null then throw NullPointerException @@ -2369,6 +2371,7 @@ groups: - method_id - call - call_virt + - short_long_range pseudo: | args = [] for (i = 0; i < 4; ++i) diff --git a/libpandafile/bytecode_instruction.h b/libpandafile/bytecode_instruction.h index 619105333c02fd48141d66948002d2576d17b7b0..0b3115104f5598509e78f33d74131797c3840777 100644 --- a/libpandafile/bytecode_instruction.h +++ b/libpandafile/bytecode_instruction.h @@ -409,6 +409,11 @@ public: static constexpr size_t Size(Format format); + /* Checks if format is used to pass arguments in vregisters (without accumulator) */ + static constexpr bool IsVregArgsShort(Format format); + static constexpr bool IsVregArgs(Format format); + static constexpr bool IsVregArgsRange(Format format); + template ::Opcode OPCODE> static constexpr auto GetQuickened(); diff --git a/libpandafile/templates/bytecode_instruction-inl_gen.h.erb b/libpandafile/templates/bytecode_instruction-inl_gen.h.erb index dd5b1ccd9a3d6eece0546ef50a50a1f7fc331aa3..384eb11ae77d8b71ed48034e4304e3e06fdd9d0e 100644 --- a/libpandafile/templates/bytecode_instruction-inl_gen.h.erb +++ b/libpandafile/templates/bytecode_instruction-inl_gen.h.erb @@ -87,6 +87,42 @@ constexpr size_t BytecodeInst::Size(Format format) { // NOLINT(readabilit UNREACHABLE_CONSTEXPR(); } +/* static */ +template +constexpr bool BytecodeInst::IsVregArgsShort(Format format) +{ +% insns = Panda::instructions.select do |i| +% mn = i.mnemonic +% mn.include?('short') && !mn.include?('acc') && i.properties.include?('short_long_range') +% end +% formats = insns.map{ |i| i.format }.uniq + return <%= formats.map{ |f| "format == Format::#{f.pretty.upcase}" }.join(' || ') %>; +} + +/* static */ +template +constexpr bool BytecodeInst::IsVregArgsRange(Format format) +{ +% insns = Panda::instructions.select do |i| +% mn = i.mnemonic +% mn.include?('range') && !mn.include?('acc') && i.properties.include?('short_long_range') +% end +% formats = insns.map{ |i| i.format }.uniq + return <%= formats.map{ |f| "format == Format::#{f.pretty.upcase}" }.join(' || ') %>; +} + +/* static */ +template +constexpr bool BytecodeInst::IsVregArgs(Format format) +{ +% insns = Panda::instructions.select do |i| +% mn = i.mnemonic +% !mn.include?('range') && !mn.include?('short') && !mn.include?('acc') && i.properties.include?('short_long_range') +% end +% formats = insns.map{ |i| i.format }.uniq + return <%= formats.map{ |f| "format == Format::#{f.pretty.upcase}" }.join(' || ') %>; +} + template template ::Format FORMAT, typename EnumT, size_t IDX /* = 0 */> inline BytecodeId BytecodeInst::GetId() const { diff --git a/plugins/ets/CMakeLists.txt b/plugins/ets/CMakeLists.txt index 0c00578d9900c04cf917bd91c418174dd4467523..12a6563e206d28db9cf3c62f2dad2d491ecb9281 100644 --- a/plugins/ets/CMakeLists.txt +++ b/plugins/ets/CMakeLists.txt @@ -28,6 +28,7 @@ if(PANDA_WITH_TOOLCHAIN) add_subdirectory(isa) endif() +add_subdirectory(irtoc_scripts) add_subdirectory(verification) add_subdirectory(arkts_header) diff --git a/plugins/ets/ets_plugin_options.yaml b/plugins/ets/ets_plugin_options.yaml index eaf17069c4aeb61dd5aeaf4d54c8910d4a772215..d8e397beda55a90a5617bdf6bc86aec8c7575bad 100644 --- a/plugins/ets/ets_plugin_options.yaml +++ b/plugins/ets/ets_plugin_options.yaml @@ -43,6 +43,10 @@ header: plugins/ets/verification/ets_plugin.h plugin_class: panda::verifier::plugin::EtsPlugin + irtoc_files: + - plugins_interpreter_handlers: plugins/ets/irtoc_scripts/interpreter_handlers.irt + - plugins_main_loop: plugins/ets/irtoc_scripts/interpreter_main_loop.irt + Metadatas: - RecordMetadata: new_class_name: panda::pandasm::extensions::ets::RecordMetadata diff --git a/plugins/ets/irtoc_scripts/CMakeLists.txt b/plugins/ets/irtoc_scripts/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..176d94c428c19b0fa486a823e23d947360f8c490 --- /dev/null +++ b/plugins/ets/irtoc_scripts/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2021-2023 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. + +add_irtoc_plugin(${PANDA_ETS_PLUGIN_SOURCE}/irtoc_scripts/interpreter_handlers.irt) +add_irtoc_plugin(${PANDA_ETS_PLUGIN_SOURCE}/irtoc_scripts/interpreter_main_loop.irt) diff --git a/plugins/ets/irtoc_scripts/interpreter_handlers.irt b/plugins/ets/irtoc_scripts/interpreter_handlers.irt new file mode 100644 index 0000000000000000000000000000000000000000..cce4ac5d3e705faea7d2ca61339591e1cf121adf --- /dev/null +++ b/plugins/ets/irtoc_scripts/interpreter_handlers.irt @@ -0,0 +1,26 @@ +# plugin interpreter_handlers +# Copyright (c) 2021-2023 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. + +['static', 'virt'].each do |dispatch| + ['short', 'long', 'range'].each do |flavor| + macro(:"handle_ets_launch_#{dispatch}_#{flavor}") do |v, id| + # TODO(mbolshov): verify method + method_ptr = get_callee(id, dispatch == 'virt', false, v) + set_acc_object(call_runtime("LaunchFromInterpreter#{flavor.capitalize}", method_ptr, %frame, pc).ptr) + If(acc, 0).EQ { + move_to_exception + } + end + end +end diff --git a/plugins/ets/irtoc_scripts/interpreter_main_loop.irt b/plugins/ets/irtoc_scripts/interpreter_main_loop.irt new file mode 100644 index 0000000000000000000000000000000000000000..4bace9709bd8fd14cee39b459e7e05004ec6e798 --- /dev/null +++ b/plugins/ets/irtoc_scripts/interpreter_main_loop.irt @@ -0,0 +1,27 @@ +# plugin interpreter_main_loop +# Copyright (c) 2021-2023 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. + + when "ETS_LAUNCH_SHORT_PREF_V4_V4_ID16" + handle_ets_launch_static_short(op[1], as_id(op[0])) + when "ETS_LAUNCH_PREF_V4_V4_V4_V4_ID16" + handle_ets_launch_static_long(op[1], as_id(op[0])) + when "ETS_LAUNCH_RANGE_PREF_V8_ID16" + handle_ets_launch_static_range(op[1], as_id(op[0])) + when "ETS_LAUNCH_VIRT_SHORT_PREF_V4_V4_ID16" + handle_ets_launch_virt_short(op[1], as_id(op[0])) + when "ETS_LAUNCH_VIRT_PREF_V4_V4_V4_V4_ID16" + handle_ets_launch_virt_long(op[1], as_id(op[0])) + when "ETS_LAUNCH_VIRT_RANGE_PREF_V8_ID16" + handle_ets_launch_virt_range(op[1], as_id(op[0])) + diff --git a/plugins/ets/isa/isa.yaml b/plugins/ets/isa/isa.yaml index 94991f0d76490609b3a9b5a5d2f1edf8ebe2e912..7abb31b945bfa74367ae52997efbfdf97937e159 100644 --- a/plugins/ets/isa/isa.yaml +++ b/plugins/ets/isa/isa.yaml @@ -24,74 +24,45 @@ groups: description: ETS extension intrunctions with prefix ets verification: - none - exceptions: [] + properties: + - method_id + - short_long_range + exceptions: + - x_oom namespace: ets instructions: - sig: ets.launch.short method_id, v1:in:top, v2:in:top prefix: ets acc: out:top format: [pref_op_v1_4_v2_4_id_16] - properties: - - method_id - - call - exceptions: - - x_call intrinsic_name: INTRINSIC_LAUNCH_SHORT - sig: ets.launch method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top prefix: ets acc: out:top format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16] - properties: - - method_id - - call - exceptions: - - x_call intrinsic_name: INTRINSIC_LAUNCH - sig: ets.launch.range method_id, v:in:top prefix: ets acc: out:top format: [pref_op_v_8_id_16] - properties: - - method_id - - call - exceptions: - - x_call intrinsic_name: INTRINSIC_LAUNCH_RANGE - sig: ets.launch.virt.short method_id, v1:in:top, v2:in:top prefix: ets acc: out:top format: [pref_op_v1_4_v2_4_id_16] - properties: - - method_id - - call - - call_virt - exceptions: - - x_call intrinsic_name: INTRINSIC_LAUNCH_VIRT_SHORT - sig: ets.launch.virt method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top prefix: ets acc: out:top format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16] - properties: - - method_id - - call - - call_virt - exceptions: - - x_call intrinsic_name: INTRINSIC_LAUNCH_VIRT - sig: ets.launch.virt.range method_id, v:in:top prefix: ets acc: out:top format: [pref_op_v_8_id_16] - properties: - - method_id - - call - - call_virt - exceptions: - - x_call intrinsic_name: INTRINSIC_LAUNCH_VIRT_RANGE diff --git a/plugins/ets/runtime/CMakeLists.txt b/plugins/ets/runtime/CMakeLists.txt index 03cf560795e3fd6d1406108a487e405d5c8eadd3..0bcc63576746e37d34bb564d11651d098f4958b2 100644 --- a/plugins/ets/runtime/CMakeLists.txt +++ b/plugins/ets/runtime/CMakeLists.txt @@ -54,6 +54,7 @@ set(ETS_RUNTIME_SOURCES ${ETS_EXT_SOURCES}/types/ets_field.cpp ${ETS_EXT_SOURCES}/types/ets_method.cpp ${ETS_EXT_SOURCES}/types/ets_promise.cpp + ${ETS_EXT_SOURCES}/types/ets_object.cpp ${ETS_EXT_SOURCES}/ets_vm_api.cpp ${ETS_EXT_SOURCES}/lambda_utils.cpp ) diff --git a/plugins/ets/runtime/ets_entrypoints.cpp b/plugins/ets/runtime/ets_entrypoints.cpp index ad35f32d007dae5a350167307fb3ad894fe74b27..dd691d3f08006269e0fbb277263c3a3184af4d00 100644 --- a/plugins/ets/runtime/ets_entrypoints.cpp +++ b/plugins/ets/runtime/ets_entrypoints.cpp @@ -21,6 +21,7 @@ #include "plugins/ets/runtime/ets_vm.h" #include "plugins/ets/runtime/types/ets_promise.h" #include "runtime/arch/helpers.h" +#include "runtime/interpreter/vregister_iterator.h" namespace panda::ets { @@ -34,6 +35,19 @@ using TypeId = panda_file::Type::TypeId; #pragma GCC diagnostic ignored "-Wpedantic" #endif +static inline void Launch(Method *method, EtsPromise *promise, PandaVector &&args) +{ + EtsCoroutine *coroutine = EtsCoroutine::GetCurrent(); + ASSERT(coroutine != nullptr); + PandaEtsVM *ets_vm = coroutine->GetPandaVM(); + auto promise_ref = ets_vm->GetGlobalObjectStorage()->Add(promise, mem::Reference::ObjectType::WEAK); + auto evt = Runtime::GetCurrent()->GetInternalAllocator()->New(promise_ref); + promise->SetEventPtr(evt); + // create the coro and put it to the ready queue + auto *cm = static_cast(ets_vm->GetThreadManager()); + cm->Launch(evt, method, std::move(args)); +} + void LaunchCoroutine(Method *method, ObjectHeader *obj, uint64_t *args, ObjectHeader *this_obj) { auto *promise = reinterpret_cast(obj); @@ -50,15 +64,7 @@ void LaunchCoroutine(Method *method, ObjectHeader *obj, uint64_t *args, ObjectHe arch::ArgReaderStack arg_reader(args); arch::ValueWriter writer(&values); ARCH_COPY_METHOD_ARGS(method, arg_reader, writer); - - EtsCoroutine *coroutine = EtsCoroutine::GetCurrent(); - PandaEtsVM *ets_vm = coroutine->GetPandaVM(); - auto promise_ref = ets_vm->GetGlobalObjectStorage()->Add(promise, mem::Reference::ObjectType::WEAK); - auto evt = Runtime::GetCurrent()->GetInternalAllocator()->New(promise_ref); - promise->SetEventPtr(evt); - // create the coro and put it to the ready queue - auto *cm = static_cast(ets_vm->GetThreadManager()); - cm->Launch(evt, method, std::move(values)); + Launch(method, promise, std::move(values)); } extern "C" void CreateLaunchStaticCoroutineEntrypoint(Method *method, ObjectHeader *obj, uint64_t *args) @@ -76,4 +82,40 @@ extern "C" void CreateLaunchVirtualCoroutineEntrypoint(Method *method, ObjectHea LaunchCoroutine(method, obj, args, this_obj); } +template +ObjectHeader *LaunchFromInterpreterImpl(Method *method, Frame *frame, const uint8_t *pc) +{ + EtsPromise *promise = EtsPromise::Create(); + if (UNLIKELY(promise == nullptr)) { + return nullptr; + } + frame->GetAccAsVReg().SetReference(promise); + + auto num_args = method->GetNumArgs(); + auto args = PandaVector {num_args}; + auto frame_handler = StaticFrameHandler(frame); + auto vreg_iter = interpreter::VRegisterIterator {BytecodeInstruction(pc), frame}; + for (decltype(num_args) i = 0; i < num_args; ++i) { + args[i] = Value::FromVReg(frame_handler.GetVReg(vreg_iter.GetVRegIdx(i))); + } + + Launch(method, promise, std::move(args)); + return promise; +} + +extern "C" ObjectHeader *LaunchFromInterpreterShort(Method *method, Frame *frame, const uint8_t *pc) +{ + return LaunchFromInterpreterImpl(method, frame, pc); +} + +extern "C" ObjectHeader *LaunchFromInterpreterLong(Method *method, Frame *frame, const uint8_t *pc) +{ + return LaunchFromInterpreterImpl(method, frame, pc); +} + +extern "C" ObjectHeader *LaunchFromInterpreterRange(Method *method, Frame *frame, const uint8_t *pc) +{ + return LaunchFromInterpreterImpl(method, frame, pc); +} + } // namespace panda::ets diff --git a/plugins/ets/runtime/interpreter/interpreter-inl.h b/plugins/ets/runtime/interpreter/interpreter-inl.h index 078d82b171b1a2676b2c313b741c82d416a622a1..b8968ecd9093ee83b17ad78188574c9aa0497d71 100644 --- a/plugins/ets/runtime/interpreter/interpreter-inl.h +++ b/plugins/ets/runtime/interpreter/interpreter-inl.h @@ -168,34 +168,27 @@ private: if constexpr (IS_RANGE) { uint16_t start_reg = this->GetInst().template GetVReg(); for (size_t i = 0; i < args.size(); ++i) { - args[i] = VReg2Value(cur_frame_handler.GetVReg(start_reg + i)); + args[i] = Value::FromVReg(cur_frame_handler.GetVReg(start_reg + i)); } } else { // launch.short of launch - args[0] = VReg2Value(cur_frame_handler.GetVReg(this->GetInst().template GetVReg())); + args[0] = Value::FromVReg(cur_frame_handler.GetVReg(this->GetInst().template GetVReg())); if (args.size() > 1U) { - args[1] = VReg2Value(cur_frame_handler.GetVReg(this->GetInst().template GetVReg())); + args[1] = Value::FromVReg(cur_frame_handler.GetVReg(this->GetInst().template GetVReg())); } if constexpr (FORMAT == BytecodeInstruction::Format::PREF_V4_V4_V4_V4_ID16) { if (args.size() > 2U) { - args[2] = VReg2Value(cur_frame_handler.GetVReg(this->GetInst().template GetVReg())); + args[2] = + Value::FromVReg(cur_frame_handler.GetVReg(this->GetInst().template GetVReg())); } if (args.size() > 3U) { - args[3] = VReg2Value(cur_frame_handler.GetVReg(this->GetInst().template GetVReg())); + args[3] = + Value::FromVReg(cur_frame_handler.GetVReg(this->GetInst().template GetVReg())); } } } } - template - ALWAYS_INLINE Value VReg2Value(VRegisterRef vreg) - { - if (vreg.HasObject()) { - return Value(vreg.GetReference()); - } - return Value(vreg.GetValue()); - } - template ALWAYS_INLINE ObjectHeader *GetObjHelper() { diff --git a/plugins/ets/runtime/types/ets_object.cpp b/plugins/ets/runtime/types/ets_object.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cdf2fa2c906749fbbe865cb4c95244403074da28 --- /dev/null +++ b/plugins/ets/runtime/types/ets_object.cpp @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "plugins/ets/runtime/types/ets_object.h" +#include "plugins/ets/runtime/ets_coroutine.h" + +namespace panda::ets { + +/* static */ +EtsObject *EtsObject::Create(EtsCoroutine *ets_coroutine, EtsClass *klass) +{ + ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS(); + return static_cast(ObjectHeader::Create(ets_coroutine, klass->GetRuntimeClass())); +} + +/* static */ +EtsObject *EtsObject::Create(EtsClass *klass) +{ + return Create(EtsCoroutine::GetCurrent(), klass); +} + +} // namespace panda::ets diff --git a/plugins/ets/runtime/types/ets_object.h b/plugins/ets/runtime/types/ets_object.h index 8893cba7e55e5d4a8130e7a35904f87ecd5a6fcd..1d09c1d9aaa2bdce6889648d084e59a871f2450c 100644 --- a/plugins/ets/runtime/types/ets_object.h +++ b/plugins/ets/runtime/types/ets_object.h @@ -22,14 +22,14 @@ namespace panda::ets { +class EtsCoroutine; + // Private inheritance, because need to disallow implicit conversion to core type class EtsObject : private ObjectHeader { public: - static EtsObject *Create(EtsClass *klass) - { - ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS(); - return reinterpret_cast(ObjectHeader::Create(klass->GetRuntimeClass())); - } + static EtsObject *Create(EtsCoroutine *ets_coroutine, EtsClass *klass); + + static EtsObject *Create(EtsClass *klass); EtsClass *GetClass() const { diff --git a/plugins/ets/runtime/types/ets_promise.cpp b/plugins/ets/runtime/types/ets_promise.cpp index 3d909e192ae0de296246a49a3eb3384ae89dafea..6819acab3bd1507e7735f7d2a4fe27f9834acf84 100644 --- a/plugins/ets/runtime/types/ets_promise.cpp +++ b/plugins/ets/runtime/types/ets_promise.cpp @@ -23,8 +23,8 @@ namespace panda::ets { EtsPromise *EtsPromise::Create(EtsCoroutine *ets_coroutine) { EtsClass *klass = ets_coroutine->GetPandaVM()->GetClassLinker()->GetPromiseClass(); - ObjectHeader *object_header = ObjectHeader::Create(klass->GetRuntimeClass()); - return reinterpret_cast(object_header); + EtsObject *ets_object = EtsObject::Create(ets_coroutine, klass); + return reinterpret_cast(ets_object); } } // namespace panda::ets diff --git a/plugins/ets/runtime/types/ets_promise.h b/plugins/ets/runtime/types/ets_promise.h index ed2902d737e5c445cc08842c17b3f182b24766c4..f11c9f8e17c28777bc0b78b5321ae3ad9dc050c4 100644 --- a/plugins/ets/runtime/types/ets_promise.h +++ b/plugins/ets/runtime/types/ets_promise.h @@ -42,7 +42,7 @@ public: NO_COPY_SEMANTIC(EtsPromise); NO_MOVE_SEMANTIC(EtsPromise); - static EtsPromise *Create(EtsCoroutine *ets_coroutine); + static EtsPromise *Create(EtsCoroutine *ets_coroutine = EtsCoroutine::GetCurrent()); static EtsPromise *FromCoreType(ObjectHeader *promise) { diff --git a/plugins/ets/subproject_sources.gn b/plugins/ets/subproject_sources.gn index 8d65df59bd0c1aa0b718ea662418214385b670cf..134b8692921747fc19564f0f223e5e3a14c3fe9a 100644 --- a/plugins/ets/subproject_sources.gn +++ b/plugins/ets/subproject_sources.gn @@ -38,6 +38,11 @@ inst_templates_yaml_path = entrypoints_yaml_path = "runtime/ets_entrypoints.yaml" +irtoc_plugins = [ + "irtoc_scripts/interpreter_handlers.irt", + "irtoc_scripts/interpreter_main_loop.irt", +] + srcs_runtime = [ "runtime/ets_annotation.cpp", "runtime/ets_class_linker.cpp", @@ -76,6 +81,7 @@ srcs_runtime = [ "runtime/types/ets_field.cpp", "runtime/types/ets_method.cpp", "runtime/types/ets_promise.cpp", + "runtime/types/ets_object.cpp", "runtime/lambda_utils.cpp", ] diff --git a/plugins/ets/tests/CMakeLists.txt b/plugins/ets/tests/CMakeLists.txt index 684f058b1e4d83675386aa849e4211ee1262a2d6..19192c9390985189d937643459b849d35789f64b 100644 --- a/plugins/ets/tests/CMakeLists.txt +++ b/plugins/ets/tests/CMakeLists.txt @@ -97,7 +97,7 @@ function(run_ets_code_verifier ETS_SRC WORK_DIR TARGET) add_dependencies(ets_tests ${TARGET}) endfunction() -function(run_int_ets_code INTERPRETER_TYPE ETS_SRC WORK_DIR TARGET) +function(run_int_ets_code_impl INTERPRETER_TYPE ETS_SRC WORK_DIR TARGET) if (NOT TARGET es2panda) return() endif() @@ -126,7 +126,7 @@ function(run_int_ets_code INTERPRETER_TYPE ETS_SRC WORK_DIR TARGET) COMMAND ${PANDA_RUN_PREFIX} $ ${RUNTIME_ARGUMENTS} DEPENDS ark etsstdlib ${ABC_TARGET} ) - + string(FIND "${RUNTIME_ARGUMENTS}" "--gc-type" GC_TYPE_SET) if(NOT PANDA_LLVMAOT AND ${GC_TYPE_SET} EQUAL -1) add_custom_target(${TARGET}-gc @@ -141,6 +141,23 @@ function(run_int_ets_code INTERPRETER_TYPE ETS_SRC WORK_DIR TARGET) add_dependencies(ets_tests ${TARGET}) endfunction() +function(run_int_ets_code ETS_SRC WORK_DIR TARGET) + set(oneValueArgs OPT_LEVEL) + set(multiValueArgs RUNTIME_EXTRA_OPTIONS) + cmake_parse_arguments(ARG "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + add_custom_target(${TARGET}) + add_dependencies(ets_tests ${TARGET}) + + run_int_ets_code_impl(cpp ${ETS_SRC} ${WORK_DIR} ${TARGET}-cpp OPT_LEVEL ${ARG_OPT_LEVEL} RUNTIME_EXTRA_OPTIONS ${ARG_RUNTIME_EXTRA_OPTIONS}) + run_int_ets_code_impl(irtoc ${ETS_SRC} ${WORK_DIR} ${TARGET}-irtoc OPT_LEVEL ${ARG_OPT_LEVEL} RUNTIME_EXTRA_OPTIONS ${ARG_RUNTIME_EXTRA_OPTIONS}) + add_dependencies(${TARGET} ${TARGET}-irtoc ${TARGET}-cpp) + if (PANDA_LLVMAOT) + run_int_ets_code_impl(llvm ${ETS_SRC} ${WORK_DIR} ${TARGET}-llvmirtoc OPT_LEVEL ${ARG_OPT_LEVEL} RUNTIME_EXTRA_OPTIONS ${ARG_RUNTIME_EXTRA_OPTIONS}) + add_dependencies(${TARGET} ${TARGET}-llvmirtoc) + endif() +endfunction() + function(run_jit_ets_code ETS_SRC WORK_DIR TARGET) set(multiValueArgs RUNTIME_EXTRA_OPTIONS) cmake_parse_arguments(ARG "" "" "${multiValueArgs}" ${ARGN}) @@ -243,12 +260,10 @@ function(run_aot_ets_code PAOC_MODE ETS_SRC WORK_DIR TARGET) endfunction() function(run_int_jit_aot_ets_code ETS_SRC WORK_DIR TARGET) - run_int_ets_code(cpp ${ETS_SRC} ${WORK_DIR} ${TARGET}-ets-int-cpp) + run_int_ets_code(${ETS_SRC} ${WORK_DIR} ${TARGET}-ets-int) run_jit_ets_code(${ETS_SRC} ${WORK_DIR} ${TARGET}-ets-jit) run_aot_ets_code(aot ${ETS_SRC} ${WORK_DIR} ${TARGET}-ets-aot) - run_int_ets_code(irtoc ${ETS_SRC} ${WORK_DIR} ${TARGET}-ets-int) if (PANDA_LLVMAOT) - run_int_ets_code(llvm ${ETS_SRC} ${WORK_DIR} ${TARGET}-ets-llvmirtoc) run_aot_ets_code(llvm ${ETS_SRC} ${WORK_DIR} ${TARGET}-ets-llvmaot) endif() if (PANDA_TARGET_ARM64) diff --git a/plugins/ets/tests/ets_test_suite/coroutines/CMakeLists.txt b/plugins/ets/tests/ets_test_suite/coroutines/CMakeLists.txt index 372ca723ffb34de0b041be7f7d3bbf2254478106..2b804040cde08bae6659fe27202c2c9e5b8e717f 100644 --- a/plugins/ets/tests/ets_test_suite/coroutines/CMakeLists.txt +++ b/plugins/ets/tests/ets_test_suite/coroutines/CMakeLists.txt @@ -52,11 +52,11 @@ foreach(test ${coroutine_tests}) # TODO(konstanting, #I67QXC): remove OPT_LEVEL when compiler supports the ets.launch instruction set(target_int ${target}-ets-int) if (test STREQUAL "await_n_workers") - run_int_ets_code(cpp ${test_in} ${test_out_dir} ${target_int} OPT_LEVEL 0 RUNTIME_EXTRA_OPTIONS "--coroutine-workers-count=0" ${threaded_impl_option}) + run_int_ets_code(${test_in} ${test_out_dir} ${target_int} OPT_LEVEL 0 RUNTIME_EXTRA_OPTIONS "--coroutine-workers-count=0" ${threaded_impl_option}) elseif (test STREQUAL "async_call") - run_int_ets_code(cpp ${test_in} ${test_out_dir} ${target_int} OPT_LEVEL 0 RUNTIME_EXTRA_OPTIONS ${js_mode_option} ${stackful_impl_option}) + run_int_ets_code(${test_in} ${test_out_dir} ${target_int} OPT_LEVEL 0 RUNTIME_EXTRA_OPTIONS ${js_mode_option} ${stackful_impl_option}) else() - run_int_ets_code(cpp ${test_in} ${test_out_dir} ${target_int} OPT_LEVEL 0 RUNTIME_EXTRA_OPTIONS ${stackful_impl_option}) + run_int_ets_code(${test_in} ${test_out_dir} ${target_int} OPT_LEVEL 0 RUNTIME_EXTRA_OPTIONS ${stackful_impl_option}) endif() add_dependencies(ets_test_suite_coroutines ${target_int}) diff --git a/plugins/ets/tests/ets_test_suite/gc/CMakeLists.txt b/plugins/ets/tests/ets_test_suite/gc/CMakeLists.txt index 3ab75aa5354ef1656eede5ff836079c8bd9941e4..5994b82eb3218b1ddc9002b59182cd3f40fa5c33 100644 --- a/plugins/ets/tests/ets_test_suite/gc/CMakeLists.txt +++ b/plugins/ets/tests/ets_test_suite/gc/CMakeLists.txt @@ -34,7 +34,7 @@ function(add_ets_gc_test) set(target ets_test_suite_gc_${TEST_NAME}-ets-${run_mode}) if ("${ARG_MODE}" STREQUAL "INT") - run_int_ets_code(irtoc ${test_in} ${test_out_dir} ${target} RUNTIME_EXTRA_OPTIONS ${ARG_OPTIONS}) + run_int_ets_code(${test_in} ${test_out_dir} ${target} RUNTIME_EXTRA_OPTIONS ${ARG_OPTIONS}) elseif ("${ARG_MODE}" STREQUAL "AOT") run_aot_ets_code(aot ${test_in} ${test_out_dir} ${target} RUNTIME_EXTRA_OPTIONS ${ARG_OPTIONS}) elseif ("${ARG_MODE}" STREQUAL "JIT") diff --git a/plugins/ets/tests/ets_test_suite/intrinsics/CMakeLists.txt b/plugins/ets/tests/ets_test_suite/intrinsics/CMakeLists.txt index 5cbde324f48c6f888f75aaaa2d83697c95f5d66e..ac32655a540e5c684d43a290e95fdb344895a346 100644 --- a/plugins/ets/tests/ets_test_suite/intrinsics/CMakeLists.txt +++ b/plugins/ets/tests/ets_test_suite/intrinsics/CMakeLists.txt @@ -33,7 +33,6 @@ foreach(test ${intrinsics_tests}) run_int_jit_aot_ets_code(${test_in} ${test_out_dir} ${target}) add_dependencies(ets_test_suite_intrinsics - ${target}-ets-int-cpp ${target}-ets-jit ${target}-ets-int) if (NOT CMAKE_CROSSCOMPILING) diff --git a/plugins/ets/tests/ets_test_suite/strings/CMakeLists.txt b/plugins/ets/tests/ets_test_suite/strings/CMakeLists.txt index e460169850ba6641c8a1d949b61e2657dc5905df..8ff851d37bf7cd9327828f1b87c41dc02e513eb0 100644 --- a/plugins/ets/tests/ets_test_suite/strings/CMakeLists.txt +++ b/plugins/ets/tests/ets_test_suite/strings/CMakeLists.txt @@ -28,7 +28,6 @@ foreach(test ${strings_tests}) run_int_jit_aot_ets_code(${test_in} ${test_out_dir} ${target}) add_dependencies(ets_test_suite_strings - ${target}-ets-int-cpp ${target}-ets-jit ${target}-ets-int) if (NOT CMAKE_CROSSCOMPILING) diff --git a/runtime/include/value.h b/runtime/include/value.h index 6536e90b1f3f7b5e71b77a82ce7d4ff0295818b9..08fb6441ad93bbe246c2fcde5ccf06741f27b55f 100644 --- a/runtime/include/value.h +++ b/runtime/include/value.h @@ -92,6 +92,15 @@ public: return &std::get(value_); } + template + static ALWAYS_INLINE Value FromVReg(VRegisterRef vreg) + { + if (vreg.HasObject()) { + return Value(vreg.GetReference()); + } + return Value(vreg.GetValue()); + } + private: std::variant value_; }; diff --git a/runtime/interpreter/vregister_iterator.h b/runtime/interpreter/vregister_iterator.h index d479072231665e13f881500f087725c715d5e1c5..3a47f755e61c4c7c16bd4de85e53da4ee387a910 100644 --- a/runtime/interpreter/vregister_iterator.h +++ b/runtime/interpreter/vregister_iterator.h @@ -23,53 +23,48 @@ public: // NOLINTNEXTLINE(performance-move-const-arg) explicit VRegisterIterator(BytecodeInstruction insn, Frame *frame) : instn_(std::move(insn)), frame_(frame) {} - template - ALWAYS_INLINE inline T GetAs(size_t param_idx) const + ALWAYS_INLINE size_t GetVRegIdx(size_t param_idx) const { - size_t vreg_idx; - - if constexpr (FORMAT == BytecodeInstruction::Format::V4_V4_ID16 /* short */) { + if constexpr (BytecodeInstruction::IsVregArgsShort(FORMAT)) { switch (param_idx) { case 0: { - vreg_idx = instn_.GetVReg(); - break; + return instn_.GetVReg(); } case 1: { - vreg_idx = instn_.GetVReg(); - break; + return instn_.GetVReg(); } default: UNREACHABLE(); } - } else if constexpr (FORMAT == BytecodeInstruction::Format::V4_V4_V4_V4_ID16) { + } else if constexpr (BytecodeInstruction::IsVregArgs(FORMAT)) { switch (param_idx) { case 0: { - vreg_idx = instn_.GetVReg(); - break; + return instn_.GetVReg(); } case 1: { - vreg_idx = instn_.GetVReg(); - break; + return instn_.GetVReg(); } case 2: { - vreg_idx = instn_.GetVReg(); - break; + return instn_.GetVReg(); } case 3: { - vreg_idx = instn_.GetVReg(); - break; + return instn_.GetVReg(); } default: UNREACHABLE(); } - } else if constexpr (FORMAT == BytecodeInstruction::Format::V8_ID16 /* range */) { - vreg_idx = instn_.GetVReg() + param_idx; + } else if constexpr (BytecodeInstruction::IsVregArgsRange(FORMAT)) { + return instn_.GetVReg() + param_idx; } else { UNREACHABLE(); + return SIZE_MAX; } + } - auto vreg = frame_->GetVReg(vreg_idx); - return vreg.template GetAs(); + template + ALWAYS_INLINE T GetAs(size_t param_idx) const + { + return frame_->GetVReg(GetVRegIdx(param_idx)).template GetAs(); } private: diff --git a/runtime/stackful_coroutine.cpp b/runtime/stackful_coroutine.cpp index e9dedc4c8352e340b18c7e6f94bb0dd013ecf145..5a715af809f155f8c31ebef17abba06244cff2aa 100644 --- a/runtime/stackful_coroutine.cpp +++ b/runtime/stackful_coroutine.cpp @@ -35,6 +35,7 @@ StackfulCoroutineContext::StackfulCoroutineContext(mem::InternalAllocatorPtr sta // okay to not pass the allocator explicitely to StackfulCoroutineContext ctor // NOLINTNEXTLINE(modernize-avoid-c-arrays) stack_ = stack_allocator_->New(STACK_SIZE); + ASSERT(stack_ != nullptr); // TODO(konstanting, #I67QXC): OOM exception fibers::GetCurrentContext(&context_); }