From 35a9d4f84b35df17f35bb4745170c9d7b651943a Mon Sep 17 00:00:00 2001 From: Lyupa Anastasia Date: Tue, 3 Jun 2025 14:40:26 +0300 Subject: [PATCH] Add core class DynamicXRef for JSValue Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICCAQX Change-Id: Ied6accb4410265be1ef19f23bf8a98911272630e Signed-off-by: Lyupa Anastasia --- static_core/isa/isa.yaml | 16 ++++----- .../ets/runtime/ets_language_context.h | 5 +++ .../ets/runtime/interop_js/js_convert.h | 2 +- .../ets/runtime/interop_js/js_value.cpp | 6 ++-- .../plugins/ets/runtime/interop_js/js_value.h | 30 +++++++++++----- .../core/core_class_linker_extension.cpp | 13 +++++++ .../runtime/core/core_language_context.cpp | 3 +- .../runtime/core/core_language_context.h | 5 +++ static_core/runtime/include/class.h | 11 ++++++ static_core/runtime/include/class_root.h | 1 + .../runtime/include/coretypes/dynamic_xref.h | 36 +++++++++++++++++++ .../runtime/include/language_context.h | 10 ++++++ .../runtime/interpreter/interpreter-inl.h | 36 +++++++++++++++---- 13 files changed, 146 insertions(+), 28 deletions(-) create mode 100644 static_core/runtime/include/coretypes/dynamic_xref.h diff --git a/static_core/isa/isa.yaml b/static_core/isa/isa.yaml index 5b8ee5e6f6..be60e12175 100644 --- a/static_core/isa/isa.yaml +++ b/static_core/isa/isa.yaml @@ -3000,7 +3000,7 @@ groups: acc: out:ref format: [pref_op_v_8_id_32] prefix: any - opcode_idx: [0xa6] + opcode_idx: [0x0] - title: Get field from reference of any type by name description: > @@ -3027,7 +3027,7 @@ groups: acc: none format: [pref_op_v1_8_v2_8_id_32] prefix: any - opcode_idx: [0xa7] + opcode_idx: [0x1] - title: Store accumulator content into reference of any type field by name description: > @@ -3054,7 +3054,7 @@ groups: acc: in:ref format: [pref_op_v_8_id_32] prefix: any - opcode_idx: [0xa8] + opcode_idx: [0x2] - title: Store register content into reference of any type field by name description: > @@ -3081,7 +3081,7 @@ groups: acc: none format: [pref_op_v1_8_v2_8_id_32] prefix: any - opcode_idx: [0xa9] + opcode_idx: [0x3] - title: Load value to accumulator from reference of any type by index description: > @@ -3101,7 +3101,7 @@ groups: acc: inout:i32->ref format: [pref_op_v_8] prefix: any - opcode_idx: [0xaa] + opcode_idx: [0x4] - title: Store value from accumulator in reference of any type by index description: > @@ -3122,7 +3122,7 @@ groups: acc: in:ref format: [pref_op_v1_8_v2_8] prefix: any - opcode_idx: [0xab] + opcode_idx: [0x5] - title: Load value to accumulator from reference of any type by value description: > @@ -3142,7 +3142,7 @@ groups: acc: out:ref format: [pref_op_v1_8_v2_8] prefix: any - opcode_idx: [0xac] + opcode_idx: [0x6] - title: Store value from accumulator in reference of any type by value description: > @@ -3163,4 +3163,4 @@ groups: acc: in:ref format: [pref_op_v1_8_v2_8] prefix: any - opcode_idx: [0xad] + opcode_idx: [0x7] diff --git a/static_core/plugins/ets/runtime/ets_language_context.h b/static_core/plugins/ets/runtime/ets_language_context.h index df5dec05f5..0c3ffea023 100644 --- a/static_core/plugins/ets/runtime/ets_language_context.h +++ b/static_core/plugins/ets/runtime/ets_language_context.h @@ -85,6 +85,11 @@ public: return utf::CStringAsMutf8(panda_file_items::class_descriptors::STRING_ARRAY.data()); } + const uint8_t *GetDynamicXRefClassDescriptor() const override + { + return utf::CStringAsMutf8(panda_file_items::class_descriptors::JS_VALUE.data()); + } + const uint8_t *GetCtorName() const override { return utf::CStringAsMutf8(panda_file_items::CTOR.data()); diff --git a/static_core/plugins/ets/runtime/interop_js/js_convert.h b/static_core/plugins/ets/runtime/interop_js/js_convert.h index 4b2250bb7f..869754e469 100644 --- a/static_core/plugins/ets/runtime/interop_js/js_convert.h +++ b/static_core/plugins/ets/runtime/interop_js/js_convert.h @@ -259,7 +259,7 @@ JSCONVERT_WRAP(ESError) auto method = klass->GetInstanceMethod("getJsError", nullptr); ASSERT(method != nullptr); std::array args = {Value(etsVal->GetCoreType())}; - auto val = JSValue::FromCoreType(method->GetPandaMethod()->Invoke(coro, args.data()).GetAs()); + auto val = JSValue::FromObjectHeader(method->GetPandaMethod()->Invoke(coro, args.data()).GetAs()); INTEROP_FATAL_IF(val == nullptr); return val->GetNapiValue(env); } diff --git a/static_core/plugins/ets/runtime/interop_js/js_value.cpp b/static_core/plugins/ets/runtime/interop_js/js_value.cpp index bc1be51e88..343cba50cf 100644 --- a/static_core/plugins/ets/runtime/interop_js/js_value.cpp +++ b/static_core/plugins/ets/runtime/interop_js/js_value.cpp @@ -34,14 +34,14 @@ namespace ark::ets::interop::js { JSValue *mirror = AllocUndefined(coro, ctx); if (UNLIKELY(mirror == nullptr)) { - FinalizeETSWeak(ctx, handle.GetPtr()); + FinalizeETSWeak(ctx, handle.GetPtr()->AsObject()); return nullptr; } mirror->type_ = handle->type_; mirror->data_ = handle->data_; - if (UNLIKELY(!ctx->PushOntoFinalizationRegistry(coro, handle.GetPtr(), mirror))) { - FinalizeETSWeak(ctx, handle.GetPtr()); + if (UNLIKELY(!ctx->PushOntoFinalizationRegistry(coro, handle.GetPtr()->AsObject(), mirror->AsObject()))) { + FinalizeETSWeak(ctx, handle.GetPtr()->AsObject()); return nullptr; } return handle.GetPtr(); diff --git a/static_core/plugins/ets/runtime/interop_js/js_value.h b/static_core/plugins/ets/runtime/interop_js/js_value.h index d45b46f84d..c7b7bc30e2 100644 --- a/static_core/plugins/ets/runtime/interop_js/js_value.h +++ b/static_core/plugins/ets/runtime/interop_js/js_value.h @@ -22,6 +22,7 @@ #include "plugins/ets/runtime/interop_js/ets_proxy/shared_reference.h" #include "plugins/ets/runtime/types/ets_object.h" #include "runtime/include/coretypes/class.h" +#include "runtime/include/coretypes/dynamic_xref.h" #include "utils/small_vector.h" #include @@ -34,17 +35,27 @@ class ESValueOffsets; struct JSValueMemberOffsets; -class JSValue : private EtsObject { +class JSValue : public coretypes::DynamicXRef { public: static JSValue *FromEtsObject(EtsObject *etsObject) { ASSERT(etsObject->GetClass() == EtsClass::FromRuntimeClass(InteropCtx::Current()->GetJSValueClass())); - return static_cast(etsObject); + return reinterpret_cast(etsObject); } - static JSValue *FromCoreType(ObjectHeader *object) + static JSValue *FromCoreType(coretypes::DynamicXRef *dynamicXRef) { - return FromEtsObject(EtsObject::FromCoreType(object)); + return reinterpret_cast(dynamicXRef); + } + + static JSValue *FromObjectHeader(ObjectHeader *obj) + { + return reinterpret_cast(obj); + } + + ObjectHeader *AsObjectHeader() + { + return reinterpret_cast(this); } EtsObject *AsObject() @@ -57,9 +68,10 @@ public: return reinterpret_cast(this); } - ObjectHeader *GetCoreType() const + coretypes::DynamicXRef *GetCoreType() { - return EtsObject::GetCoreType(); + ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS(); + return reinterpret_cast(this); } napi_valuetype GetType() const @@ -211,7 +223,7 @@ private: if (UNLIKELY(!obj)) { return nullptr; } - jsValue = FromCoreType(obj); + jsValue = FromObjectHeader(obj); } static_assert(napi_undefined == 0); // zero-initialized ASSERT(jsValue->GetType() == napi_undefined); @@ -277,7 +289,7 @@ private: ASSERT(GetValueType(ctx->GetJSEnv(), jsValue) == type); ASSERT(IsRefType(type)); SetType(type); - SetData(ctx->GetSharedRefStorage()->CreateJSObjectRef(ctx, this, jsValue)); + SetData(ctx->GetSharedRefStorage()->CreateJSObjectRef(ctx, AsObject(), jsValue)); } FIELD_UNUSED uint32_t type_; @@ -291,7 +303,7 @@ class ESValue : private EtsObject { public: JSValue *GetEo() { - return JSValue::FromCoreType(ObjectAccessor::GetObject(this, GetEoOffset())); + return JSValue::FromObjectHeader(ObjectAccessor::GetObject(this, GetEoOffset())); } static constexpr uint32_t GetEoOffset() diff --git a/static_core/runtime/core/core_class_linker_extension.cpp b/static_core/runtime/core/core_class_linker_extension.cpp index 0a2588a17f..1d2c1ae539 100644 --- a/static_core/runtime/core/core_class_linker_extension.cpp +++ b/static_core/runtime/core/core_class_linker_extension.cpp @@ -124,7 +124,17 @@ bool CoreClassLinkerExtension::InitializeImpl(bool compressedStringEnabled) InitializeArrayClassRoot(ClassRoot::ARRAY_CLASS, ClassRoot::CLASS, utf::Mutf8AsCString(ctx.GetClassArrayClassDescriptor())); + auto *dynamicXRefClass = + CreateClass(ctx.GetDynamicXRefClassDescriptor(), GetClassVTableSize(ClassRoot::DYNAMIC_XREF), + GetClassIMTSize(ClassRoot::DYNAMIC_XREF), GetClassSize(ClassRoot::DYNAMIC_XREF)); + dynamicXRefClass->SetBase(objClass); + dynamicXRefClass->SetJSValueClass(); + dynamicXRefClass->SetState(Class::State::LOADED); + dynamicXRefClass->SetLoadContext(GetBootContext()); + GetClassLinker()->AddClassRoot(ClassRoot::DYNAMIC_XREF, dynamicXRefClass); + InitializeClassRoots(ctx); + return true; } @@ -187,6 +197,7 @@ size_t CoreClassLinkerExtension::GetClassVTableSize(ClassRoot root) case ClassRoot::OBJECT: case ClassRoot::CLASS: case ClassRoot::STRING: + case ClassRoot::DYNAMIC_XREF: return 0; default: { break; @@ -232,6 +243,7 @@ size_t CoreClassLinkerExtension::GetClassIMTSize(ClassRoot root) case ClassRoot::OBJECT: case ClassRoot::CLASS: case ClassRoot::STRING: + case ClassRoot::DYNAMIC_XREF: return 0; default: { break; @@ -277,6 +289,7 @@ size_t CoreClassLinkerExtension::GetClassSize(ClassRoot root) case ClassRoot::OBJECT: case ClassRoot::CLASS: case ClassRoot::STRING: + case ClassRoot::DYNAMIC_XREF: return Class::ComputeClassSize(GetClassVTableSize(root), GetClassIMTSize(root), 0, 0, 0, 0, 0, 0); default: { break; diff --git a/static_core/runtime/core/core_language_context.cpp b/static_core/runtime/core/core_language_context.cpp index 9a463f6538..fa99d317e8 100644 --- a/static_core/runtime/core/core_language_context.cpp +++ b/static_core/runtime/core/core_language_context.cpp @@ -82,7 +82,8 @@ void CoreLanguageContext::ThrowException(ManagedThread *thread, const uint8_t *m panda_file::Type(panda_file::Type::TypeId::REFERENCE), panda_file::Type(panda_file::Type::TypeId::REFERENCE)}, Method::Proto::RefTypeVector {utf::Mutf8AsCString(ctx.GetStringClassDescriptor()), - utf::Mutf8AsCString(ctx.GetObjectClassDescriptor())}); + utf::Mutf8AsCString(ctx.GetObjectClassDescriptor()), + utf::Mutf8AsCString(ctx.GetDynamicXRefClassDescriptor())}); auto *ctorName = ctx.GetCtorName(); auto *ctor = cls->GetDirectMethod(ctorName, proto); if (ctor == nullptr) { diff --git a/static_core/runtime/core/core_language_context.h b/static_core/runtime/core/core_language_context.h index a6a2d4e883..0f2090d72f 100644 --- a/static_core/runtime/core/core_language_context.h +++ b/static_core/runtime/core/core_language_context.h @@ -62,6 +62,11 @@ public: return utf::CStringAsMutf8("[Lpanda/String;"); } + const uint8_t *GetDynamicXRefClassDescriptor() const override + { + return utf::CStringAsMutf8("Lpanda/DynamicXRef;"); + } + const uint8_t *GetNullPointerExceptionClassDescriptor() const override { return utf::CStringAsMutf8("Lpanda/NullPointerException;"); diff --git a/static_core/runtime/include/class.h b/static_core/runtime/include/class.h index a6121da597..ecf5ee50b1 100644 --- a/static_core/runtime/include/class.h +++ b/static_core/runtime/include/class.h @@ -121,6 +121,7 @@ public: using UniqId = uint64_t; static constexpr uint32_t STRING_CLASS = DYNAMIC_CLASS << 1U; static constexpr uint32_t IS_CLONEABLE = STRING_CLASS << 1U; + static constexpr uint32_t JSVALUE_CLASS = IS_CLONEABLE << 1U; static constexpr size_t IMTABLE_SIZE = 32; enum { @@ -365,6 +366,16 @@ public: SetFlags(GetFlags() | IS_CLONEABLE); } + bool IsJSValueClass() const + { + return (GetFlags() & JSVALUE_CLASS) != 0; + } + + void SetJSValueClass() + { + SetFlags(GetFlags() | JSVALUE_CLASS); + } + bool IsVariableSize() const { return IsArrayClass() || IsStringClass(); diff --git a/static_core/runtime/include/class_root.h b/static_core/runtime/include/class_root.h index 69d841ab4e..3430e563c4 100644 --- a/static_core/runtime/include/class_root.h +++ b/static_core/runtime/include/class_root.h @@ -48,6 +48,7 @@ enum class ClassRoot { STRING, ARRAY_CLASS, ARRAY_STRING, + DYNAMIC_XREF, LAST_CLASS_ROOT_ENTRY = ARRAY_STRING // Must be the last in this enum }; diff --git a/static_core/runtime/include/coretypes/dynamic_xref.h b/static_core/runtime/include/coretypes/dynamic_xref.h new file mode 100644 index 0000000000..f5c492c7a9 --- /dev/null +++ b/static_core/runtime/include/coretypes/dynamic_xref.h @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2021-2024 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 PANDA_RUNTIME_CORETYPES_DYNAMICXREF_H_ +#define PANDA_RUNTIME_CORETYPES_DYNAMICXREF_H_ + +#include "runtime/include/object_header.h" + +namespace ark::coretypes { + +class DynamicXRef : public ObjectHeader { +public: + static DynamicXRef *Cast(ObjectHeader *object) + { + return static_cast(object); + } + +private: + DynamicXRef() : ObjectHeader() {} +}; + +} // namespace ark::coretypes + +#endif // PANDA_RUNTIME_CORETYPES_DYNAMICXREF_H_ \ No newline at end of file diff --git a/static_core/runtime/include/language_context.h b/static_core/runtime/include/language_context.h index 20aec5e125..301cb40f31 100644 --- a/static_core/runtime/include/language_context.h +++ b/static_core/runtime/include/language_context.h @@ -77,6 +77,11 @@ public: virtual const uint8_t *GetStringArrayClassDescriptor() const = 0; + virtual const uint8_t *GetDynamicXRefClassDescriptor() const + { + return utf::CStringAsMutf8("Lpanda/DynamicXRef;"); + } + virtual const uint8_t *GetCtorName() const { return utf::CStringAsMutf8(ark::panda_file::GetCtorName(GetLanguage())); @@ -376,6 +381,11 @@ public: return base_->GetStringArrayClassDescriptor(); } + const uint8_t *GetDynamicXRefClassDescriptor() const + { + return base_->GetDynamicXRefClassDescriptor(); + } + const uint8_t *GetCtorName() const { return base_->GetCtorName(); diff --git a/static_core/runtime/interpreter/interpreter-inl.h b/static_core/runtime/interpreter/interpreter-inl.h index e029a76289..796138df43 100644 --- a/static_core/runtime/interpreter/interpreter-inl.h +++ b/static_core/runtime/interpreter/interpreter-inl.h @@ -3791,9 +3791,21 @@ public: RuntimeIfaceT::ThrowNullPointerException(); this->MoveToExceptionHandler(); } - - // NOTE: handle it - UNREACHABLE(); + auto *cls = obj->ClassAddr(); + ASSERT(cls != nullptr); + if (cls->IsJSValueClass()) { + // refer to node_api.h, js_value.h and runtime/interop_js overall + // NOTE: handle it + UNREACHABLE(); + } else { + ASSERT(cls->GetSourceLang() == ark::SourceLanguage::ETS); + // extended ets_stubs.h logic, which maps to core + // NOTE: handle it + UNREACHABLE(); + } + if (UNLIKELY(this->GetThread()->HasPendingException())) { + this->MoveToExceptionHandler(); + } } template @@ -3864,9 +3876,21 @@ public: RuntimeIfaceT::ThrowNullPointerException(); this->MoveToExceptionHandler(); } - - // NOTE: handle it - UNREACHABLE(); + auto *cls = obj->ClassAddr(); + ASSERT(cls != nullptr); + if (cls->IsJSValueClass()) { + // refer to node_api.h, js_value.h and runtime/interop_js overall + // NOTE: handle it + UNREACHABLE(); + } else { + ASSERT(cls->GetSourceLang() == ark::SourceLanguage::ETS); + // extended ets_stubs.h logic, which maps to core + // NOTE: handle it + UNREACHABLE(); + } + if (UNLIKELY(this->GetThread()->HasPendingException())) { + this->MoveToExceptionHandler(); + } } template -- Gitee