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