1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * vim: set ts=8 sts=4 et sw=4 tw=99: 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 jit_RematerializedFrame_h 8 #define jit_RematerializedFrame_h 9 10 #include <algorithm> 11 12 #include "jit/JitFrames.h" 13 #include "jit/JSJitFrameIter.h" 14 #include "vm/EnvironmentObject.h" 15 #include "vm/JSFunction.h" 16 #include "vm/Stack.h" 17 18 namespace js { 19 namespace jit { 20 21 // 22 // An optimized frame that has been rematerialized with values read out of 23 // Snapshots. 24 // 25 class RematerializedFrame { 26 // See DebugScopes::updateLiveScopes. 27 bool prevUpToDate_; 28 29 // Propagated to the Baseline frame once this is popped. 30 bool isDebuggee_; 31 32 // Has an initial environment has been pushed on the environment chain for 33 // function frames that need a CallObject or eval frames that need a 34 // VarEnvironmentObject? 35 bool hasInitialEnv_; 36 37 // Is this frame constructing? 38 bool isConstructing_; 39 40 // If true, this frame has been on the stack when 41 // |js::SavedStacks::saveCurrentStack| was called, and so there is a 42 // |js::SavedFrame| object cached for this frame. 43 bool hasCachedSavedFrame_; 44 45 // The fp of the top frame associated with this possibly inlined frame. 46 uint8_t* top_; 47 48 // The bytecode at the time of rematerialization. 49 jsbytecode* pc_; 50 51 size_t frameNo_; 52 unsigned numActualArgs_; 53 54 JSScript* script_; 55 JSObject* envChain_; 56 JSFunction* callee_; 57 ArgumentsObject* argsObj_; 58 59 Value returnValue_; 60 Value thisArgument_; 61 Value newTarget_; 62 Value slots_[1]; 63 64 RematerializedFrame(JSContext* cx, uint8_t* top, unsigned numActualArgs, 65 InlineFrameIterator& iter, MaybeReadFallback& fallback); 66 67 public: 68 static RematerializedFrame* New(JSContext* cx, uint8_t* top, 69 InlineFrameIterator& iter, 70 MaybeReadFallback& fallback); 71 72 // Rematerialize all remaining frames pointed to by |iter| into |frames| 73 // in older-to-younger order, e.g., frames[0] is the oldest frame. 74 static MOZ_MUST_USE bool RematerializeInlineFrames( 75 JSContext* cx, uint8_t* top, InlineFrameIterator& iter, 76 MaybeReadFallback& fallback, GCVector<RematerializedFrame*>& frames); 77 78 // Free a vector of RematerializedFrames; takes care to call the 79 // destructor. Also clears the vector. 80 static void FreeInVector(GCVector<RematerializedFrame*>& frames); 81 prevUpToDate()82 bool prevUpToDate() const { return prevUpToDate_; } setPrevUpToDate()83 void setPrevUpToDate() { prevUpToDate_ = true; } unsetPrevUpToDate()84 void unsetPrevUpToDate() { prevUpToDate_ = false; } 85 isDebuggee()86 bool isDebuggee() const { return isDebuggee_; } setIsDebuggee()87 void setIsDebuggee() { isDebuggee_ = true; } unsetIsDebuggee()88 void unsetIsDebuggee() { 89 MOZ_ASSERT(!script()->isDebuggee()); 90 isDebuggee_ = false; 91 } 92 top()93 uint8_t* top() const { return top_; } outerScript()94 JSScript* outerScript() const { 95 JitFrameLayout* jsFrame = (JitFrameLayout*)top_; 96 return ScriptFromCalleeToken(jsFrame->calleeToken()); 97 } pc()98 jsbytecode* pc() const { return pc_; } frameNo()99 size_t frameNo() const { return frameNo_; } inlined()100 bool inlined() const { return frameNo_ > 0; } 101 environmentChain()102 JSObject* environmentChain() const { return envChain_; } 103 104 template <typename SpecificEnvironment> pushOnEnvironmentChain(SpecificEnvironment & env)105 void pushOnEnvironmentChain(SpecificEnvironment& env) { 106 MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment()); 107 envChain_ = &env; 108 if (IsFrameInitialEnvironment(this, env)) hasInitialEnv_ = true; 109 } 110 111 template <typename SpecificEnvironment> popOffEnvironmentChain()112 void popOffEnvironmentChain() { 113 MOZ_ASSERT(envChain_->is<SpecificEnvironment>()); 114 envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment(); 115 } 116 117 MOZ_MUST_USE bool initFunctionEnvironmentObjects(JSContext* cx); 118 MOZ_MUST_USE bool pushVarEnvironment(JSContext* cx, HandleScope scope); 119 hasInitialEnvironment()120 bool hasInitialEnvironment() const { return hasInitialEnv_; } 121 CallObject& callObj() const; 122 hasArgsObj()123 bool hasArgsObj() const { return !!argsObj_; } argsObj()124 ArgumentsObject& argsObj() const { 125 MOZ_ASSERT(hasArgsObj()); 126 MOZ_ASSERT(script()->needsArgsObj()); 127 return *argsObj_; 128 } 129 isFunctionFrame()130 bool isFunctionFrame() const { return !!script_->functionNonDelazifying(); } isGlobalFrame()131 bool isGlobalFrame() const { return script_->isGlobalCode(); } isModuleFrame()132 bool isModuleFrame() const { return script_->module(); } 133 script()134 JSScript* script() const { return script_; } callee()135 JSFunction* callee() const { 136 MOZ_ASSERT(isFunctionFrame()); 137 MOZ_ASSERT(callee_); 138 return callee_; 139 } calleev()140 Value calleev() const { return ObjectValue(*callee()); } thisArgument()141 Value& thisArgument() { return thisArgument_; } 142 isConstructing()143 bool isConstructing() const { return isConstructing_; } 144 hasCachedSavedFrame()145 bool hasCachedSavedFrame() const { return hasCachedSavedFrame_; } 146 setHasCachedSavedFrame()147 void setHasCachedSavedFrame() { hasCachedSavedFrame_ = true; } 148 numFormalArgs()149 unsigned numFormalArgs() const { 150 return isFunctionFrame() ? callee()->nargs() : 0; 151 } numActualArgs()152 unsigned numActualArgs() const { return numActualArgs_; } numArgSlots()153 unsigned numArgSlots() const { 154 return (std::max)(numFormalArgs(), numActualArgs()); 155 } 156 argv()157 Value* argv() { return slots_; } locals()158 Value* locals() { return slots_ + numArgSlots(); } 159 unaliasedLocal(unsigned i)160 Value& unaliasedLocal(unsigned i) { 161 MOZ_ASSERT(i < script()->nfixed()); 162 return locals()[i]; 163 } 164 Value& unaliasedFormal(unsigned i, 165 MaybeCheckAliasing checkAliasing = CHECK_ALIASING) { 166 MOZ_ASSERT(i < numFormalArgs()); 167 MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals() && 168 !script()->formalIsAliased(i)); 169 return argv()[i]; 170 } 171 Value& unaliasedActual(unsigned i, 172 MaybeCheckAliasing checkAliasing = CHECK_ALIASING) { 173 MOZ_ASSERT(i < numActualArgs()); 174 MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals()); 175 MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(), 176 !script()->formalIsAliased(i)); 177 return argv()[i]; 178 } 179 newTarget()180 Value newTarget() { 181 MOZ_ASSERT(isFunctionFrame()); 182 if (callee()->isArrow()) 183 return callee()->getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT); 184 MOZ_ASSERT_IF(!isConstructing(), newTarget_.isUndefined()); 185 return newTarget_; 186 } 187 setReturnValue(const Value & value)188 void setReturnValue(const Value& value) { returnValue_ = value; } 189 returnValue()190 Value& returnValue() { return returnValue_; } 191 192 void trace(JSTracer* trc); 193 void dump(); 194 }; 195 196 } // namespace jit 197 } // namespace js 198 199 namespace JS { 200 201 template <> 202 struct MapTypeToRootKind<js::jit::RematerializedFrame*> { 203 static const RootKind kind = RootKind::Traceable; 204 }; 205 206 template <> 207 struct GCPolicy<js::jit::RematerializedFrame*> 208 : public NonGCPointerPolicy<js::jit::RematerializedFrame*> {}; 209 210 } // namespace JS 211 212 #endif // jit_RematerializedFrame_h 213