1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef vm_Activation_inl_h
8 #define vm_Activation_inl_h
9
10 #include "vm/Activation.h"
11
12 #include "mozilla/Assertions.h" // MOZ_ASSERT{,_IF}, MOZ_CRASH
13 #include "mozilla/Likely.h" // MOZ_UNLIKELY
14 #include "mozilla/Maybe.h" // mozilla::Maybe
15
16 #include "jit/CalleeToken.h" // js::jit::CalleeToken
17 #include "vm/FrameIter.h" // js::FrameIter
18 #include "vm/JitActivation.h" // js::jit::JitActivation
19 #include "vm/JSContext.h" // JSContext
20 #include "vm/Stack.h" // js::AbstractFramePtr
21
22 namespace js {
23
ActivationEntryMonitor(JSContext * cx)24 inline ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx)
25 : cx_(cx), entryMonitor_(cx->entryMonitor) {
26 cx->entryMonitor = nullptr;
27 }
28
ActivationEntryMonitor(JSContext * cx,InterpreterFrame * entryFrame)29 inline ActivationEntryMonitor::ActivationEntryMonitor(
30 JSContext* cx, InterpreterFrame* entryFrame)
31 : ActivationEntryMonitor(cx) {
32 if (MOZ_UNLIKELY(entryMonitor_)) {
33 init(cx, entryFrame);
34 }
35 }
36
ActivationEntryMonitor(JSContext * cx,jit::CalleeToken entryToken)37 inline ActivationEntryMonitor::ActivationEntryMonitor(
38 JSContext* cx, jit::CalleeToken entryToken)
39 : ActivationEntryMonitor(cx) {
40 if (MOZ_UNLIKELY(entryMonitor_)) {
41 init(cx, entryToken);
42 }
43 }
44
~ActivationEntryMonitor()45 inline ActivationEntryMonitor::~ActivationEntryMonitor() {
46 if (entryMonitor_) {
47 entryMonitor_->Exit(cx_);
48 }
49
50 cx_->entryMonitor = entryMonitor_;
51 }
52
Activation(JSContext * cx,Kind kind)53 inline Activation::Activation(JSContext* cx, Kind kind)
54 : cx_(cx),
55 compartment_(cx->compartment()),
56 prev_(cx->activation_),
57 prevProfiling_(prev_ ? prev_->mostRecentProfiling() : nullptr),
58 hideScriptedCallerCount_(0),
59 frameCache_(cx),
60 asyncStack_(cx, cx->asyncStackForNewActivations()),
61 asyncCause_(cx->asyncCauseForNewActivations),
62 asyncCallIsExplicit_(cx->asyncCallIsExplicit),
63 kind_(kind) {
64 cx->asyncStackForNewActivations() = nullptr;
65 cx->asyncCauseForNewActivations = nullptr;
66 cx->asyncCallIsExplicit = false;
67 cx->activation_ = this;
68 }
69
~Activation()70 inline Activation::~Activation() {
71 MOZ_ASSERT_IF(isProfiling(), this != cx_->profilingActivation_);
72 MOZ_ASSERT(cx_->activation_ == this);
73 MOZ_ASSERT(hideScriptedCallerCount_ == 0);
74 cx_->activation_ = prev_;
75 cx_->asyncCauseForNewActivations = asyncCause_;
76 cx_->asyncStackForNewActivations() = asyncStack_;
77 cx_->asyncCallIsExplicit = asyncCallIsExplicit_;
78 }
79
isProfiling()80 inline bool Activation::isProfiling() const {
81 if (isInterpreter()) {
82 return asInterpreter()->isProfiling();
83 }
84
85 MOZ_ASSERT(isJit());
86 return asJit()->isProfiling();
87 }
88
mostRecentProfiling()89 inline Activation* Activation::mostRecentProfiling() {
90 if (isProfiling()) {
91 return this;
92 }
93 return prevProfiling_;
94 }
95
getLiveSavedFrameCache(JSContext * cx)96 inline LiveSavedFrameCache* Activation::getLiveSavedFrameCache(JSContext* cx) {
97 if (!frameCache_.get().initialized() && !frameCache_.get().init(cx)) {
98 return nullptr;
99 }
100 return frameCache_.address();
101 }
102
103 /* static */ inline mozilla::Maybe<LiveSavedFrameCache::FramePtr>
create(const FrameIter & iter)104 LiveSavedFrameCache::FramePtr::create(const FrameIter& iter) {
105 if (iter.done()) {
106 return mozilla::Nothing();
107 }
108
109 if (iter.isPhysicalJitFrame()) {
110 return mozilla::Some(FramePtr(iter.physicalJitFrame()));
111 }
112
113 if (!iter.hasUsableAbstractFramePtr()) {
114 return mozilla::Nothing();
115 }
116
117 auto afp = iter.abstractFramePtr();
118
119 if (afp.isInterpreterFrame()) {
120 return mozilla::Some(FramePtr(afp.asInterpreterFrame()));
121 }
122 if (afp.isWasmDebugFrame()) {
123 return mozilla::Some(FramePtr(afp.asWasmDebugFrame()));
124 }
125 if (afp.isRematerializedFrame()) {
126 return mozilla::Some(FramePtr(afp.asRematerializedFrame()));
127 }
128
129 MOZ_CRASH("unexpected frame type");
130 }
131
132 struct LiveSavedFrameCache::FramePtr::HasCachedMatcher {
133 template <typename Frame>
operatorHasCachedMatcher134 bool operator()(Frame* f) const {
135 return f->hasCachedSavedFrame();
136 }
137 };
138
hasCachedSavedFrame()139 inline bool LiveSavedFrameCache::FramePtr::hasCachedSavedFrame() const {
140 return ptr.match(HasCachedMatcher());
141 }
142
143 struct LiveSavedFrameCache::FramePtr::SetHasCachedMatcher {
144 template <typename Frame>
operatorSetHasCachedMatcher145 void operator()(Frame* f) {
146 f->setHasCachedSavedFrame();
147 }
148 };
149
setHasCachedSavedFrame()150 inline void LiveSavedFrameCache::FramePtr::setHasCachedSavedFrame() {
151 ptr.match(SetHasCachedMatcher());
152 }
153
154 struct LiveSavedFrameCache::FramePtr::ClearHasCachedMatcher {
155 template <typename Frame>
operatorClearHasCachedMatcher156 void operator()(Frame* f) {
157 f->clearHasCachedSavedFrame();
158 }
159 };
160
clearHasCachedSavedFrame()161 inline void LiveSavedFrameCache::FramePtr::clearHasCachedSavedFrame() {
162 ptr.match(ClearHasCachedMatcher());
163 }
164
hasWasmExitFP()165 inline bool Activation::hasWasmExitFP() const {
166 return isJit() && asJit()->hasWasmExitFP();
167 }
168
169 } // namespace js
170
171 #endif // vm_Activation_inl_h
172