• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_PLUGINS_ETS_RUNTIME_TYPES_ETS_ESCOMPAT_ARRAY_H
17 #define PANDA_PLUGINS_ETS_RUNTIME_TYPES_ETS_ESCOMPAT_ARRAY_H
18 
19 #include <cstdint>
20 
21 #include "libpandabase/macros.h"
22 #include "libpandabase/mem/object_pointer.h"
23 #include "runtime/include/thread.h"
24 #include "runtime/include/managed_thread.h"
25 #include "runtime/coroutines/coroutine.h"
26 #include "runtime/entrypoints/entrypoints.h"
27 #include "plugins/ets/runtime/ets_class_linker_extension.h"
28 #include "plugins/ets/runtime/ets_coroutine.h"
29 #include "plugins/ets/runtime/ets_vm.h"
30 #include "plugins/ets/runtime/types/ets_object.h"
31 #include "plugins/ets/runtime/types/ets_array.h"
32 #include "plugins/ets/runtime/types/ets_box_primitive.h"
33 #include "plugins/ets/runtime/types/ets_method.h"
34 
35 namespace ark::ets {
36 
37 namespace test {
38 template <class ElementType>
39 class EtsArrayObjectMembers;
40 }  // namespace test
41 
42 // Mirror class for Array<T> from ETS stdlib
43 template <class ElementType>
44 class EtsArrayObject : public EtsObject {
45 public:
46     EtsArrayObject() = delete;
47     ~EtsArrayObject() = delete;
48 
49     NO_COPY_SEMANTIC(EtsArrayObject);
50     NO_MOVE_SEMANTIC(EtsArrayObject);
51 
AsObject()52     EtsObject *AsObject()
53     {
54         return this;
55     }
56 
AsObject()57     const EtsObject *AsObject() const
58     {
59         return this;
60     }
61 
FromEtsObject(EtsObject * etsObj)62     static EtsArrayObject *FromEtsObject(EtsObject *etsObj)
63     {
64         return reinterpret_cast<EtsArrayObject *>(etsObj);
65     }
66 
GetData()67     EtsTypedObjectArray<ElementType> *GetData()
68     {
69         return reinterpret_cast<EtsTypedObjectArray<ElementType> *>(GetFieldObject(GetBufferOffset()));
70     }
71 
GetActualLength()72     uint32_t GetActualLength()
73     {
74         return helpers::ToUnsigned(GetFieldPrimitive<EtsInt>(GetActualLengthOffset()));
75     }
76 
GetBufferOffset()77     static constexpr size_t GetBufferOffset()
78     {
79         return MEMBER_OFFSET(EtsArrayObject, buffer_);
80     }
81 
GetActualLengthOffset()82     static constexpr size_t GetActualLengthOffset()
83     {
84         return MEMBER_OFFSET(EtsArrayObject, actualLength_);
85     }
86 
Create(size_t length)87     static EtsArrayObject *Create(size_t length)
88     {
89         auto *coro = EtsCoroutine::GetCurrent();
90         ASSERT(coro->HasPendingException() == false);
91 
92         EtsHandleScope scope(coro);
93 
94         const EtsPlatformTypes *platformTypes = PlatformTypes(coro->GetPandaVM());
95         EtsClass *klass = platformTypes->escompatArray;
96         EtsHandle<EtsArrayObject> arrayHandle(coro, FromEtsObject(EtsObject::Create(klass)));
97 
98         auto *ctor = klass->GetDirectMethod(coro->GetLanguageContext().GetCtorName(), "I:V");
99         ASSERT(ctor != nullptr);
100 
101         std::array args {Value(arrayHandle->GetCoreType()), Value(length)};
102         ctor->GetPandaMethod()->InvokeVoid(coro, args.data());
103 
104         if (UNLIKELY(coro->HasPendingException())) {
105             if (coro->GetPandaVM()->GetOOMErrorObject() == nullptr ||
106                 (coro->GetException()->ClassAddr<Class>() ==
107                  coro->GetPandaVM()->GetOOMErrorObject()->ClassAddr<Class>())) {
108                 coro->ClearException();
109                 return nullptr;
110             }
111             // We do not expect any other exception than OOM
112             UNREACHABLE();
113         }
114 
115         return arrayHandle.GetPtr();
116     }
117 
118     /// @return Returns a status code of bool indicating success or failure.
SetRef(size_t index,ElementType * ref)119     bool SetRef(size_t index, ElementType *ref)
120     {
121         if (index >= GetActualLength()) {
122             return false;
123         }
124 
125         GetData()->Set(index, ref);
126         return true;
127     }
128 
129     /// @return Returns a status code of bool indicating success or failure.
GetRef(size_t index,ElementType ** ref)130     bool GetRef(size_t index, ElementType **ref)
131     {
132         ASSERT(ref != nullptr);
133         if (index >= GetActualLength()) {
134             return false;
135         }
136 
137         *ref = GetData()->Get(index);
138         return true;
139     }
140 
141 private:
142     ObjectPointer<EtsTypedObjectArray<ElementType>> buffer_;
143     EtsInt actualLength_;
144 
145     friend class test::EtsArrayObjectMembers<ElementType>;
146 };
147 
148 using EtsBoxedBooleanArray = EtsArrayObject<EtsBoxPrimitive<EtsBoolean>>;
149 using EtsBoxedByteArray = EtsArrayObject<EtsBoxPrimitive<EtsByte>>;
150 using EtsBoxedCharArray = EtsArrayObject<EtsBoxPrimitive<EtsChar>>;
151 using EtsBoxedShortArray = EtsArrayObject<EtsBoxPrimitive<EtsShort>>;
152 using EtsBoxedIntArray = EtsArrayObject<EtsBoxPrimitive<EtsInt>>;
153 using EtsBoxedLongArray = EtsArrayObject<EtsBoxPrimitive<EtsLong>>;
154 using EtsBoxedFloatArray = EtsArrayObject<EtsBoxPrimitive<EtsFloat>>;
155 using EtsBoxedDoubleArray = EtsArrayObject<EtsBoxPrimitive<EtsDouble>>;
156 
157 }  // namespace ark::ets
158 
159 #endif  // PANDA_PLUGINS_ETS_RUNTIME_TYPES_ETS_ESCOMPAT_ARRAY_H
160