diff --git a/static_core/isa/isa.yaml b/static_core/isa/isa.yaml index 5b8ee5e6f66904efa7f056e5c5336ee9f89f018d..be60e12175acf14fd381eadb657b2aa5deef84c7 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 df5dec05f5a58f2c7f127619af0b6068107bdbab..0c3ffea023757903418f83636d1db216eae61fdc 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 4b2250bb7f67ddbb8f45e9429a8826108abd3d62..869754e469f03ab46ebb1939800897763c6baa55 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 bc1be51e88038d7e674cefef6064a5c048de562d..343cba50cf6e9e97b7ae90fd2469c5c9f7391362 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 d45b46f84dd79f9f127c6101dfdd5a2f488625fd..c7b7bc30e2b3d8ad6e91c316a6843cc6e348b3d7 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 0a2588a17fb168747b27d40a144ecfee5704fd32..1d2c1ae5390ee0eb1ca34ef0545351d3917fe6ef 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 9a463f65386eb916b4c1e74c4cf459f6fb47e976..fa99d317e830547abf0c89522d92126eb3a3a631 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 a6a2d4e88329b404b8ec0800dd40a42f6dbb7d62..0f2090d72f88a3027bb35a4e048eb5e0f0836ba2 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 a6121da5975ae474ead8522102d18625d9b97725..ecf5ee50b172360e40c4da65450af6e625a976d7 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 69d841ab4ede4fc3ccb507311d75eab2b7aa6e48..3430e563c4ea03e161015b03c5f10f0a52dce8a8 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 0000000000000000000000000000000000000000..f5c492c7a9477ad40caeeb02cf34af43c8cb11a5 --- /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 20aec5e125093f66f971754ee2cdd594ea4e713e..301cb40f3191f478524ee5759346892ce06f26de 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 e029a7628933a0d7624e01e1d79c15ce37d701be..796138df43afa6ce3ccd1fd72626f3c29b385402 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