• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 SRC_JSVM_REFERENCE_
17 #define SRC_JSVM_REFERENCE_
18 #include <cstdint>
19 
20 #include "jsvm_types.h"
21 #include "jsvm_util.h"
22 
23 namespace v8impl {
24 class RefTracker;
25 using RefList = RefTracker;
26 
27 class RefTracker {
28 public:
RefTracker()29     RefTracker() : next(nullptr), prev(nullptr) {}
30 
31     virtual ~RefTracker() = default;
32 
33     static void FinalizeAll(RefList* list);
34 
35 protected:
36     virtual void Finalize();
37 
38     inline void Link(RefList* list);
39 
Unlink()40     inline void Unlink()
41     {
42         if (prev != nullptr) {
43             prev->next = next;
44         }
45         if (next != nullptr) {
46             next->prev = prev;
47         }
48         prev = nullptr;
49         next = nullptr;
50     }
51 
52 private:
53     RefList* next;
54     RefList* prev;
55 };
56 
57 class UserReference final : public RefTracker {
58 public:
59     static UserReference* New(JSVM_Env env, v8::Local<v8::Value> value, uint32_t initialRefcount);
60 
61     static UserReference* NewData(JSVM_Env env, v8::Local<v8::Data> data, uint32_t initialRefcount);
62 
63     ~UserReference() override;
64 
65     // Increase and decrease reference
66     uint32_t Ref();
67     uint32_t Unref();
68     uint32_t RefCount();
69 
70     // Get v8::Local value
71     v8::Local<v8::Value> Get();
72     v8::Local<v8::Data> GetData();
73 
IsValue()74     bool IsValue()
75     {
76         return isValue;
77     }
78 
79 protected:
80     UserReference(JSVM_Env env, v8::Local<v8::Data> value, bool isValue, uint32_t initialRefcount);
81 
82     void Finalize() override;
83 
84 private:
85     void SetWeak();
86 
87 private:
88     v8impl::Persistent<v8::Data> persistent;
89     bool isValue;
90     JSVM_Env env;
91     uint32_t refcount;
92     bool canBeWeak;
93 };
94 
95 class FinalizerTracker : public RefTracker {
96 protected:
97     FinalizerTracker(JSVM_Env env, JSVM_Finalize cb, void* data, void* hint);
98 
99 public:
100     static FinalizerTracker* New(JSVM_Env env, JSVM_Finalize cb, void* finalizeData, void* finalizeHint);
101 
102     ~FinalizerTracker() override;
103 
GetData()104     void* GetData()
105     {
106         return data;
107     }
108 
109 protected:
110     void ResetFinalizer();
111 
112     void CallFinalizer();
113 
114     void Finalize() override;
115 
ResetEnv()116     void ResetEnv()
117     {
118         env = nullptr;
119     }
120 
121 private:
122     JSVM_Env env;
123     JSVM_Finalize cb;
124     void* data;
125     void* hint;
126 };
127 
128 class RuntimeReference : public FinalizerTracker {
129 protected:
130     RuntimeReference(JSVM_Env env, v8::Local<v8::Value> value, JSVM_Finalize cb, void* data, void* hint);
131 
132 public:
133     static RuntimeReference* New(JSVM_Env env, v8::Local<v8::Value> value, void* data);
134     static RuntimeReference* New(JSVM_Env env, v8::Local<v8::Value> value, JSVM_Finalize cb, void* data, void* hint);
135     static void DeleteReference(RuntimeReference* ref);
136 
137 private:
138     inline void SetWeak(bool needSecondPass);
139     static void FirstPassCallback(const v8::WeakCallbackInfo<RuntimeReference>& data);
140     static void SecondPassCallback(const v8::WeakCallbackInfo<RuntimeReference>& data);
141     static void FirstPassCallbackWithoutFinalizer(const v8::WeakCallbackInfo<RuntimeReference>& data);
142 
143 private:
144     v8impl::Persistent<v8::Value> persistent;
145 };
146 
147 class TrackedStringResource : public FinalizerTracker {
148 public:
TrackedStringResource(JSVM_Env env,JSVM_Finalize finalizeCallback,void * data,void * finalizeHint)149     TrackedStringResource(JSVM_Env env, JSVM_Finalize finalizeCallback, void* data, void* finalizeHint)
150         : FinalizerTracker(env, finalizeCallback, data, finalizeHint)
151     {}
152 
153 protected:
154     // The only time Finalize() gets called before Dispose() is if the
155     // environment is dying. Finalize() expects that the item will be unlinked,
156     // so we do it here. V8 will still call Dispose() on us later, so we don't do
157     // any deleting here. We just null out env_ to avoid passing a stale pointer
158     // to the user's finalizer when V8 does finally call Dispose().
Finalize()159     void Finalize() override
160     {
161         Unlink();
162         ResetEnv();
163     }
164 
~TrackedStringResource()165     ~TrackedStringResource() override
166     {
167         CallFinalizer();
168     }
169 };
170 
171 class ExternalOneByteStringResource : public v8::String::ExternalOneByteStringResource, TrackedStringResource {
172 public:
ExternalOneByteStringResource(JSVM_Env env,char * string,const size_t length,JSVM_Finalize finalizeCallback,void * finalizeHint)173     ExternalOneByteStringResource(JSVM_Env env,
174                                   char* string,
175                                   const size_t length,
176                                   JSVM_Finalize finalizeCallback,
177                                   void* finalizeHint)
178         : TrackedStringResource(env, finalizeCallback, string, finalizeHint), string_(string), length_(length)
179     {}
180 
data()181     const char* data() const override
182     {
183         return string_;
184     }
length()185     size_t length() const override
186     {
187         return length_;
188     }
189 
190 private:
191     const char* string_;
192     const size_t length_;
193 };
194 
195 class ExternalStringResource : public v8::String::ExternalStringResource, TrackedStringResource {
196 public:
ExternalStringResource(JSVM_Env env,char16_t * string,const size_t length,JSVM_Finalize finalizeCallback,void * finalizeHint)197     ExternalStringResource(JSVM_Env env,
198                            char16_t* string,
199                            const size_t length,
200                            JSVM_Finalize finalizeCallback,
201                            void* finalizeHint)
202         : TrackedStringResource(env, finalizeCallback, string, finalizeHint),
203           string_(reinterpret_cast<uint16_t*>(string)), length_(length)
204     {}
205 
data()206     const uint16_t* data() const override
207     {
208         return string_;
209     }
length()210     size_t length() const override
211     {
212         return length_;
213     }
214 
215 private:
216     const uint16_t* string_;
217     const size_t length_;
218 };
219 
220 } // namespace v8impl
221 
222 #endif