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 #include "ecmascript/sustaining_js_handle.h"
17 #include "ecmascript/jit/jit_thread.h"
18 #include "ecmascript/jit/jit_task.h"
19
20 namespace panda::ecmascript {
SustainingJSHandle(EcmaVM * vm)21 SustainingJSHandle::SustainingJSHandle(EcmaVM *vm) : vm_(vm)
22 {
23 vm_->AddSustainingJSHandle(this);
24 }
25
~SustainingJSHandle()26 SustainingJSHandle::~SustainingJSHandle()
27 {
28 vm_->RemoveSustainingJSHandle(this);
29 for (auto block : handleBlocks_) {
30 delete block;
31 }
32 handleBlocks_.clear();
33 }
34
GetJsHandleSlot(const JitThread * jitThread,JSTaggedType value)35 uintptr_t SustainingJSHandle::GetJsHandleSlot(const JitThread *jitThread, JSTaggedType value)
36 {
37 // new handle from jit current task sustaining jshandle
38 auto jitTask = jitThread->GetCurrentTask();
39 ASSERT(jitTask != nullptr);
40 auto sustainingJSHandle = jitTask->GetSustainingJSHandle();
41 ASSERT(sustainingJSHandle != nullptr);
42 return sustainingJSHandle->GetJsHandleSlot(value);
43 }
44
GetJsHandleSlot(JSTaggedType value)45 uintptr_t SustainingJSHandle::GetJsHandleSlot(JSTaggedType value)
46 {
47 if (blockNext_ == blockLimit_) {
48 Expand();
49 }
50 ASSERT(blockNext_ != blockLimit_);
51
52 *blockNext_ = value;
53 uintptr_t slot = reinterpret_cast<uintptr_t>(blockNext_);
54 blockNext_++;
55 return slot;
56 }
57
Expand()58 uintptr_t SustainingJSHandle::Expand()
59 {
60 auto block = new std::array<JSTaggedType, BLOCK_SIZE>();
61 handleBlocks_.push_back(block);
62
63 blockNext_ = &block->data()[0];
64 blockLimit_ = &block->data()[BLOCK_SIZE];
65 return reinterpret_cast<uintptr_t>(blockNext_);
66 }
67
Iterate(RootVisitor & v)68 void SustainingJSHandle::Iterate(RootVisitor &v)
69 {
70 size_t size = handleBlocks_.size();
71 for (size_t i = 0; i < size; ++i) {
72 auto block = handleBlocks_.at(i);
73 auto start = block->data();
74 auto end = (i != (size - 1)) ? &(block->data()[BLOCK_SIZE]) : blockNext_;
75 v.VisitRangeRoot(Root::ROOT_HANDLE, ObjectSlot(ToUintPtr(start)), ObjectSlot(ToUintPtr(end)));
76 }
77 }
78
AddSustainingJSHandle(SustainingJSHandle * sustainingJSHandle)79 void SustainingJSHandleList::AddSustainingJSHandle(SustainingJSHandle *sustainingJSHandle)
80 {
81 LockHolder lock(mutex_);
82 if (sustainingJSHandle == nullptr) {
83 return;
84 }
85
86 if (listHead_ == nullptr) {
87 listHead_ = sustainingJSHandle;
88 return;
89 }
90 sustainingJSHandle->next_ = listHead_;
91 listHead_->pre_ = sustainingJSHandle;
92 listHead_ = sustainingJSHandle;
93 }
94
RemoveSustainingJSHandle(SustainingJSHandle * sustainingJSHandle)95 void SustainingJSHandleList::RemoveSustainingJSHandle(SustainingJSHandle *sustainingJSHandle)
96 {
97 LockHolder lock(mutex_);
98 if (sustainingJSHandle == nullptr) {
99 return;
100 }
101
102 auto next = sustainingJSHandle->next_;
103 auto pre = sustainingJSHandle->pre_;
104 if (pre != nullptr) {
105 pre->next_ = next;
106 }
107 if (next != nullptr) {
108 next->pre_ = pre;
109 }
110
111 if (listHead_ == sustainingJSHandle) {
112 listHead_ = sustainingJSHandle->next_;
113 }
114 }
115
Iterate(RootVisitor & v)116 void SustainingJSHandleList::Iterate(RootVisitor &v)
117 {
118 LockHolder lock(mutex_);
119 for (auto handles = listHead_; handles != nullptr; handles = handles->next_) {
120 handles->Iterate(v);
121 }
122 }
123 } // namespace panda::ecmascript
124