• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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/ecma_handle_scope.h"
17 
18 #include "ecmascript/ecma_context.h"
19 
20 namespace panda::ecmascript {
EcmaHandleScope(JSThread * thread)21 EcmaHandleScope::EcmaHandleScope(JSThread *thread) : thread_(thread)
22 {
23     auto context = thread_->GetCurrentEcmaContext();
24     prevNext_ = context->handleScopeStorageNext_;
25     prevEnd_ = context->handleScopeStorageEnd_;
26     prevHandleStorageIndex_ = context->currentHandleStorageIndex_;
27 #ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
28     context->HandleScopeCountAdd();
29     prevHandleScope_ = context->GetLastHandleScope();
30     context->SetLastHandleScope(this);
31 #endif
32 }
33 
~EcmaHandleScope()34 EcmaHandleScope::~EcmaHandleScope()
35 {
36     auto context = thread_->GetCurrentEcmaContext();
37 #ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
38     context->HandleScopeCountDec();
39     context->SetLastHandleScope(prevHandleScope_);
40     prevHandleScope_ = nullptr;
41 #endif
42     context->handleScopeStorageNext_ = prevNext_;
43     if (context->handleScopeStorageEnd_ != prevEnd_) {
44         context->handleScopeStorageEnd_ = prevEnd_;
45         context->ShrinkHandleStorage(prevHandleStorageIndex_);
46     }
47 }
48 
NewHandle(JSThread * thread,JSTaggedType value)49 uintptr_t EcmaHandleScope::NewHandle(JSThread *thread, JSTaggedType value)
50 {
51     auto context = thread->GetCurrentEcmaContext();
52 #ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
53     // Each Handle must be managed by HandleScope, otherwise it may cause Handle leakage.
54     if (context->handleScopeCount_ <= 0) {
55         LOG_ECMA(ERROR) << "New handle must be in handlescope" << context->handleScopeCount_;
56     }
57     static const long MAYBE_HANDLE_LEAK_TIME_MS = 5000;
58     if (context->GetLastHandleScope() != nullptr) {
59         float totalSpentTime = context->GetLastHandleScope()->scope_.TotalSpentTime();
60         if (totalSpentTime >= MAYBE_HANDLE_LEAK_TIME_MS) {
61             LOG_ECMA(INFO) << "New handle in scope count:" << context->handleScopeCount_
62                             << ", time:" << totalSpentTime << "ms";
63             std::ostringstream stack;
64             Backtrace(stack, true);
65             LOG_ECMA(INFO) << stack.str();
66         }
67     }
68 #endif
69     auto result = context->handleScopeStorageNext_;
70     if (result == context->handleScopeStorageEnd_) {
71         result = reinterpret_cast<JSTaggedType *>(context->ExpandHandleStorage());
72     }
73 #if ECMASCRIPT_ENABLE_NEW_HANDLE_CHECK
74     thread->CheckJSTaggedType(value);
75     if (result == nullptr) {
76         LOG_ECMA(ERROR) << "result is nullptr, New handle fail!";
77         return nullptr;
78     }
79 #endif
80     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
81     context->handleScopeStorageNext_ = result + 1;
82     *result = value;
83     return reinterpret_cast<uintptr_t>(result);
84 }
85 }  // namespace panda::ecmascript