• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "ecmascript/deoptimizer/deoptimizer.h"
16 
17 #include <cmath>
18 
19 #include "ecmascript/compiler/assembler/assembler.h"
20 #include "ecmascript/compiler/gate_meta_data.h"
21 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
22 #include "ecmascript/frames.h"
23 #include "ecmascript/interpreter/interpreter.h"
24 #include "ecmascript/js_thread.h"
25 #include "ecmascript/stubs/runtime_stubs-inl.h"
26 
27 namespace panda::ecmascript {
28 class FrameWriter {
29 public:
FrameWriter(Deoptimizier * deoptimizier)30     explicit FrameWriter(Deoptimizier *deoptimizier) : thread_(deoptimizier->GetThread())
31     {
32         JSTaggedType *prevSp = const_cast<JSTaggedType *>(thread_->GetCurrentSPFrame());
33         start_ = top_ = EcmaInterpreter::GetInterpreterFrameEnd(thread_, prevSp);
34     }
35 
PushValue(JSTaggedType value)36     void PushValue(JSTaggedType value)
37     {
38         *(--top_) = value;
39     }
40 
PushRawValue(uintptr_t value)41     void PushRawValue(uintptr_t value)
42     {
43         *(--top_) = value;
44     }
45 
Reserve(size_t size)46     bool Reserve(size_t size)
47     {
48         return !thread_->DoStackOverflowCheck(top_ - size);
49     }
50 
ReserveAsmInterpretedFrame()51     AsmInterpretedFrame *ReserveAsmInterpretedFrame()
52     {
53         auto frame = AsmInterpretedFrame::GetFrameFromSp(top_);
54         top_ = reinterpret_cast<JSTaggedType *>(frame);
55         return frame;
56     }
57 
GetStart() const58     JSTaggedType *GetStart() const
59     {
60         return start_;
61     }
62 
GetTop() const63     JSTaggedType *GetTop() const
64     {
65         return top_;
66     }
67 
GetFirstFrame() const68     JSTaggedType *GetFirstFrame() const
69     {
70         return firstFrame_;
71     }
72 
RecordFirstFrame()73     void RecordFirstFrame()
74     {
75         firstFrame_ = top_;
76     }
77 
ReviseValueByIndex(JSTaggedType value,size_t index)78     void ReviseValueByIndex(JSTaggedType value, size_t index)
79     {
80         ASSERT(index < static_cast<size_t>(start_ - top_));
81         *(top_ + index) = value;
82     }
83 
84 private:
85     JSThread *thread_ {nullptr};
86     JSTaggedType *start_ {nullptr};
87     JSTaggedType *top_ {nullptr};
88     JSTaggedType *firstFrame_ {nullptr};
89 };
90 
CollectVregs(const std::vector<kungfu::ARKDeopt> & deoptBundle,size_t shift)91 void Deoptimizier::CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle, size_t shift)
92 {
93     deoptVregs_.clear();
94     for (size_t i = 0; i < deoptBundle.size(); i++) {
95         ARKDeopt deopt = deoptBundle.at(i);
96         JSTaggedType v;
97         VRegId id = deopt.id;
98         if (std::holds_alternative<DwarfRegAndOffsetType>(deopt.value)) {
99             ASSERT(deopt.kind == LocationTy::Kind::INDIRECT);
100             auto value = std::get<DwarfRegAndOffsetType>(deopt.value);
101             DwarfRegType dwarfReg = value.first;
102             OffsetType offset = value.second;
103             ASSERT (dwarfReg == GCStackMapRegisters::FP || dwarfReg == GCStackMapRegisters::SP);
104             uintptr_t addr;
105             if (dwarfReg == GCStackMapRegisters::SP) {
106                 addr = context_.callsiteSp + offset;
107             } else {
108                 addr = context_.callsiteFp + offset;
109             }
110             v = *(reinterpret_cast<JSTaggedType *>(addr));
111         } else if (std::holds_alternative<LargeInt>(deopt.value)) {
112             ASSERT(deopt.kind == LocationTy::Kind::CONSTANTNDEX);
113             v = JSTaggedType(static_cast<int64_t>(std::get<LargeInt>(deopt.value)));
114         } else {
115             ASSERT(std::holds_alternative<IntType>(deopt.value));
116             ASSERT(deopt.kind == LocationTy::Kind::CONSTANT);
117             v = JSTaggedType(static_cast<int64_t>(std::get<IntType>(deopt.value)));
118         }
119         size_t curDepth = DecodeDeoptDepth(id, shift);
120         OffsetType vregId = static_cast<OffsetType>(DecodeVregIndex(id, shift));
121         if (vregId != static_cast<OffsetType>(SpecVregIndex::PC_OFFSET_INDEX)) {
122             deoptVregs_.insert({{curDepth, vregId}, JSHandle<JSTaggedValue>(thread_, JSTaggedValue(v))});
123         } else {
124             pc_.insert({curDepth, static_cast<size_t>(v)});
125         }
126     }
127 }
128 
129 // when AOT trigger deopt, frame layout as the following
130 // * OptimizedJSFunctionFrame layout description as the following:
131 //               +--------------------------+ ---------------
132 //               |        ......            |               ^
133 //               |        ......            |       callerFunction
134 //               |        ......            |               |
135 //               |--------------------------|               |
136 //               |        args              |               v
137 //               +--------------------------+ ---------------
138 //               |       returnAddr         |               ^
139 //               |--------------------------|               |
140 //               |       callsiteFp         |               |
141 //               |--------------------------|   OptimizedJSFunction  FrameType:OPTIMIZED_JS_FUNCTION_FRAME
142 //               |       frameType          |               |
143 //               |--------------------------|               |
144 //               |       call-target        |               |
145 //               |--------------------------|               |
146 //               |       lexEnv             |               |
147 //               |--------------------------|               |
148 //               |       ...........        |               v
149 //               +--------------------------+ ---------------
150 //               |       returnAddr         |               ^
151 //               |--------------------------|               |
152 //               |       callsiteFp         |               |
153 //               |--------------------------|   __llvm_deoptimize  FrameType:OPTIMIZED_FRAME
154 //               |       frameType          |               |
155 //               |--------------------------|               |
156 //               |       No CalleeSave      |               |
157 //               |       Registers          |               v
158 //               +--------------------------+ ---------------
159 //               |       returnAddr         |               ^
160 //               |--------------------------|               |
161 //               |       callsiteFp         |               |
162 //               |--------------------------|   DeoptHandlerAsm  FrameType:ASM_BRIDGE_FRAME
163 //               |       frameType          |               |
164 //               |--------------------------|               |
165 //               |       glue               |               |
166 //               |--------------------------|               |
167 //               | CalleeSave Registers     |               v
168 //               +--------------------------+ ---------------
169 //               |       .........          |               ^
170 //               |       .........          |     CallRuntime   FrameType:LEAVE_FRAME
171 //               |       .........          |               |
172 //               |       .........          |               v
173 //               |--------------------------| ---------------
174 
175 // After gathering the necessary information(After Call Runtime), frame layout after constructing
176 // asminterpreterframe is shown as the following:
177 //               +----------------------------------+---------+
178 //               |        ......                    |         ^
179 //               |        ......                    |   callerFunction
180 //               |        ......                    |         |
181 //               |----------------------------------|         |
182 //               |        args                      |         v
183 //               +----------------------------------+---------+
184 //               |       returnAddr                 |         ^
185 //               |----------------------------------|         |
186 //               |       frameType                  |         |
187 //               |----------------------------------|    ASM_INTERPRETER_BRIDGE_FRAME
188 //               |       callsiteFp                 |         |
189 //               |----------------------------------|         |
190 //               |       ...........                |         v
191 //               +----------------------------------+---------+
192 //               |       returnAddr                 |
193 //               |----------------------------------|
194 //               |    argv[n-1]                     |
195 //               |----------------------------------|
196 //               |    ......                        |
197 //               |----------------------------------|
198 //               |    thisArg [maybe not exist]     |
199 //               |----------------------------------|
200 //               |    newTarget [maybe not exist]   |
201 //               |----------------------------------|
202 //               |    ......                        |
203 //               |----------------------------------|
204 //               |    Vregs [not exist in native]   |
205 //               +----------------------------------+--------+
206 //               |        .  .  .   .               |        ^
207 //               |     InterpretedFrameBase         |        |
208 //               |        .  .  .   .               |        |
209 //               |----------------------------------|        |
210 //               |    pc(bytecode addr)             |        |
211 //               |----------------------------------|        |
212 //               |    sp(current stack pointer)     |        |
213 //               |----------------------------------|   AsmInterpretedFrame 0
214 //               |    callSize                      |        |
215 //               |----------------------------------|        |
216 //               |    env                           |        |
217 //               |----------------------------------|        |
218 //               |    acc                           |        |
219 //               |----------------------------------|        |
220 //               |    thisObj                       |        |
221 //               |----------------------------------|        |
222 //               |    call-target                   |        v
223 //               +----------------------------------+--------+
224 //               |    argv[n-1]                     |
225 //               |----------------------------------|
226 //               |    ......                        |
227 //               |----------------------------------|
228 //               |    thisArg [maybe not exist]     |
229 //               |----------------------------------|
230 //               |    newTarget [maybe not exist]   |
231 //               |----------------------------------|
232 //               |    ......                        |
233 //               |----------------------------------|
234 //               |    Vregs [not exist in native]   |
235 //               +----------------------------------+--------+
236 //               |        .  .  .   .               |        ^
237 //               |     InterpretedFrameBase         |        |
238 //               |        .  .  .   .               |        |
239 //               |----------------------------------|        |
240 //               |    pc(bytecode addr)             |        |
241 //               |----------------------------------|        |
242 //               |    sp(current stack pointer)     |        |
243 //               |----------------------------------|   AsmInterpretedFrame 1
244 //               |    callSize                      |        |
245 //               |----------------------------------|        |
246 //               |    env                           |        |
247 //               |----------------------------------|        |
248 //               |    acc                           |        |
249 //               |----------------------------------|        |
250 //               |    thisObj                       |        |
251 //               |----------------------------------|        |
252 //               |    call-target                   |        v
253 //               +----------------------------------+--------+
254 //               |        .  .  .   .               |        ^
255 //               |        .  .  .   .               |   AsmInterpretedFrame n
256 //               |        .  .  .   .               |        v
257 //               +----------------------------------+--------+
258 
CollectDeoptBundleVec(std::vector<ARKDeopt> & deoptBundle)259 void Deoptimizier::CollectDeoptBundleVec(std::vector<ARKDeopt>& deoptBundle)
260 {
261     JSTaggedType *lastLeave = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
262     FrameIterator it(lastLeave, thread_);
263     // note: last deopt bridge frame is generated by DeoptHandlerAsm, callee Regs is grow from this frame
264     for (; !it.Done() && deoptBundle.empty(); it.Advance<GCVisitedFlag::VISITED>()) {
265         FrameType type = it.GetFrameType();
266         switch (type) {
267             case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
268             case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
269                 auto frame = it.GetFrame<OptimizedJSFunctionFrame>();
270                 frame->GetDeoptBundleInfo(it, deoptBundle);
271                 CalleeRegAndOffsetVec calleeRegInfo;
272                 frame->GetFuncCalleeRegAndOffset(it, calleeRegInfo);
273                 context_.calleeRegAndOffset = calleeRegInfo;
274                 context_.callsiteSp = it.GetCallSiteSp();
275                 context_.callsiteFp = reinterpret_cast<uintptr_t>(it.GetSp());
276                 auto preFrameSp = frame->ComputePrevFrameSp(it);
277                 frameArgc_ = frame->GetArgc(preFrameSp);
278                 frameArgvs_ = frame->GetArgv(preFrameSp);
279                 stackContext_.callFrameTop_ = it.GetPrevFrameCallSiteSp();
280                 stackContext_.returnAddr_ = frame->GetReturnAddr();
281                 stackContext_.callerFp_ = reinterpret_cast<uintptr_t>(frame->GetPrevFrameFp());
282                 break;
283             }
284             case FrameType::ASM_BRIDGE_FRAME: {
285                 auto sp = reinterpret_cast<uintptr_t*>(it.GetSp());
286                 static constexpr size_t TYPE_GLUE_SLOT = 2; // 2: skip type & glue
287                 sp -= TYPE_GLUE_SLOT;
288                 calleeRegAddr_ = sp - numCalleeRegs_;
289                 break;
290             }
291             case FrameType::OPTIMIZED_FRAME:
292             case FrameType::LEAVE_FRAME:
293                 break;
294             default: {
295                 LOG_FULL(FATAL) << "frame type error!";
296                 UNREACHABLE();
297             }
298         }
299     }
300     ASSERT(!it.Done());
301 }
302 
GetMethod(JSTaggedValue & target)303 Method* Deoptimizier::GetMethod(JSTaggedValue &target)
304 {
305     ECMAObject *callTarget = reinterpret_cast<ECMAObject*>(target.GetTaggedObject());
306     ASSERT(callTarget != nullptr);
307     Method *method = callTarget->GetCallTarget();
308     return method;
309 }
310 
RelocateCalleeSave()311 void Deoptimizier::RelocateCalleeSave()
312 {
313     CalleeReg callreg;
314     for (auto &it: context_.calleeRegAndOffset) {
315         auto reg = it.first;
316         auto offset = it.second;
317         uintptr_t value = *(reinterpret_cast<uintptr_t *>(context_.callsiteFp + offset));
318         int order = callreg.FindCallRegOrder(reg);
319         calleeRegAddr_[order] = value;
320     }
321 }
322 
CollectVirtualRegisters(Method * method,FrameWriter * frameWriter,size_t curDepth)323 bool Deoptimizier::CollectVirtualRegisters(Method* method, FrameWriter *frameWriter, size_t curDepth)
324 {
325     int32_t actualNumArgs = 0;
326     int32_t declaredNumArgs = 0;
327     if (curDepth == 0) {
328         actualNumArgs = static_cast<int32_t>(GetDeoptValue(curDepth,
329             static_cast<int32_t>(SpecVregIndex::ACTUAL_ARGC_INDEX)).GetInt());
330         declaredNumArgs = static_cast<int32_t>(method->GetNumArgsWithCallField());
331     } else {
332         // inline method actualNumArgs equal to declaredNumArgs
333         actualNumArgs = static_cast<int32_t>(method->GetNumArgsWithCallField());
334         declaredNumArgs = static_cast<int32_t>(method->GetNumArgsWithCallField());
335     }
336 
337     int32_t callFieldNumVregs = static_cast<int32_t>(method->GetNumVregsWithCallField());
338 
339     // layout of frame:
340     // [maybe argc] [actual args] [reserved args] [call field virtual regs]
341 
342     // [maybe argc]
343     if (!method->IsFastCall() && declaredNumArgs != actualNumArgs) {
344         auto value = JSTaggedValue(actualNumArgs);
345         frameWriter->PushValue(value.GetRawData());
346     }
347     int32_t virtualIndex = declaredNumArgs + callFieldNumVregs +
348         static_cast<int32_t>(method->GetNumRevervedArgs()) - 1;
349     if (!frameWriter->Reserve(static_cast<size_t>(virtualIndex))) {
350         return false;
351     }
352     for (int32_t i = static_cast<int32_t>(declaredNumArgs - 1); i >= 0; i--) {
353         JSTaggedValue value = JSTaggedValue::Undefined();
354         // deopt value
355         if (HasDeoptValue(curDepth, virtualIndex)) {
356             value = GetDeoptValue(curDepth, virtualIndex);
357         }
358         frameWriter->PushValue(value.GetRawData());
359         virtualIndex--;
360     }
361 
362     // [reserved args]
363     if (method->HaveThisWithCallField()) {
364         JSTaggedValue value = deoptVregs_.at(
365             {curDepth, static_cast<OffsetType>(SpecVregIndex::THIS_OBJECT_INDEX)}).GetTaggedValue();
366         frameWriter->PushValue(value.GetRawData());
367         virtualIndex--;
368     }
369     if (method->HaveNewTargetWithCallField()) {
370         JSTaggedValue value = deoptVregs_.at(
371             {curDepth, static_cast<OffsetType>(SpecVregIndex::NEWTARGET_INDEX)}).GetTaggedValue();
372         frameWriter->PushValue(value.GetRawData());
373         virtualIndex--;
374     }
375     if (method->HaveFuncWithCallField()) {
376         JSTaggedValue value = deoptVregs_.at(
377             {curDepth, static_cast<OffsetType>(SpecVregIndex::FUNC_INDEX)}).GetTaggedValue();
378         frameWriter->PushValue(value.GetRawData());
379         virtualIndex--;
380     }
381 
382     // [call field virtual regs]
383     for (int32_t i = virtualIndex; i >= 0; i--) {
384         JSTaggedValue value = GetDeoptValue(curDepth, virtualIndex);
385         frameWriter->PushValue(value.GetRawData());
386         virtualIndex--;
387     }
388     // revise correct a0 - aN virtual regs , for example: ldobjbyname key; sta a2; update value to a2
389     //         +--------------------------+            ^
390     //         |       aN                 |            |
391     //         +--------------------------+            |
392     //         |       ...                |            |
393     //         +--------------------------+            |
394     //         |       a2(this)           |            |
395     //         +--------------------------+   revise correct vreg
396     //         |       a1(newtarget)      |            |
397     //         +--------------------------+            |
398     //         |       a0(func)           |            |
399     //         |--------------------------|            v
400     //         |       v0 - vN            |
401     //  sp --> |--------------------------|
402     int32_t vregsAndArgsNum = declaredNumArgs + callFieldNumVregs +
403         static_cast<int32_t>(method->GetNumRevervedArgs());
404     for (int32_t i = callFieldNumVregs; i < vregsAndArgsNum; i++) {
405         JSTaggedValue value = JSTaggedValue::Undefined();
406         if (HasDeoptValue(curDepth, i)) {
407             value = GetDeoptValue(curDepth, i);
408             frameWriter->ReviseValueByIndex(value.GetRawData(), i);
409         }
410     }
411     return true;
412 }
413 
Dump(Method * method,kungfu::DeoptType type,size_t depth)414 void Deoptimizier::Dump(Method* method, kungfu::DeoptType type, size_t depth)
415 {
416     if (traceDeopt_) {
417         std::string checkType = DisplayItems(type);
418         LOG_COMPILER(INFO) << "Check Type: " << checkType;
419         std::string data = JsStackInfo::BuildJsStackTrace(thread_, true);
420         LOG_COMPILER(INFO) << "Deoptimize" << data;
421         const uint8_t *pc = method->GetBytecodeArray() + pc_.at(depth);
422         BytecodeInstruction inst(pc);
423         LOG_COMPILER(INFO) << inst;
424     }
425 }
426 
DisplayItems(DeoptType type)427 std::string Deoptimizier::DisplayItems(DeoptType type)
428 {
429     const std::map<DeoptType, const char *> strMap = {
430 #define DEOPT_NAME_MAP(NAME, TYPE) {DeoptType::TYPE, #NAME},
431         GATE_META_DATA_DEOPT_REASON(DEOPT_NAME_MAP)
432 #undef DEOPT_NAME_MAP
433     };
434     if (strMap.count(type) > 0) {
435         return strMap.at(type);
436     }
437     return "DeoptType-" + std::to_string(static_cast<uint8_t>(type));
438 }
439 
440 // layout of frameWriter
441 //   |--------------------------| --------------> start(n)
442 //   |          args            |
443 //   |          this            |
444 //   |        newTarget         |
445 //   |       callTarget         |
446 //   |          vregs           |
447 //   |---------------------------
448 //   |       ASM Interpreter    |
449 //   +--------------------------+ --------------> end(n)
450 //   |        outputcounts      |          outputcounts = end(n) - start(n)
451 //   |--------------------------| --------------> start(n-1)
452 //   |          args            |
453 //   |          this            |
454 //   |        newTarget         |
455 //   |       callTarget         |
456 //   |          vregs           |
457 //   |-------------------------------------------
458 //   |       ASM Interpreter    |
459 //   +--------------------------+ --------------> end(n-1)
460 //   |        outputcounts      |           outputcounts = end(n-1) - start(n-1)
461 //   |--------------------------| --------------> start(n-1)
462 //   |       ......             |
463 //   +--------------------------+ ---------------
464 //   |        callerFp_         |               ^
465 //   |       returnAddr_        |          stackContext
466 //   |      callFrameTop_       |               |
467 //   |       inlineDepth        |               v
468 //   |--------------------------| ---------------
469 
ConstructAsmInterpretFrame()470 JSTaggedType Deoptimizier::ConstructAsmInterpretFrame()
471 {
472     FrameWriter frameWriter(this);
473     // Push asm interpreter frame
474     for (int32_t curDepth = static_cast<int32_t>(inlineDepth_); curDepth >= 0; curDepth--) {
475         auto start = frameWriter.GetTop();
476         JSTaggedValue callTarget = GetDeoptValue(curDepth, static_cast<int32_t>(SpecVregIndex::FUNC_INDEX));
477         auto method = GetMethod(callTarget);
478         if (!CollectVirtualRegisters(method, &frameWriter, curDepth)) {
479             return JSTaggedValue::Exception().GetRawData();
480         }
481         AsmInterpretedFrame *statePtr = frameWriter.ReserveAsmInterpretedFrame();
482         const uint8_t *resumePc = method->GetBytecodeArray() + pc_.at(curDepth);
483         JSTaggedValue thisObj = GetDeoptValue(curDepth, static_cast<int32_t>(SpecVregIndex::THIS_OBJECT_INDEX));
484         auto acc = GetDeoptValue(curDepth, static_cast<int32_t>(SpecVregIndex::ACC_INDEX));
485         statePtr->function = callTarget;
486         statePtr->acc = acc;
487         statePtr->env = GetDeoptValue(curDepth, static_cast<int32_t>(SpecVregIndex::ENV_INDEX));
488         statePtr->callSize = GetCallSize(curDepth, resumePc);
489         statePtr->fp = 0;  // need update
490         statePtr->thisObj = thisObj;
491         statePtr->pc = resumePc;
492         // -uintptr_t skip lr
493         if (curDepth == 0) {
494             statePtr->base.prev = reinterpret_cast<JSTaggedType *>(stackContext_.callFrameTop_ - sizeof(uintptr_t));
495         } else {
496             statePtr->base.prev = 0; // need update
497         }
498 
499         statePtr->base.type = FrameType::ASM_INTERPRETER_FRAME;
500 
501         // construct stack context
502         auto end = frameWriter.GetTop();
503         auto outputCount = start - end;
504         frameWriter.PushRawValue(outputCount);
505     }
506 
507     RelocateCalleeSave();
508 
509     frameWriter.PushRawValue(stackContext_.callerFp_);
510     frameWriter.PushRawValue(stackContext_.returnAddr_);
511     frameWriter.PushRawValue(stackContext_.callFrameTop_);
512     frameWriter.PushRawValue(inlineDepth_);
513     return reinterpret_cast<JSTaggedType>(frameWriter.GetTop());
514 }
515 
UpdateAndDumpDeoptInfo(kungfu::DeoptType type)516 void Deoptimizier::UpdateAndDumpDeoptInfo(kungfu::DeoptType type)
517 {
518     // depth records the number of layers of nested calls when deopt occurs
519     for (size_t i = 0; i <= inlineDepth_; i++) {
520         JSTaggedValue CallTarget = GetDeoptValue(i, static_cast<int32_t>(SpecVregIndex::FUNC_INDEX));
521         auto method = GetMethod(CallTarget);
522         if (i == inlineDepth_) {
523             Dump(method, type, i);
524         }
525         ASSERT(thread_ != nullptr);
526         uint8_t deoptThreshold = method->GetDeoptThreshold();
527         if (deoptThreshold > 0) {
528             method->SetDeoptType(type);
529             method->SetDeoptThreshold(--deoptThreshold);
530         } else {
531             FunctionKind kind = method->GetFunctionKind();
532             ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
533             JSHandle<ECMAObject> jsFunc(thread_, CallTarget);
534             JSHandle<JSHClass> oldHclass(thread_, jsFunc->GetClass());
535             // instead of hclass by non_optimized hclass when method ClearAOTFlags
536             JSHandle<JSHClass> newHClass = factory->GetNonOptimizedHclass(oldHclass, kind);
537             jsFunc->SynchronizedSetClass(*newHClass);
538         }
539     }
540 }
541 
542 // call instructions need compute jumpSize
GetCallSize(size_t curDepth,const uint8_t * resumePc)543 size_t Deoptimizier::GetCallSize(size_t curDepth, const uint8_t *resumePc)
544 {
545     if (inlineDepth_ > 0 && curDepth != inlineDepth_) {
546         auto op = BytecodeInstruction(resumePc).GetOpcode();
547         size_t jumpSize = BytecodeInstruction::Size(op);
548         return jumpSize;
549     }
550     return 0;
551 }
552 
EncodeDeoptVregIndex(int32_t index,size_t depth,size_t shift)553 int32_t Deoptimizier::EncodeDeoptVregIndex(int32_t index, size_t depth, size_t shift)
554 {
555     if (index >= 0) {
556         return (index << shift) | depth;
557     }
558     return -((-index << shift) | depth);
559 }
560 
ComputeShift(size_t depth)561 size_t Deoptimizier::ComputeShift(size_t depth)
562 {
563     size_t shift = 0;
564     if (depth != 0) {
565         shift = std::floor(std::log2(depth)) + 1;
566     }
567     return shift;
568 }
569 
DecodeVregIndex(OffsetType id,size_t shift)570 int32_t Deoptimizier::DecodeVregIndex(OffsetType id, size_t shift)
571 {
572     if (id >= 0) {
573         return id >> shift;
574     }
575     return -((-id) >> shift);
576 }
577 
DecodeDeoptDepth(OffsetType id,size_t shift)578 size_t Deoptimizier::DecodeDeoptDepth(OffsetType id, size_t shift)
579 {
580     size_t mask = (1 << shift) - 1;
581     if (id >= 0) {
582         return id & mask;
583     }
584     return (-id) & mask;
585 }
586 }  // namespace panda::ecmascript
587