1 /*
2  * Copyright (c) 2021-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 #ifndef ECMASCRIPT_JS_THREAD_H
17 #define ECMASCRIPT_JS_THREAD_H
18 
19 #include <atomic>
20 #include <sstream>
21 #include <string>
22 #include <cstdint>
23 
24 #include "ecmascript/platform/ffrt.h"
25 #include "ecmascript/base/aligned_struct.h"
26 #include "ecmascript/builtin_entries.h"
27 #include "ecmascript/daemon/daemon_task.h"
28 #include "ecmascript/global_index.h"
29 #include "ecmascript/js_object_resizing_strategy.h"
30 #include "ecmascript/js_tagged_value.h"
31 #include "ecmascript/js_thread_hclass_entries.h"
32 #include "ecmascript/js_thread_stub_entries.h"
33 #include "ecmascript/log_wrapper.h"
34 #include "ecmascript/mem/visitor.h"
35 #include "ecmascript/mutator_lock.h"
36 
37 #if defined(ENABLE_FFRT_INTERFACES)
38 #include "ffrt.h"
39 #include "c/executor_task.h"
40 #endif
41 
42 namespace panda::ecmascript {
43 class EcmaContext;
44 class EcmaVM;
45 class EcmaHandleScope;
46 class GlobalIndex;
47 class HeapRegionAllocator;
48 class PropertiesCache;
49 template<typename T>
50 class EcmaGlobalStorage;
51 class Node;
52 class DebugNode;
53 class VmThreadControl;
54 class GlobalEnvConstants;
55 enum class ElementsKind : uint8_t;
56 
57 // NOTE: remove
58 class MachineCode;
59 using JitCodeVector = std::vector<std::tuple<MachineCode*, std::string, uintptr_t>>;
60 using JitCodeMapVisitor = std::function<void(std::map<JSTaggedType, JitCodeVector*>&)>;
61 
62 using WeakClearCallback = void (*)(void *);
63 
64 enum class MarkStatus : uint8_t {
65     READY_TO_MARK,
66     MARKING,
67     MARK_FINISHED,
68 };
69 
70 enum class GCKind : uint8_t {
71     LOCAL_GC,
72     SHARED_GC
73 };
74 
75 enum class PGOProfilerStatus : uint8_t {
76     PGO_PROFILER_DISABLE,
77     PGO_PROFILER_ENABLE,
78 };
79 
80 enum class BCStubStatus: uint8_t {
81     NORMAL_BC_STUB,
82     PROFILE_BC_STUB,
83     JIT_PROFILE_BC_STUB,
84 };
85 
86 enum class StableArrayChangeKind { PROTO, NOT_PROTO };
87 
88 enum ThreadType : uint8_t {
89     JS_THREAD,
90     JIT_THREAD,
91     DAEMON_THREAD,
92 };
93 
94 enum ThreadFlag : uint16_t {
95     NO_FLAGS = 0 << 0,
96     SUSPEND_REQUEST = 1 << 0,
97     ACTIVE_BARRIER = 1 << 1,
98 };
99 
100 static constexpr uint32_t THREAD_STATE_OFFSET = 16;
101 static constexpr uint32_t THREAD_FLAGS_MASK = (0x1 << THREAD_STATE_OFFSET) - 1;
102 enum class ThreadState : uint16_t {
103     CREATED = 0,
104     RUNNING = 1,
105     NATIVE = 2,
106     WAIT = 3,
107     IS_SUSPENDED = 4,
108     TERMINATED = 5,
109 };
110 
111 union ThreadStateAndFlags {
ThreadStateAndFlags(uint32_t val = 0)112     explicit ThreadStateAndFlags(uint32_t val = 0): asInt(val) {}
113     struct {
114         volatile uint16_t flags;
115         volatile ThreadState state;
116     } asStruct;
117     struct {
118         uint16_t flags;
119         ThreadState state;
120     } asNonvolatileStruct;
121     volatile uint32_t asInt;
122     uint32_t asNonvolatileInt;
123     std::atomic<uint32_t> asAtomicInt;
124 private:
125     NO_COPY_SEMANTIC(ThreadStateAndFlags);
126 };
127 
128 static constexpr uint32_t MAIN_THREAD_INDEX = 0;
129 
130 class JSThread {
131 public:
132     static constexpr int CONCURRENT_MARKING_BITFIELD_NUM = 2;
133     static constexpr int CONCURRENT_MARKING_BITFIELD_MASK = 0x3;
134     static constexpr int SHARED_CONCURRENT_MARKING_BITFIELD_NUM = 1;
135     static constexpr int SHARED_CONCURRENT_MARKING_BITFIELD_MASK = 0x1;
136     static constexpr int CHECK_SAFEPOINT_BITFIELD_NUM = 8;
137     static constexpr int PGO_PROFILER_BITFIELD_START = 16;
138     static constexpr int BOOL_BITFIELD_NUM = 1;
139     static constexpr int BCSTUBSTATUS_BITFIELD_NUM = 2;
140     static constexpr uint32_t RESERVE_STACK_SIZE = 128;
141     using MarkStatusBits = BitField<MarkStatus, 0, CONCURRENT_MARKING_BITFIELD_NUM>;
142     using SharedMarkStatusBits = BitField<SharedMarkStatus, 0, SHARED_CONCURRENT_MARKING_BITFIELD_NUM>;
143     using CheckSafePointBit = BitField<bool, 0, BOOL_BITFIELD_NUM>;
144     using VMNeedSuspensionBit = BitField<bool, CHECK_SAFEPOINT_BITFIELD_NUM, BOOL_BITFIELD_NUM>;
145     using VMHasSuspendedBit = VMNeedSuspensionBit::NextFlag;
146     using InstallMachineCodeBit = VMHasSuspendedBit::NextFlag;
147     using PGOStatusBits = BitField<PGOProfilerStatus, PGO_PROFILER_BITFIELD_START, BOOL_BITFIELD_NUM>;
148     using BCStubStatusBits = PGOStatusBits::NextField<BCStubStatus, BCSTUBSTATUS_BITFIELD_NUM>;
149     using ThreadId = uint32_t;
150 
151     enum FrameDroppedState {
152         StateFalse = 0,
153         StateTrue,
154         StatePending
155     };
156 
157     explicit JSThread(EcmaVM *vm);
158     // only used in jit thread
159     explicit JSThread(EcmaVM *vm, ThreadType threadType);
160     // only used in daemon thread
161     explicit JSThread(ThreadType threadType);
162 
163     PUBLIC_API ~JSThread();
164 
GetEcmaVM() const165     EcmaVM *GetEcmaVM() const
166     {
167         return vm_;
168     }
169 
170     static JSThread *Create(EcmaVM *vm);
171     static JSThread *GetCurrent();
172 
GetNestedLevel() const173     int GetNestedLevel() const
174     {
175         return nestedLevel_;
176     }
177 
SetNestedLevel(int level)178     void SetNestedLevel(int level)
179     {
180         nestedLevel_ = level;
181     }
182 
SetLastFp(JSTaggedType *fp)183     void SetLastFp(JSTaggedType *fp)
184     {
185         glueData_.lastFp_ = fp;
186     }
187 
GetLastFp() const188     const JSTaggedType *GetLastFp() const
189     {
190         return glueData_.lastFp_;
191     }
192 
GetCurrentSPFrame() const193     const JSTaggedType *GetCurrentSPFrame() const
194     {
195         return glueData_.currentFrame_;
196     }
197 
SetCurrentSPFrame(JSTaggedType *sp)198     void SetCurrentSPFrame(JSTaggedType *sp)
199     {
200         glueData_.currentFrame_ = sp;
201     }
202 
GetLastLeaveFrame() const203     const JSTaggedType *GetLastLeaveFrame() const
204     {
205         return glueData_.leaveFrame_;
206     }
207 
SetLastLeaveFrame(JSTaggedType *sp)208     void SetLastLeaveFrame(JSTaggedType *sp)
209     {
210         glueData_.leaveFrame_ = sp;
211     }
212 
213     const JSTaggedType *GetCurrentFrame() const;
214 
215     void SetCurrentFrame(JSTaggedType *sp);
216 
217     const JSTaggedType *GetCurrentInterpretedFrame() const;
218 
219     bool DoStackOverflowCheck(const JSTaggedType *sp);
220 
221     bool DoStackLimitCheck();
222 
GetNativeAreaAllocator() const223     NativeAreaAllocator *GetNativeAreaAllocator() const
224     {
225         return nativeAreaAllocator_;
226     }
227 
GetHeapRegionAllocator() const228     HeapRegionAllocator *GetHeapRegionAllocator() const
229     {
230         return heapRegionAllocator_;
231     }
232 
ReSetNewSpaceAllocationAddress(const uintptr_t *top, const uintptr_t* end)233     void ReSetNewSpaceAllocationAddress(const uintptr_t *top, const uintptr_t* end)
234     {
235         glueData_.newSpaceAllocationTopAddress_ = top;
236         glueData_.newSpaceAllocationEndAddress_ = end;
237     }
238 
ReSetSOldSpaceAllocationAddress(const uintptr_t *top, const uintptr_t* end)239     void ReSetSOldSpaceAllocationAddress(const uintptr_t *top, const uintptr_t* end)
240     {
241         glueData_.sOldSpaceAllocationTopAddress_ = top;
242         glueData_.sOldSpaceAllocationEndAddress_ = end;
243     }
244 
ReSetSNonMovableSpaceAllocationAddress(const uintptr_t *top, const uintptr_t* end)245     void ReSetSNonMovableSpaceAllocationAddress(const uintptr_t *top, const uintptr_t* end)
246     {
247         glueData_.sNonMovableSpaceAllocationTopAddress_ = top;
248         glueData_.sNonMovableSpaceAllocationEndAddress_ = end;
249     }
250 
GetUnsharedConstpools() const251     uintptr_t GetUnsharedConstpools() const
252     {
253         return glueData_.unsharedConstpools_;
254     }
255 
SetUnsharedConstpools(uintptr_t unsharedConstpools)256     void SetUnsharedConstpools(uintptr_t unsharedConstpools)
257     {
258         glueData_.unsharedConstpools_ = unsharedConstpools;
259     }
260 
SetIsStartHeapSampling(bool isStart)261     void SetIsStartHeapSampling(bool isStart)
262     {
263         glueData_.isStartHeapSampling_ = isStart ? JSTaggedValue::True() : JSTaggedValue::False();
264     }
265 
SetIsTracing(bool isTracing)266     void SetIsTracing(bool isTracing)
267     {
268         glueData_.isTracing_ = isTracing;
269     }
270 
271     void Iterate(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
272         const RootBaseAndDerivedVisitor &derivedVisitor);
273 
274     void IterateJitCodeMap(const JitCodeMapVisitor &updater);
275 
276     void IterateHandleWithCheck(const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor);
277 
278     uintptr_t* PUBLIC_API ExpandHandleStorage();
279     void PUBLIC_API ShrinkHandleStorage(int prevIndex);
280     void PUBLIC_API CheckJSTaggedType(JSTaggedType value) const;
281     bool PUBLIC_API CpuProfilerCheckJSTaggedType(JSTaggedType value) const;
282 
283     void PUBLIC_API SetException(JSTaggedValue exception);
284 
GetException() const285     JSTaggedValue GetException() const
286     {
287         return glueData_.exception_;
288     }
289 
HasPendingException() const290     bool HasPendingException() const
291     {
292         return !glueData_.exception_.IsHole();
293     }
294 
295     void ClearException();
296 
297     void SetEnableForceIC(bool isEnableForceIC);
298 
299     bool IsEnableForceIC() const;
300 
SetGlobalObject(JSTaggedValue globalObject)301     void SetGlobalObject(JSTaggedValue globalObject)
302     {
303         glueData_.globalObject_ = globalObject;
304     }
305 
GetGlobalEnv() const306     const GlobalEnv *GetGlobalEnv() const
307     {
308         return glueData_.glueGlobalEnv_;
309     }
310 
GlobalConstants() const311     const GlobalEnvConstants *GlobalConstants() const
312     {
313         return glueData_.globalConst_;
314     }
315 
SetGlobalConstants(const GlobalEnvConstants *constants)316     void SetGlobalConstants(const GlobalEnvConstants *constants)
317     {
318         glueData_.globalConst_ = const_cast<GlobalEnvConstants*>(constants);
319     }
320 
GetBuiltinEntries() const321     const BuiltinEntries GetBuiltinEntries() const
322     {
323         return glueData_.builtinEntries_;
324     }
325 
GetBuiltinEntriesPointer()326     BuiltinEntries* GetBuiltinEntriesPointer()
327     {
328         return &glueData_.builtinEntries_;
329     }
330 
GetArrayHClassIndexMap() const331     const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &GetArrayHClassIndexMap() const
332     {
333         return arrayHClassIndexMap_;
334     }
335 
GetCtorHclassEntries() const336     const CMap<JSHClass *, GlobalIndex> &GetCtorHclassEntries() const
337     {
338         return ctorHclassEntries_;
339     }
340 
341     void NotifyStableArrayElementsGuardians(JSHandle<JSObject> receiver, StableArrayChangeKind changeKind);
342 
IsStableArrayElementsGuardiansInvalid() const343     bool IsStableArrayElementsGuardiansInvalid() const
344     {
345         return !glueData_.stableArrayElementsGuardians_;
346     }
347 
348     void ResetGuardians();
349 
350     void SetInitialBuiltinHClass(
351         BuiltinTypeId type, JSHClass *builtinHClass, JSHClass *instanceHClass,
352                             JSHClass *prototypeHClass, JSHClass *prototypeOfPrototypeHClass = nullptr,
353                             JSHClass *extraHClass = nullptr);
354 
355     void SetInitialBuiltinGlobalHClass(JSHClass *builtinHClass, GlobalIndex globalIndex);
356 
357     JSHClass *GetBuiltinHClass(BuiltinTypeId type) const;
358 
359     JSHClass *GetBuiltinInstanceHClass(BuiltinTypeId type) const;
360     JSHClass *GetBuiltinExtraHClass(BuiltinTypeId type) const;
361     JSHClass *GetArrayInstanceHClass(ElementsKind kind, bool isPrototype) const;
362 
363     PUBLIC_API JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const;
364     PUBLIC_API JSHClass *GetBuiltinPrototypeOfPrototypeHClass(BuiltinTypeId type) const;
365 
366     static size_t GetBuiltinHClassOffset(BuiltinTypeId, bool isArch32);
367 
368     static size_t GetBuiltinPrototypeHClassOffset(BuiltinTypeId, bool isArch32);
369 
GetBuiltinHClassEntries() const370     const BuiltinHClassEntries &GetBuiltinHClassEntries() const
371     {
372         return glueData_.builtinHClassEntries_;
373     }
374 
375     JSTaggedValue GetCurrentLexenv() const;
376     JSTaggedValue GetCurrentFunction() const;
377 
RegisterRTInterface(size_t id, Address addr)378     void RegisterRTInterface(size_t id, Address addr)
379     {
380         ASSERT(id < kungfu::RuntimeStubCSigns::NUM_OF_STUBS);
381         glueData_.rtStubEntries_.Set(id, addr);
382     }
383 
384     Address GetRTInterface(size_t id) const
385     {
386         ASSERT(id < kungfu::RuntimeStubCSigns::NUM_OF_STUBS);
387         return glueData_.rtStubEntries_.Get(id);
388     }
389 
390     Address GetFastStubEntry(uint32_t id) const
391     {
392         return glueData_.coStubEntries_.Get(id);
393     }
394 
395     void SetFastStubEntry(size_t id, Address entry)
396     {
397         glueData_.coStubEntries_.Set(id, entry);
398     }
399 
400     Address GetBuiltinStubEntry(uint32_t id) const
401     {
402         return glueData_.builtinStubEntries_.Get(id);
403     }
404 
405     void SetBuiltinStubEntry(size_t id, Address entry)
406     {
407         glueData_.builtinStubEntries_.Set(id, entry);
408     }
409 
410     Address GetBCStubEntry(uint32_t id) const
411     {
412         return glueData_.bcStubEntries_.Get(id);
413     }
414 
415     void SetBCStubEntry(size_t id, Address entry)
416     {
417         glueData_.bcStubEntries_.Set(id, entry);
418     }
419 
420     Address GetBaselineStubEntry(uint32_t id) const
421     {
422         return glueData_.baselineStubEntries_.Get(id);
423     }
424 
425     void SetBaselineStubEntry(size_t id, Address entry)
426     {
427         glueData_.baselineStubEntries_.Set(id, entry);
428     }
429 
430     void SetBCDebugStubEntry(size_t id, Address entry)
431     {
432         glueData_.bcDebuggerStubEntries_.Set(id, entry);
433     }
434 
435     Address *GetBytecodeHandler()
436     {
437         return glueData_.bcStubEntries_.GetAddr();
438     }
439 
440     void PUBLIC_API CheckSwitchDebuggerBCStub();
441     void CheckOrSwitchPGOStubs();
442     void SwitchJitProfileStubs(bool isEnablePgo);
443 
444     ThreadId GetThreadId() const
445     {
446         return id_.load(std::memory_order_acquire);
447     }
448 
449     void PostFork();
450 
451     static ThreadId GetCurrentThreadId();
452 
453     void IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor, GCKind gcKind = GCKind::LOCAL_GC);
454 
455     void UpdateJitCodeMapReference(const WeakRootVisitor &visitor);
456 
457     PUBLIC_API PropertiesCache *GetPropertiesCache() const;
458 
459     MarkStatus GetMarkStatus() const
460     {
461         return MarkStatusBits::Decode(glueData_.gcStateBitField_);
462     }
463 
464     void SetMarkStatus(MarkStatus status)
465     {
466         MarkStatusBits::Set(status, &glueData_.gcStateBitField_);
467     }
468 
469     bool IsConcurrentMarkingOrFinished() const
470     {
471         return !IsReadyToConcurrentMark();
472     }
473 
474     bool IsReadyToConcurrentMark() const
475     {
476         auto status = MarkStatusBits::Decode(glueData_.gcStateBitField_);
477         return status == MarkStatus::READY_TO_MARK;
478     }
479 
480     bool IsMarking() const
481     {
482         auto status = MarkStatusBits::Decode(glueData_.gcStateBitField_);
483         return status == MarkStatus::MARKING;
484     }
485 
486     bool IsMarkFinished() const
487     {
488         auto status = MarkStatusBits::Decode(glueData_.gcStateBitField_);
489         return status == MarkStatus::MARK_FINISHED;
490     }
491 
492     SharedMarkStatus GetSharedMarkStatus() const
493     {
494         return SharedMarkStatusBits::Decode(glueData_.sharedGCStateBitField_);
495     }
496 
497     void SetSharedMarkStatus(SharedMarkStatus status)
498     {
499         SharedMarkStatusBits::Set(status, &glueData_.sharedGCStateBitField_);
500     }
501 
502     bool IsSharedConcurrentMarkingOrFinished() const
503     {
504         auto status = SharedMarkStatusBits::Decode(glueData_.sharedGCStateBitField_);
505         return status == SharedMarkStatus::CONCURRENT_MARKING_OR_FINISHED;
506     }
507 
508     bool IsReadyToSharedConcurrentMark() const
509     {
510         auto status = SharedMarkStatusBits::Decode(glueData_.sharedGCStateBitField_);
511         return status == SharedMarkStatus::READY_TO_CONCURRENT_MARK;
512     }
513 
514     void SetPGOProfilerEnable(bool enable)
515     {
516         PGOProfilerStatus status =
517             enable ? PGOProfilerStatus::PGO_PROFILER_ENABLE : PGOProfilerStatus::PGO_PROFILER_DISABLE;
518         SetInterruptValue<PGOStatusBits>(status);
519     }
520 
521     bool IsPGOProfilerEnable() const
522     {
523         auto status = PGOStatusBits::Decode(glueData_.interruptVector_);
524         return status == PGOProfilerStatus::PGO_PROFILER_ENABLE;
525     }
526 
527     void SetBCStubStatus(BCStubStatus status)
528     {
529         SetInterruptValue<BCStubStatusBits>(status);
530     }
531 
532     BCStubStatus GetBCStubStatus() const
533     {
534         return BCStubStatusBits::Decode(glueData_.interruptVector_);
535     }
536 
537     bool CheckSafepoint();
538 
539     void CheckAndPassActiveBarrier();
540 
541     bool PassSuspendBarrier();
542 
543     void SetGetStackSignal(bool isParseStack)
544     {
545         getStackSignal_ = isParseStack;
546     }
547 
548     bool GetStackSignal() const
549     {
550         return getStackSignal_;
551     }
552 
553     void SetNeedProfiling(bool needProfiling)
554     {
555         needProfiling_.store(needProfiling);
556     }
557 
558     void SetIsProfiling(bool isProfiling)
559     {
560         isProfiling_ = isProfiling;
561     }
562 
563     bool GetIsProfiling() const
564     {
565         return isProfiling_;
566     }
567 
568     void SetGcState(bool gcState)
569     {
570         gcState_ = gcState;
571     }
572 
573     bool GetGcState() const
574     {
575         return gcState_;
576     }
577 
578     void SetRuntimeState(bool runtimeState)
579     {
580         runtimeState_ = runtimeState;
581     }
582 
583     bool GetRuntimeState() const
584     {
585         return runtimeState_;
586     }
587 
588     bool SetMainThread()
589     {
590         return isMainThread_ = true;
591     }
592 
593     bool IsMainThreadFast() const
594     {
595         return isMainThread_;
596     }
597 
598     void SetCpuProfileName(std::string &profileName)
599     {
600         profileName_ = profileName;
601     }
602 
603     void EnableAsmInterpreter()
604     {
605         isAsmInterpreter_ = true;
606     }
607 
608     bool IsAsmInterpreter() const
609     {
610         return isAsmInterpreter_;
611     }
612 
613     VmThreadControl *GetVmThreadControl() const
614     {
615         return vmThreadControl_;
616     }
617 
618     void SetEnableStackSourceFile(bool value)
619     {
620         enableStackSourceFile_ = value;
621     }
622 
623     bool GetEnableStackSourceFile() const
624     {
625         return enableStackSourceFile_;
626     }
627 
628     void SetEnableLazyBuiltins(bool value)
629     {
630         enableLazyBuiltins_ = value;
631     }
632 
633     bool GetEnableLazyBuiltins() const
634     {
635         return enableLazyBuiltins_;
636     }
637 
638     void SetReadyForGCIterating(bool flag)
639     {
640         readyForGCIterating_ = flag;
641     }
642 
643     bool ReadyForGCIterating() const
644     {
645         return readyForGCIterating_;
646     }
647 
648     static constexpr size_t GetGlueDataOffset()
649     {
650         return MEMBER_OFFSET(JSThread, glueData_);
651     }
652 
653     uintptr_t GetGlueAddr() const
654     {
655         return reinterpret_cast<uintptr_t>(this) + GetGlueDataOffset();
656     }
657 
658     static JSThread *GlueToJSThread(uintptr_t glue)
659     {
660         // very careful to modify here
661         return reinterpret_cast<JSThread *>(glue - GetGlueDataOffset());
662     }
663 
664     void SetCheckSafePointStatus()
665     {
666         ASSERT(static_cast<uint8_t>(glueData_.interruptVector_ & 0xFF) <= 1);
667         SetInterruptValue<CheckSafePointBit>(true);
668     }
669 
670     void ResetCheckSafePointStatus()
671     {
672         ASSERT(static_cast<uint8_t>(glueData_.interruptVector_ & 0xFF) <= 1);
673         SetInterruptValue<CheckSafePointBit>(false);
674     }
675 
676     void SetVMNeedSuspension(bool flag)
677     {
678         SetInterruptValue<VMNeedSuspensionBit>(flag);
679     }
680 
681     bool VMNeedSuspension()
682     {
683         return VMNeedSuspensionBit::Decode(glueData_.interruptVector_);
684     }
685 
686     void SetVMSuspended(bool flag)
687     {
688         SetInterruptValue<VMHasSuspendedBit>(flag);
689     }
690 
691     bool IsVMSuspended()
692     {
693         return VMHasSuspendedBit::Decode(glueData_.interruptVector_);
694     }
695 
696     bool HasTerminationRequest() const
697     {
698         return needTermination_;
699     }
700 
701     void SetTerminationRequest(bool flag)
702     {
703         needTermination_ = flag;
704     }
705 
706     void SetVMTerminated(bool flag)
707     {
708         hasTerminated_ = flag;
709     }
710 
711     bool HasTerminated() const
712     {
713         return hasTerminated_;
714     }
715 
716     void TerminateExecution();
717 
718     void SetInstallMachineCode(bool flag)
719     {
720         SetInterruptValue<InstallMachineCodeBit>(flag);
721     }
722 
723     bool HasInstallMachineCode() const
724     {
725         return InstallMachineCodeBit::Decode(glueData_.interruptVector_);
726     }
727 
728     static uintptr_t GetCurrentStackPosition()
729     {
730         return reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
731     }
732 
733     bool IsLegalAsmSp(uintptr_t sp) const;
734 
735     bool IsLegalThreadSp(uintptr_t sp) const;
736 
737     bool IsLegalSp(uintptr_t sp) const;
738 
739     void SetCheckAndCallEnterState(bool state)
740     {
741         finalizationCheckState_ = state;
742     }
743 
744     bool GetCheckAndCallEnterState() const
745     {
746         return finalizationCheckState_;
747     }
748 
749     uint64_t GetStackStart() const
750     {
751         return glueData_.stackStart_;
752     }
753 
754     uint64_t GetStackLimit() const
755     {
756         return glueData_.stackLimit_;
757     }
758 
759     GlobalEnv *GetGlueGlobalEnv()
760     {
761         return glueData_.glueGlobalEnv_;
762     }
763 
764     void SetGlueGlobalEnv(GlobalEnv *global)
765     {
766         ASSERT(global != nullptr);
767         glueData_.glueGlobalEnv_ = global;
768     }
769 
770     inline uintptr_t NewGlobalHandle(JSTaggedType value)
771     {
772         return newGlobalHandle_(value);
773     }
774 
775     inline void DisposeGlobalHandle(uintptr_t nodeAddr)
776     {
777         disposeGlobalHandle_(nodeAddr);
778     }
779 
780     inline uintptr_t SetWeak(uintptr_t nodeAddr, void *ref = nullptr, WeakClearCallback freeGlobalCallBack = nullptr,
781                              WeakClearCallback nativeFinalizeCallBack = nullptr)
782     {
783         return setWeak_(nodeAddr, ref, freeGlobalCallBack, nativeFinalizeCallBack);
784     }
785 
786     inline uintptr_t ClearWeak(uintptr_t nodeAddr)
787     {
788         return clearWeak_(nodeAddr);
789     }
790 
791     inline bool IsWeak(uintptr_t addr) const
792     {
793         return isWeak_(addr);
794     }
795 
796     void EnableCrossThreadExecution()
797     {
798         glueData_.allowCrossThreadExecution_ = true;
799     }
800 
801     bool IsCrossThreadExecutionEnable() const
802     {
803         return glueData_.allowCrossThreadExecution_;
804     }
805 
806     bool IsFrameDropped()
807     {
808         return glueData_.isFrameDropped_;
809     }
810 
811     void SetFrameDroppedState()
812     {
813         glueData_.isFrameDropped_ = true;
814     }
815 
816     void ResetFrameDroppedState()
817     {
818         glueData_.isFrameDropped_ = false;
819     }
820 
821     bool IsEntryFrameDroppedTrue()
822     {
823         return glueData_.entryFrameDroppedState_ == FrameDroppedState::StateTrue;
824     }
825 
826     bool IsEntryFrameDroppedPending()
827     {
828         return glueData_.entryFrameDroppedState_ == FrameDroppedState::StatePending;
829     }
830 
831     void SetEntryFrameDroppedState()
832     {
833         glueData_.entryFrameDroppedState_ = FrameDroppedState::StateTrue;
834     }
835 
836     void ResetEntryFrameDroppedState()
837     {
838         glueData_.entryFrameDroppedState_ = FrameDroppedState::StateFalse;
839     }
840 
841     void PendingEntryFrameDroppedState()
842     {
843         glueData_.entryFrameDroppedState_ = FrameDroppedState::StatePending;
844     }
845 
846     bool IsDebugMode()
847     {
848         return glueData_.isDebugMode_;
849     }
850 
851     void SetDebugModeState()
852     {
853         glueData_.isDebugMode_ = true;
854     }
855 
856     void ResetDebugModeState()
857     {
858         glueData_.isDebugMode_ = false;
859     }
860 
861     template<typename T, typename V>
862     void SetInterruptValue(V value)
863     {
864         volatile auto interruptValue =
865             reinterpret_cast<volatile std::atomic<uint64_t> *>(&glueData_.interruptVector_);
866         uint64_t oldValue = interruptValue->load(std::memory_order_relaxed);
867         auto newValue = oldValue;
868         do {
869             newValue = oldValue;
870             T::Set(value, &newValue);
871         } while (!std::atomic_compare_exchange_strong_explicit(interruptValue, &oldValue, newValue,
872                                                                std::memory_order_release,
873                                                                std::memory_order_relaxed));
874     }
875 
876     void InvokeWeakNodeFreeGlobalCallBack();
877     void InvokeWeakNodeNativeFinalizeCallback();
878     bool IsStartGlobalLeakCheck() const;
879     bool EnableGlobalObjectLeakCheck() const;
880     bool EnableGlobalPrimitiveLeakCheck() const;
881     void WriteToStackTraceFd(std::ostringstream &buffer) const;
882     void SetStackTraceFd(int32_t fd);
883     void CloseStackTraceFd();
884     uint32_t IncreaseGlobalNumberCount()
885     {
886         return ++globalNumberCount_;
887     }
888 
889     void SetPropertiesGrowStep(uint32_t step)
890     {
891         glueData_.propertiesGrowStep_ = step;
892     }
893 
894     uint32_t GetPropertiesGrowStep() const
895     {
896         return glueData_.propertiesGrowStep_;
897     }
898 
899     void SetRandomStatePtr(uint64_t *ptr)
900     {
901         glueData_.randomStatePtr_ = reinterpret_cast<uintptr_t>(ptr);
902     }
903 
904     void SetTaskInfo(uintptr_t taskInfo)
905     {
906         glueData_.taskInfo_ = taskInfo;
907     }
908 
909     uintptr_t GetTaskInfo() const
910     {
911         return glueData_.taskInfo_;
912     }
913 
914     void SetJitCodeMap(JSTaggedType exception,  MachineCode* machineCode, std::string &methodName, uintptr_t offset);
915 
916     std::map<JSTaggedType, JitCodeVector*> &GetJitCodeMaps()
917     {
918         return jitCodeMaps_;
919     }
920 
921     struct GlueData : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
922                                                  BCStubEntries,
923                                                  JSTaggedValue,
924                                                  JSTaggedValue,
925                                                  base::AlignedBool,
926                                                  base::AlignedPointer,
927                                                  base::AlignedPointer,
928                                                  base::AlignedPointer,
929                                                  base::AlignedPointer,
930                                                  base::AlignedPointer,
931                                                  base::AlignedPointer,
932                                                  base::AlignedPointer,
933                                                  base::AlignedPointer,
934                                                  base::AlignedPointer,
935                                                  RTStubEntries,
936                                                  COStubEntries,
937                                                  BuiltinStubEntries,
938                                                  BuiltinHClassEntries,
939                                                  BCDebuggerStubEntries,
940                                                  BaselineStubEntries,
941                                                  base::AlignedUint64,
942                                                  base::AlignedUint64,
943                                                  base::AlignedPointer,
944                                                  base::AlignedUint64,
945                                                  base::AlignedUint64,
946                                                  base::AlignedPointer,
947                                                  base::AlignedPointer,
948                                                  base::AlignedUint64,
949                                                  base::AlignedUint64,
950                                                  JSTaggedValue,
951                                                  base::AlignedBool,
952                                                  base::AlignedBool,
953                                                  base::AlignedUint32,
954                                                  JSTaggedValue,
955                                                  base::AlignedPointer,
956                                                  BuiltinEntries,
957                                                  base::AlignedBool,
958                                                  base::AlignedPointer,
959                                                  base::AlignedPointer,
960                                                  base::AlignedPointer,
961                                                  base::AlignedUint32,
962                                                  base::AlignedBool,
963                                                  base::AlignedBool> {
964         enum class Index : size_t {
965             BcStubEntriesIndex = 0,
966             ExceptionIndex,
967             GlobalObjIndex,
968             StableArrayElementsGuardiansIndex,
969             CurrentFrameIndex,
970             LeaveFrameIndex,
971             LastFpIndex,
972             NewSpaceAllocationTopAddressIndex,
973             NewSpaceAllocationEndAddressIndex,
974             SOldSpaceAllocationTopAddressIndex,
975             SOldSpaceAllocationEndAddressIndex,
976             SNonMovableSpaceAllocationTopAddressIndex,
977             SNonMovableSpaceAllocationEndAddressIndex,
978             RTStubEntriesIndex,
979             COStubEntriesIndex,
980             BuiltinsStubEntriesIndex,
981             BuiltinHClassEntriesIndex,
982             BcDebuggerStubEntriesIndex,
983             BaselineStubEntriesIndex,
984             GCStateBitFieldIndex,
985             SharedGCStateBitFieldIndex,
986             FrameBaseIndex,
987             StackStartIndex,
988             StackLimitIndex,
989             GlueGlobalEnvIndex,
990             GlobalConstIndex,
991             AllowCrossThreadExecutionIndex,
992             InterruptVectorIndex,
993             IsStartHeapSamplingIndex,
994             IsDebugModeIndex,
995             IsFrameDroppedIndex,
996             PropertiesGrowStepIndex,
997             EntryFrameDroppedStateIndex,
998             CurrentContextIndex,
999             BuiltinEntriesIndex,
1000             IsTracingIndex,
1001             UnsharedConstpoolsIndex,
1002             RandomStatePtrIndex,
1003             StateAndFlagsIndex,
1004             TaskInfoIndex,
1005             IsEnableElementsKindIndex,
1006             IsEnableForceIC,
1007             NumOfMembers
1008         };
1009         static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1010 
1011         static size_t GetExceptionOffset(bool isArch32)
1012         {
1013             return GetOffset<static_cast<size_t>(Index::ExceptionIndex)>(isArch32);
1014         }
1015 
1016         static size_t GetGlobalObjOffset(bool isArch32)
1017         {
1018             return GetOffset<static_cast<size_t>(Index::GlobalObjIndex)>(isArch32);
1019         }
1020 
1021         static size_t GetStableArrayElementsGuardiansOffset(bool isArch32)
1022         {
1023             return GetOffset<static_cast<size_t>(Index::StableArrayElementsGuardiansIndex)>(isArch32);
1024         }
1025 
1026         static size_t GetGlobalConstOffset(bool isArch32)
1027         {
1028             return GetOffset<static_cast<size_t>(Index::GlobalConstIndex)>(isArch32);
1029         }
1030 
1031         static size_t GetGCStateBitFieldOffset(bool isArch32)
1032         {
1033             return GetOffset<static_cast<size_t>(Index::GCStateBitFieldIndex)>(isArch32);
1034         }
1035 
1036         static size_t GetSharedGCStateBitFieldOffset(bool isArch32)
1037         {
1038             return GetOffset<static_cast<size_t>(Index::SharedGCStateBitFieldIndex)>(isArch32);
1039         }
1040 
1041         static size_t GetCurrentFrameOffset(bool isArch32)
1042         {
1043             return GetOffset<static_cast<size_t>(Index::CurrentFrameIndex)>(isArch32);
1044         }
1045 
1046         static size_t GetLeaveFrameOffset(bool isArch32)
1047         {
1048             return GetOffset<static_cast<size_t>(Index::LeaveFrameIndex)>(isArch32);
1049         }
1050 
1051         static size_t GetLastFpOffset(bool isArch32)
1052         {
1053             return GetOffset<static_cast<size_t>(Index::LastFpIndex)>(isArch32);
1054         }
1055 
1056         static size_t GetNewSpaceAllocationTopAddressOffset(bool isArch32)
1057         {
1058             return GetOffset<static_cast<size_t>(Index::NewSpaceAllocationTopAddressIndex)>(isArch32);
1059         }
1060 
1061         static size_t GetNewSpaceAllocationEndAddressOffset(bool isArch32)
1062         {
1063             return GetOffset<static_cast<size_t>(Index::NewSpaceAllocationEndAddressIndex)>(isArch32);
1064         }
1065 
1066         static size_t GetSOldSpaceAllocationTopAddressOffset(bool isArch32)
1067         {
1068             return GetOffset<static_cast<size_t>(Index::SOldSpaceAllocationTopAddressIndex)>(isArch32);
1069         }
1070 
1071         static size_t GetSOldSpaceAllocationEndAddressOffset(bool isArch32)
1072         {
1073             return GetOffset<static_cast<size_t>(Index::SOldSpaceAllocationEndAddressIndex)>(isArch32);
1074         }
1075 
1076         static size_t GetSNonMovableSpaceAllocationTopAddressOffset(bool isArch32)
1077         {
1078             return GetOffset<static_cast<size_t>(Index::SNonMovableSpaceAllocationTopAddressIndex)>(isArch32);
1079         }
1080 
1081         static size_t GetSNonMovableSpaceAllocationEndAddressOffset(bool isArch32)
1082         {
1083             return GetOffset<static_cast<size_t>(Index::SNonMovableSpaceAllocationEndAddressIndex)>(isArch32);
1084         }
1085 
1086         static size_t GetBCStubEntriesOffset(bool isArch32)
1087         {
1088             return GetOffset<static_cast<size_t>(Index::BcStubEntriesIndex)>(isArch32);
1089         }
1090 
1091         static size_t GetRTStubEntriesOffset(bool isArch32)
1092         {
1093             return GetOffset<static_cast<size_t>(Index::RTStubEntriesIndex)>(isArch32);
1094         }
1095 
1096         static size_t GetCOStubEntriesOffset(bool isArch32)
1097         {
1098             return GetOffset<static_cast<size_t>(Index::COStubEntriesIndex)>(isArch32);
1099         }
1100 
1101         static size_t GetBaselineStubEntriesOffset(bool isArch32)
1102         {
1103             return GetOffset<static_cast<size_t>(Index::BaselineStubEntriesIndex)>(isArch32);
1104         }
1105 
1106         static size_t GetBuiltinsStubEntriesOffset(bool isArch32)
1107         {
1108             return GetOffset<static_cast<size_t>(Index::BuiltinsStubEntriesIndex)>(isArch32);
1109         }
1110 
1111         static size_t GetBuiltinHClassEntriesOffset(bool isArch32)
1112         {
1113             return GetOffset<static_cast<size_t>(Index::BuiltinHClassEntriesIndex)>(isArch32);
1114         }
1115 
1116         static size_t GetBuiltinHClassOffset(BuiltinTypeId type, bool isArch32)
1117         {
1118             return GetBuiltinHClassEntriesOffset(isArch32) + BuiltinHClassEntries::GetBuiltinHClassOffset(type);
1119         }
1120 
1121         static size_t GetBuiltinInstanceHClassOffset(BuiltinTypeId type, bool isArch32)
1122         {
1123             return GetBuiltinHClassEntriesOffset(isArch32) + BuiltinHClassEntries::GetInstanceHClassOffset(type);
1124         }
1125 
1126         static size_t GetBuiltinPrototypeHClassOffset(BuiltinTypeId type, bool isArch32)
1127         {
1128             return GetBuiltinHClassEntriesOffset(isArch32) + BuiltinHClassEntries::GetPrototypeHClassOffset(type);
1129         }
1130 
1131         static size_t GetBuiltinPrototypeOfPrototypeHClassOffset(BuiltinTypeId type, bool isArch32)
1132         {
1133             return GetBuiltinHClassEntriesOffset(isArch32) +
1134                    BuiltinHClassEntries::GetPrototypeOfPrototypeHClassOffset(type);
1135         }
1136 
1137         static size_t GetBuiltinExtraHClassOffset(BuiltinTypeId type, bool isArch32)
1138         {
1139             return GetBuiltinHClassEntriesOffset(isArch32) + BuiltinHClassEntries::GetExtraHClassOffset(type);
1140         }
1141 
1142         static size_t GetBCDebuggerStubEntriesOffset(bool isArch32)
1143         {
1144             return GetOffset<static_cast<size_t>(Index::BcDebuggerStubEntriesIndex)>(isArch32);
1145         }
1146 
1147         static size_t GetFrameBaseOffset(bool isArch32)
1148         {
1149             return GetOffset<static_cast<size_t>(Index::FrameBaseIndex)>(isArch32);
1150         }
1151 
1152         static size_t GetStackLimitOffset(bool isArch32)
1153         {
1154             return GetOffset<static_cast<size_t>(Index::StackLimitIndex)>(isArch32);
1155         }
1156 
1157         static size_t GetGlueGlobalEnvOffset(bool isArch32)
1158         {
1159             return GetOffset<static_cast<size_t>(Index::GlueGlobalEnvIndex)>(isArch32);
1160         }
1161 
1162         static size_t GetAllowCrossThreadExecutionOffset(bool isArch32)
1163         {
1164             return GetOffset<static_cast<size_t>(Index::AllowCrossThreadExecutionIndex)>(isArch32);
1165         }
1166 
1167         static size_t GetInterruptVectorOffset(bool isArch32)
1168         {
1169             return GetOffset<static_cast<size_t>(Index::InterruptVectorIndex)>(isArch32);
1170         }
1171 
1172         static size_t GetIsStartHeapSamplingOffset(bool isArch32)
1173         {
1174             return GetOffset<static_cast<size_t>(Index::IsStartHeapSamplingIndex)>(isArch32);
1175         }
1176 
1177         static size_t GetIsDebugModeOffset(bool isArch32)
1178         {
1179             return GetOffset<static_cast<size_t>(Index::IsDebugModeIndex)>(isArch32);
1180         }
1181 
1182         static size_t GetIsFrameDroppedOffset(bool isArch32)
1183         {
1184             return GetOffset<static_cast<size_t>(Index::IsFrameDroppedIndex)>(isArch32);
1185         }
1186 
1187         static size_t GetPropertiesGrowStepOffset(bool isArch32)
1188         {
1189             return GetOffset<static_cast<size_t>(Index::PropertiesGrowStepIndex)>(isArch32);
1190         }
1191 
1192         static size_t GetEntryFrameDroppedStateOffset(bool isArch32)
1193         {
1194             return GetOffset<static_cast<size_t>(Index::EntryFrameDroppedStateIndex)>(isArch32);
1195         }
1196 
1197         static size_t GetCurrentContextOffset(bool isArch32)
1198         {
1199             return GetOffset<static_cast<size_t>(Index::CurrentContextIndex)>(isArch32);
1200         }
1201 
1202         static size_t GetBuiltinEntriesOffset(bool isArch32)
1203         {
1204             return GetOffset<static_cast<size_t>(Index::BuiltinEntriesIndex)>(isArch32);
1205         }
1206 
1207         static size_t GetIsTracingOffset(bool isArch32)
1208         {
1209             return GetOffset<static_cast<size_t>(Index::IsTracingIndex)>(isArch32);
1210         }
1211 
1212         static size_t GetUnSharedConstpoolsOffset(bool isArch32)
1213         {
1214             return GetOffset<static_cast<size_t>(Index::UnsharedConstpoolsIndex)>(isArch32);
1215         }
1216 
1217         static size_t GetStateAndFlagsOffset(bool isArch32)
1218         {
1219             return GetOffset<static_cast<size_t>(Index::StateAndFlagsIndex)>(isArch32);
1220         }
1221 
1222         static size_t GetRandomStatePtrOffset(bool isArch32)
1223         {
1224             return GetOffset<static_cast<size_t>(Index::RandomStatePtrIndex)>(isArch32);
1225         }
1226 
1227         static size_t GetTaskInfoOffset(bool isArch32)
1228         {
1229             return GetOffset<static_cast<size_t>(Index::TaskInfoIndex)>(isArch32);
1230         }
1231 
1232         static size_t GetIsEnableElementsKindOffset(bool isArch32)
1233         {
1234             return GetOffset<static_cast<size_t>(Index::IsEnableElementsKindIndex)>(isArch32);
1235         }
1236 
1237         static size_t GetIsEnableForceICOffSet(bool isArch32)
1238         {
1239             return GetOffset<static_cast<size_t>(Index::IsEnableForceIC)>(isArch32);
1240         }
1241 
1242         alignas(EAS) BCStubEntries bcStubEntries_ {};
1243         alignas(EAS) JSTaggedValue exception_ {JSTaggedValue::Hole()};
1244         alignas(EAS) JSTaggedValue globalObject_ {JSTaggedValue::Hole()};
1245         alignas(EAS) bool stableArrayElementsGuardians_ {true};
1246         alignas(EAS) JSTaggedType *currentFrame_ {nullptr};
1247         alignas(EAS) JSTaggedType *leaveFrame_ {nullptr};
1248         alignas(EAS) JSTaggedType *lastFp_ {nullptr};
1249         alignas(EAS) const uintptr_t *newSpaceAllocationTopAddress_ {nullptr};
1250         alignas(EAS) const uintptr_t *newSpaceAllocationEndAddress_ {nullptr};
1251         alignas(EAS) const uintptr_t *sOldSpaceAllocationTopAddress_ {nullptr};
1252         alignas(EAS) const uintptr_t *sOldSpaceAllocationEndAddress_ {nullptr};
1253         alignas(EAS) const uintptr_t *sNonMovableSpaceAllocationTopAddress_ {nullptr};
1254         alignas(EAS) const uintptr_t *sNonMovableSpaceAllocationEndAddress_ {nullptr};
1255         alignas(EAS) RTStubEntries rtStubEntries_ {};
1256         alignas(EAS) COStubEntries coStubEntries_ {};
1257         alignas(EAS) BuiltinStubEntries builtinStubEntries_ {};
1258         alignas(EAS) BuiltinHClassEntries builtinHClassEntries_ {};
1259         alignas(EAS) BCDebuggerStubEntries bcDebuggerStubEntries_ {};
1260         alignas(EAS) BaselineStubEntries baselineStubEntries_ {};
1261         alignas(EAS) volatile uint64_t gcStateBitField_ {0ULL};
1262         alignas(EAS) volatile uint64_t sharedGCStateBitField_ {0ULL};
1263         alignas(EAS) JSTaggedType *frameBase_ {nullptr};
1264         alignas(EAS) uint64_t stackStart_ {0};
1265         alignas(EAS) uint64_t stackLimit_ {0};
1266         alignas(EAS) GlobalEnv *glueGlobalEnv_ {nullptr};
1267         alignas(EAS) GlobalEnvConstants *globalConst_ {nullptr};
1268         alignas(EAS) bool allowCrossThreadExecution_ {false};
1269         alignas(EAS) volatile uint64_t interruptVector_ {0};
1270         alignas(EAS) JSTaggedValue isStartHeapSampling_ {JSTaggedValue::False()};
1271         alignas(EAS) bool isDebugMode_ {false};
1272         alignas(EAS) bool isFrameDropped_ {false};
1273         alignas(EAS) uint32_t propertiesGrowStep_ {JSObjectResizingStrategy::PROPERTIES_GROW_SIZE};
1274         alignas(EAS) uint64_t entryFrameDroppedState_ {FrameDroppedState::StateFalse};
1275         alignas(EAS) EcmaContext *currentContext_ {nullptr};
1276         alignas(EAS) BuiltinEntries builtinEntries_ {};
1277         alignas(EAS) bool isTracing_ {false};
1278         alignas(EAS) uintptr_t unsharedConstpools_ {0};
1279         alignas(EAS) uintptr_t randomStatePtr_ {0};
1280         alignas(EAS) ThreadStateAndFlags stateAndFlags_ {};
1281         alignas(EAS) uintptr_t taskInfo_ {0};
1282         alignas(EAS) bool isEnableElementsKind_ {false};
1283         alignas(EAS) bool isEnableForceIC_ {true};
1284     };
1285     STATIC_ASSERT_EQ_ARCH(sizeof(GlueData), GlueData::SizeArch32, GlueData::SizeArch64);
1286 
1287     void PushContext(EcmaContext *context);
1288     void PopContext();
1289 
1290     EcmaContext *GetCurrentEcmaContext() const
1291     {
1292         return glueData_.currentContext_;
1293     }
1294 
1295     JSTaggedValue GetSingleCharTable() const
1296     {
1297         ASSERT(glueData_.globalConst_->GetSingleCharTable() != JSTaggedValue::Hole());
1298         return glueData_.globalConst_->GetSingleCharTable();
1299     }
1300 
1301     void SwitchCurrentContext(EcmaContext *currentContext, bool isInIterate = false);
1302 
1303     CVector<EcmaContext *> GetEcmaContexts()
1304     {
1305         return contexts_;
1306     }
1307 
1308     bool IsPropertyCacheCleared() const;
1309 
1310     bool EraseContext(EcmaContext *context);
1311     void ClearContextCachedConstantPool();
1312 
1313     const GlobalEnvConstants *GetFirstGlobalConst() const;
1314     bool IsAllContextsInitialized() const;
1315     bool IsReadyToUpdateDetector() const;
1316     Area *GetOrCreateRegExpCache();
1317 
1318     void InitializeBuiltinObject(const std::string& key);
1319     void InitializeBuiltinObject();
1320 
1321     void SetFullMarkRequest()
1322     {
1323         fullMarkRequest_ = true;
1324     }
1325 
1326     inline bool IsThreadSafe() const
1327     {
1328         return IsMainThread() || HasSuspendRequest();
1329     }
1330 
1331     bool IsSuspended() const
1332     {
1333         bool f = ReadFlag(ThreadFlag::SUSPEND_REQUEST);
1334         bool s = (GetState() != ThreadState::RUNNING);
1335         return f && s;
1336     }
1337 
1338     inline bool HasSuspendRequest() const
1339     {
1340         return ReadFlag(ThreadFlag::SUSPEND_REQUEST);
1341     }
1342 
1343     void CheckSafepointIfSuspended()
1344     {
1345         if (HasSuspendRequest()) {
1346             WaitSuspension();
1347         }
1348     }
1349 
1350     bool IsInSuspendedState() const
1351     {
1352         return GetState() == ThreadState::IS_SUSPENDED;
1353     }
1354 
1355     bool IsInRunningState() const
1356     {
1357         return GetState() == ThreadState::RUNNING;
1358     }
1359 
1360     bool IsInRunningStateOrProfiling() const;
1361 
1362     ThreadState GetState() const
1363     {
1364         uint32_t stateAndFlags = glueData_.stateAndFlags_.asAtomicInt.load(std::memory_order_acquire);
1365         return static_cast<enum ThreadState>(stateAndFlags >> THREAD_STATE_OFFSET);
1366     }
1367     void PUBLIC_API UpdateState(ThreadState newState);
1368     void SuspendThread(bool internalSuspend, SuspendBarrier* barrier = nullptr);
1369     void ResumeThread(bool internalSuspend);
1370     void WaitSuspension();
1371     static bool IsMainThread();
1372     PUBLIC_API void ManagedCodeBegin();
1373     PUBLIC_API void ManagedCodeEnd();
1374 #ifndef NDEBUG
1375     bool IsInManagedState() const;
1376     MutatorLock::MutatorLockState GetMutatorLockState() const;
1377     void SetMutatorLockState(MutatorLock::MutatorLockState newState);
1378 #endif
SetWeakFinalizeTaskCallback(const WeakFinalizeTaskCallback &callback)1379     void SetWeakFinalizeTaskCallback(const WeakFinalizeTaskCallback &callback)
1380     {
1381         finalizeTaskCallback_ = callback;
1382     }
1383 
GetJobId()1384     uint64_t GetJobId()
1385     {
1386         if (jobId_ == UINT64_MAX) {
1387             jobId_ = 0;
1388         }
1389         return ++jobId_;
1390     }
1391 
SetAsyncCleanTaskCallback(const NativePointerTaskCallback &callback)1392     void SetAsyncCleanTaskCallback(const NativePointerTaskCallback &callback)
1393     {
1394         asyncCleanTaskCb_ = callback;
1395     }
1396 
GetAsyncCleanTaskCallback() const1397     NativePointerTaskCallback GetAsyncCleanTaskCallback() const
1398     {
1399         return asyncCleanTaskCb_;
1400     }
1401 
1402     static void RegisterThread(JSThread *jsThread);
1403 
1404     static void UnregisterThread(JSThread *jsThread);
1405 
IsJSThread() const1406     bool IsJSThread() const
1407     {
1408         return threadType_ == ThreadType::JS_THREAD;
1409     }
1410 
IsJitThread() const1411     bool IsJitThread() const
1412     {
1413         return threadType_ == ThreadType::JIT_THREAD;
1414     }
1415 
IsDaemonThread() const1416     bool IsDaemonThread() const
1417     {
1418         return threadType_ == ThreadType::DAEMON_THREAD;
1419     }
1420 
1421     // Daemon_Thread and JS_Thread have some difference in transition, for example, when transition to running,
1422     // JS_Thread may take some local_gc actions, but Daemon_Thread do not need.
1423     void TransferDaemonThreadToRunning();
1424 
GetJitLock()1425     RecursiveMutex *GetJitLock()
1426     {
1427         return &jitMutex_;
1428     }
1429 
GetProfileTypeAccessorLock()1430     RecursiveMutex &GetProfileTypeAccessorLock()
1431     {
1432         return profileTypeAccessorLockMutex_;
1433     }
1434 
SetMachineCodeLowMemory(bool isLow)1435     void SetMachineCodeLowMemory(bool isLow)
1436     {
1437         machineCodeLowMemory_ = isLow;
1438     }
1439 
IsMachineCodeLowMemory()1440     bool IsMachineCodeLowMemory()
1441     {
1442         return machineCodeLowMemory_;
1443     }
1444 
GetEnv() const1445     void *GetEnv() const
1446     {
1447         return env_;
1448     }
1449 
SetEnv(void *env)1450     void SetEnv(void *env)
1451     {
1452         env_ = env;
1453     }
1454 
SetIsInConcurrentScope(bool flag)1455     void SetIsInConcurrentScope(bool flag)
1456     {
1457         isInConcurrentScope_ = flag;
1458     }
1459 
IsInConcurrentScope()1460     bool IsInConcurrentScope()
1461     {
1462         return isInConcurrentScope_;
1463     }
1464 
EnableEdenGCBarriers()1465     void EnableEdenGCBarriers()
1466     {
1467         auto setValueStub = GetFastStubEntry(kungfu::CommonStubCSigns::SetValueWithEdenBarrier);
1468         SetFastStubEntry(kungfu::CommonStubCSigns::SetValueWithBarrier, setValueStub);
1469         auto markStub = GetRTInterface(kungfu::RuntimeStubCSigns::ID_MarkingBarrierWithEden);
1470         RegisterRTInterface(kungfu::RuntimeStubCSigns::ID_MarkingBarrier, markStub);
1471         auto setNotShareValueStub = GetFastStubEntry(kungfu::CommonStubCSigns::SetNonSValueWithEdenBarrier);
1472         SetFastStubEntry(kungfu::CommonStubCSigns::SetNonSValueWithBarrier, setNotShareValueStub);
1473         auto asmCheckStub = GetRTInterface(kungfu::RuntimeStubCSigns::ID_ASMWriteBarrierWithEden);
1474         RegisterRTInterface(kungfu::RuntimeStubCSigns::ID_ASMFastWriteBarrier, asmCheckStub);
1475     }
1476 
1477 
1478 
1479 #ifndef NDEBUG
LaunchSuspendAll()1480     inline void LaunchSuspendAll()
1481     {
1482         launchedSuspendAll_ = true;
1483     }
1484 
HasLaunchedSuspendAll() const1485     inline bool HasLaunchedSuspendAll() const
1486     {
1487         return launchedSuspendAll_;
1488     }
1489 
CompleteSuspendAll()1490     inline void CompleteSuspendAll()
1491     {
1492         launchedSuspendAll_ = false;
1493     }
1494 #endif
1495 
1496 protected:
SetThreadId()1497     void SetThreadId()
1498     {
1499         id_.store(JSThread::GetCurrentThreadId(), std::memory_order_release);
1500     }
1501 
1502     // When call EcmaVM::PreFork(), the std::thread for Daemon_Thread is finished, but the Daemon_Thread instance
1503     // is still alive, and need to reset ThreadId to 0.
ResetThreadId()1504     void ResetThreadId()
1505     {
1506         id_.store(0, std::memory_order_release);
1507     }
1508 private:
1509     NO_COPY_SEMANTIC(JSThread);
1510     NO_MOVE_SEMANTIC(JSThread);
SetGlobalConst(GlobalEnvConstants *globalConst)1511     void SetGlobalConst(GlobalEnvConstants *globalConst)
1512     {
1513         glueData_.globalConst_ = globalConst;
1514     }
SetCurrentEcmaContext(EcmaContext *context)1515     void SetCurrentEcmaContext(EcmaContext *context)
1516     {
1517         glueData_.currentContext_ = context;
1518     }
1519 
SetArrayHClassIndexMap(const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &map)1520     void SetArrayHClassIndexMap(const CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &map)
1521     {
1522         arrayHClassIndexMap_ = map;
1523     }
1524 
1525     void TransferFromRunningToSuspended(ThreadState newState);
1526 
1527     void TransferToRunning();
1528 
1529     inline void StoreState(ThreadState newState);
1530 
1531     void StoreRunningState(ThreadState newState);
1532 
1533     void StoreSuspendedState(ThreadState newState);
1534 
ReadFlag(ThreadFlag flag) const1535     bool ReadFlag(ThreadFlag flag) const
1536     {
1537         uint32_t stateAndFlags = glueData_.stateAndFlags_.asAtomicInt.load(std::memory_order_acquire);
1538         uint16_t flags = (stateAndFlags & THREAD_FLAGS_MASK);
1539         return (flags & static_cast<uint16_t>(flag)) != 0;
1540     }
1541 
SetFlag(ThreadFlag flag)1542     void SetFlag(ThreadFlag flag)
1543     {
1544         glueData_.stateAndFlags_.asAtomicInt.fetch_or(flag, std::memory_order_seq_cst);
1545     }
1546 
ClearFlag(ThreadFlag flag)1547     void ClearFlag(ThreadFlag flag)
1548     {
1549         glueData_.stateAndFlags_.asAtomicInt.fetch_and(UINT32_MAX ^ flag, std::memory_order_seq_cst);
1550     }
1551 
1552     void DumpStack() DUMP_API_ATTR;
1553 
1554     static size_t GetAsmStackLimit();
1555 
1556     static constexpr size_t DEFAULT_MAX_SYSTEM_STACK_SIZE = 8_MB;
1557 
1558     GlueData glueData_;
1559     std::atomic<ThreadId> id_ {0};
1560     EcmaVM *vm_ {nullptr};
1561     void *env_ {nullptr};
1562     Area *regExpCache_ {nullptr};
1563 
1564     // MM: handles, global-handles, and aot-stubs.
1565     int nestedLevel_ = 0;
1566     NativeAreaAllocator *nativeAreaAllocator_ {nullptr};
1567     HeapRegionAllocator *heapRegionAllocator_ {nullptr};
1568     bool runningNativeFinalizeCallbacks_ {false};
1569     std::vector<std::pair<WeakClearCallback, void *>> weakNodeFreeGlobalCallbacks_ {};
1570     std::vector<std::pair<WeakClearCallback, void *>> weakNodeNativeFinalizeCallbacks_ {};
1571 
1572     EcmaGlobalStorage<Node> *globalStorage_ {nullptr};
1573     EcmaGlobalStorage<DebugNode> *globalDebugStorage_ {nullptr};
1574     int32_t stackTraceFd_ {-1};
1575 
1576     std::function<uintptr_t(JSTaggedType value)> newGlobalHandle_;
1577     std::function<void(uintptr_t nodeAddr)> disposeGlobalHandle_;
1578     std::function<uintptr_t(uintptr_t nodeAddr, void *ref, WeakClearCallback freeGlobalCallBack_,
1579          WeakClearCallback nativeFinalizeCallBack)> setWeak_;
1580     std::function<uintptr_t(uintptr_t nodeAddr)> clearWeak_;
1581     std::function<bool(uintptr_t addr)> isWeak_;
1582     NativePointerTaskCallback asyncCleanTaskCb_ {nullptr};
1583     WeakFinalizeTaskCallback finalizeTaskCallback_ {nullptr};
1584     uint32_t globalNumberCount_ {0};
1585 
1586     // Run-time state
1587     bool getStackSignal_ {false};
1588     bool runtimeState_ {false};
1589     bool isAsmInterpreter_ {false};
1590     VmThreadControl *vmThreadControl_ {nullptr};
1591     bool enableStackSourceFile_ {true};
1592     bool enableLazyBuiltins_ {false};
1593     bool readyForGCIterating_ {false};
1594     // CpuProfiler
1595     bool isProfiling_ {false};
1596     bool gcState_ {false};
1597     std::atomic_bool needProfiling_ {false};
1598     std::string profileName_ {""};
1599 
1600     bool finalizationCheckState_ {false};
1601     // Shared heap
1602     bool isMainThread_ {false};
1603     bool fullMarkRequest_ {false};
1604 
1605     // { ElementsKind, (hclass, hclassWithProto) }
1606     CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> arrayHClassIndexMap_;
1607     CMap<JSHClass *, GlobalIndex> ctorHclassEntries_;
1608 
1609     CVector<EcmaContext *> contexts_;
1610     EcmaContext *currentContext_ {nullptr};
1611 
1612     Mutex suspendLock_;
1613     int32_t suspendCount_ {0};
1614     ConditionVariable suspendCondVar_;
1615     SuspendBarrier *suspendBarrier_ {nullptr};
1616 
1617     uint64_t jobId_ {0};
1618 
1619     ThreadType threadType_ {ThreadType::JS_THREAD};
1620     RecursiveMutex jitMutex_;
1621     bool machineCodeLowMemory_ {false};
1622     RecursiveMutex profileTypeAccessorLockMutex_;
1623 
1624 #ifndef NDEBUG
1625     MutatorLock::MutatorLockState mutatorLockState_ = MutatorLock::MutatorLockState::UNLOCKED;
1626     std::atomic<bool> launchedSuspendAll_ {false};
1627 #endif
1628     // Collect a map from JsError to MachineCode objects, JsError objects with stack frame generated by jit in the map.
1629     // It will be used to keep MachineCode objects alive (for dump) before JsError object be free.
1630     std::map<JSTaggedType, JitCodeVector*> jitCodeMaps_;
1631 
1632     std::atomic<bool> needTermination_ {false};
1633     std::atomic<bool> hasTerminated_ {false};
1634 
1635     bool isInConcurrentScope_ {false};
1636 
1637     friend class GlobalHandleCollection;
1638     friend class EcmaVM;
1639     friend class EcmaContext;
1640     friend class JitVM;
1641 };
1642 }  // namespace panda::ecmascript
1643 #endif  // ECMASCRIPT_JS_THREAD_H
1644