• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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/dependent_infos.h"
17 
18 #include "ecmascript/deoptimizer/deoptimizer.h"
19 #include "ecmascript/js_function.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
22 
23 namespace panda::ecmascript {
24 
AppendDependentInfos(JSThread * thread,const JSHandle<JSTaggedValue> jsFunc,const DependentStateCollection collection,const JSHandle<DependentInfos> info)25 JSHandle<DependentInfos> DependentInfos::AppendDependentInfos(JSThread *thread,
26                                                               const JSHandle<JSTaggedValue> jsFunc,
27                                                               const DependentStateCollection collection,
28                                                               const JSHandle<DependentInfos> info)
29 {
30     JSHandle<JSTaggedValue> first = jsFunc;
31     JSHandle<JSTaggedValue> second(thread, JSTaggedValue(collection));
32     JSHandle<WeakVector> newVec1 = WeakVector::Append(thread,
33         JSHandle<WeakVector>::Cast(info), first, ElementType::WEAK);
34     JSHandle<WeakVector> newVec2 = WeakVector::Append(thread, newVec1, second);
35     return JSHandle<DependentInfos>(newVec2);
36 }
37 
38 // static
TraceLazyDeoptReason(JSThread * thread,JSHandle<JSFunction> func,DependentStateCollection collection)39 void DependentInfos::TraceLazyDeoptReason(JSThread *thread, JSHandle<JSFunction> func,
40                                           DependentStateCollection collection)
41 {
42     if (!thread->GetEcmaVM()->GetJSOptions().IsEnableLazyDeoptTrace()) {
43         return;
44     }
45     JSTaggedValue funcName = JSFunction::NameGetter(thread, JSHandle<JSObject>::Cast(func));
46     std::string funNameS = "Lazy Deoptimization occurred on";
47     funNameS += " function: \"" + EcmaStringAccessor(funcName).ToStdString(thread) + "\"";
48     LOG_TRACE(INFO) << funNameS;
49     // Get the lowbit of collection.
50     uint32_t value = (static_cast<uint32_t>(collection) & (-static_cast<uint32_t>(collection)));
51     std::string reason;
52     switch (value) {
53     #define LAZY_DEOPT_TYPE_CASE(name, value)           \
54         case (value): {                                 \
55             reason = #name;                             \
56             break;                                      \
57         }
58         LAZY_DEOPT_TYPE_LIST(LAZY_DEOPT_TYPE_CASE)
59     #undef LAZY_DEOPT_TYPE_CASE
60         default:
61             reason = "Unknown";
62     }
63     LOG_TRACE(INFO) << "Lazy Deoptimize reason: " << reason;
64     std::string data = JsStackInfo::BuildJsStackTrace(thread, true);
65     LOG_COMPILER(INFO) << "Lazy Deoptimize" << data;
66 }
67 
68 // static
TriggerLazyDeoptimization(JSHandle<DependentInfos> dependentInfos,JSThread * thread,DependentStateCollection collection)69 void DependentInfos::TriggerLazyDeoptimization(JSHandle<DependentInfos> dependentInfos,
70                                                JSThread *thread, DependentStateCollection collection)
71 {
72     bool hasDeoptMethod = false;
73     for (uint32_t i = 0; i < dependentInfos->GetEnd(); i += SLOT_PER_ENTRY) {
74         DependentStateCollection depCollection =
75             static_cast<DependentStateCollection>(
76                 dependentInfos->GetPrimitive(i + COLLECTION_SLOT_OFFSET).GetInt());
77         if (!CheckCollectionEffect(depCollection, collection)) {
78             continue;
79         }
80         JSTaggedValue rawValue = dependentInfos->Get(thread, i + FUNCTION_SLOT_OFFSET).GetWeakRawValue();
81         if (!rawValue.IsHeapObject()) {
82             continue;
83         }
84         JSHandle<JSFunction> func(thread, rawValue);
85         if (func->IsCompiledCode()) {
86             hasDeoptMethod = true;
87             JSHandle<Method> method(thread, func->GetMethod(thread));
88             // When lazy deopt happened, the deopt method cannot call as jit any more.
89             Deoptimizier::ClearCompiledCodeStatusWhenDeopt(thread,
90                                                            func.GetObject<JSFunction>(),
91                                                            method.GetObject<Method>(),
92                                                            kungfu::DeoptType::LAZYDEOPT);
93             TraceLazyDeoptReason(thread, func, (depCollection & collection));
94         }
95     }
96     if (hasDeoptMethod) {
97         // Replace return address
98         Deoptimizier::PrepareForLazyDeopt(thread);
99     }
100 }
101 }  // namespace panda::ecmascript
102