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