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