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/BaselineFrame.h" // js::jit::BaselineFrame
17 #include "jit/JSJitFrameIter.h" // js::jit::CalleeToken
18 #include "vm/FrameIter.h" // js::FrameIter
19 #include "vm/JitActivation.h" // js::jit::JitActivation
20 #include "vm/JSContext.h" // JSContext
21 #include "vm/Stack.h" // js::AbstractFramePtr
22
23 namespace js {
24
ActivationEntryMonitor(JSContext * cx)25 inline ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx)
26 : cx_(cx), entryMonitor_(cx->entryMonitor) {
27 cx->entryMonitor = nullptr;
28 }
29
ActivationEntryMonitor(JSContext * cx,InterpreterFrame * entryFrame)30 inline ActivationEntryMonitor::ActivationEntryMonitor(
31 JSContext* cx, InterpreterFrame* entryFrame)
32 : ActivationEntryMonitor(cx) {
33 if (MOZ_UNLIKELY(entryMonitor_)) {
34 init(cx, entryFrame);
35 }
36 }
37
ActivationEntryMonitor(JSContext * cx,jit::CalleeToken entryToken)38 inline ActivationEntryMonitor::ActivationEntryMonitor(
39 JSContext* cx, jit::CalleeToken entryToken)
40 : ActivationEntryMonitor(cx) {
41 if (MOZ_UNLIKELY(entryMonitor_)) {
42 init(cx, entryToken);
43 }
44 }
45
~ActivationEntryMonitor()46 inline ActivationEntryMonitor::~ActivationEntryMonitor() {
47 if (entryMonitor_) {
48 entryMonitor_->Exit(cx_);
49 }
50
51 cx_->entryMonitor = entryMonitor_;
52 }
53
Activation(JSContext * cx,Kind kind)54 inline Activation::Activation(JSContext* cx, Kind kind)
55 : cx_(cx),
56 compartment_(cx->compartment()),
57 prev_(cx->activation_),
58 prevProfiling_(prev_ ? prev_->mostRecentProfiling() : nullptr),
59 hideScriptedCallerCount_(0),
60 frameCache_(cx),
61 asyncStack_(cx, cx->asyncStackForNewActivations()),
62 asyncCause_(cx->asyncCauseForNewActivations),
63 asyncCallIsExplicit_(cx->asyncCallIsExplicit),
64 kind_(kind) {
65 cx->asyncStackForNewActivations() = nullptr;
66 cx->asyncCauseForNewActivations = nullptr;
67 cx->asyncCallIsExplicit = false;
68 cx->activation_ = this;
69 }
70
~Activation()71 inline Activation::~Activation() {
72 MOZ_ASSERT_IF(isProfiling(), this != cx_->profilingActivation_);
73 MOZ_ASSERT(cx_->activation_ == this);
74 MOZ_ASSERT(hideScriptedCallerCount_ == 0);
75 cx_->activation_ = prev_;
76 cx_->asyncCauseForNewActivations = asyncCause_;
77 cx_->asyncStackForNewActivations() = asyncStack_;
78 cx_->asyncCallIsExplicit = asyncCallIsExplicit_;
79 }
80
isProfiling()81 inline bool Activation::isProfiling() const {
82 if (isInterpreter()) {
83 return asInterpreter()->isProfiling();
84 }
85
86 MOZ_ASSERT(isJit());
87 return asJit()->isProfiling();
88 }
89
mostRecentProfiling()90 inline Activation* Activation::mostRecentProfiling() {
91 if (isProfiling()) {
92 return this;
93 }
94 return prevProfiling_;
95 }
96
getLiveSavedFrameCache(JSContext * cx)97 inline LiveSavedFrameCache* Activation::getLiveSavedFrameCache(JSContext* cx) {
98 if (!frameCache_.get().initialized() && !frameCache_.get().init(cx)) {
99 return nullptr;
100 }
101 return frameCache_.address();
102 }
103
104 /* static */ inline mozilla::Maybe<LiveSavedFrameCache::FramePtr>
create(const FrameIter & iter)105 LiveSavedFrameCache::FramePtr::create(const FrameIter& iter) {
106 if (iter.done()) {
107 return mozilla::Nothing();
108 }
109
110 if (iter.isPhysicalJitFrame()) {
111 return mozilla::Some(FramePtr(iter.physicalJitFrame()));
112 }
113
114 if (!iter.hasUsableAbstractFramePtr()) {
115 return mozilla::Nothing();
116 }
117
118 auto afp = iter.abstractFramePtr();
119
120 if (afp.isInterpreterFrame()) {
121 return mozilla::Some(FramePtr(afp.asInterpreterFrame()));
122 }
123 if (afp.isWasmDebugFrame()) {
124 return mozilla::Some(FramePtr(afp.asWasmDebugFrame()));
125 }
126 if (afp.isRematerializedFrame()) {
127 return mozilla::Some(FramePtr(afp.asRematerializedFrame()));
128 }
129
130 MOZ_CRASH("unexpected frame type");
131 }
132
133 /* static */ inline LiveSavedFrameCache::FramePtr
create(AbstractFramePtr afp)134 LiveSavedFrameCache::FramePtr::create(AbstractFramePtr afp) {
135 MOZ_ASSERT(afp);
136
137 if (afp.isBaselineFrame()) {
138 js::jit::CommonFrameLayout* common = afp.asBaselineFrame()->framePrefix();
139 return FramePtr(common);
140 }
141 if (afp.isInterpreterFrame()) {
142 return FramePtr(afp.asInterpreterFrame());
143 }
144 if (afp.isWasmDebugFrame()) {
145 return FramePtr(afp.asWasmDebugFrame());
146 }
147 if (afp.isRematerializedFrame()) {
148 return FramePtr(afp.asRematerializedFrame());
149 }
150
151 MOZ_CRASH("unexpected frame type");
152 }
153
154 struct LiveSavedFrameCache::FramePtr::HasCachedMatcher {
155 template <typename Frame>
operatorHasCachedMatcher156 bool operator()(Frame* f) const {
157 return f->hasCachedSavedFrame();
158 }
159 };
160
hasCachedSavedFrame()161 inline bool LiveSavedFrameCache::FramePtr::hasCachedSavedFrame() const {
162 return ptr.match(HasCachedMatcher());
163 }
164
165 struct LiveSavedFrameCache::FramePtr::SetHasCachedMatcher {
166 template <typename Frame>
operatorSetHasCachedMatcher167 void operator()(Frame* f) {
168 f->setHasCachedSavedFrame();
169 }
170 };
171
setHasCachedSavedFrame()172 inline void LiveSavedFrameCache::FramePtr::setHasCachedSavedFrame() {
173 ptr.match(SetHasCachedMatcher());
174 }
175
176 struct LiveSavedFrameCache::FramePtr::ClearHasCachedMatcher {
177 template <typename Frame>
operatorClearHasCachedMatcher178 void operator()(Frame* f) {
179 f->clearHasCachedSavedFrame();
180 }
181 };
182
clearHasCachedSavedFrame()183 inline void LiveSavedFrameCache::FramePtr::clearHasCachedSavedFrame() {
184 ptr.match(ClearHasCachedMatcher());
185 }
186
hasWasmExitFP()187 inline bool Activation::hasWasmExitFP() const {
188 return isJit() && asJit()->hasWasmExitFP();
189 }
190
191 } // namespace js
192
193 #endif // vm_Activation_inl_h
194