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