summaryrefslogtreecommitdiffstats
path: root/js/src/jit/RematerializedFrame.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/RematerializedFrame.h')
-rw-r--r--js/src/jit/RematerializedFrame.h275
1 files changed, 275 insertions, 0 deletions
diff --git a/js/src/jit/RematerializedFrame.h b/js/src/jit/RematerializedFrame.h
new file mode 100644
index 000000000..80bbca34a
--- /dev/null
+++ b/js/src/jit/RematerializedFrame.h
@@ -0,0 +1,275 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef jit_RematerializedFrame_h
+#define jit_RematerializedFrame_h
+
+#include <algorithm>
+
+#include "jsfun.h"
+
+#include "jit/JitFrameIterator.h"
+#include "jit/JitFrames.h"
+
+#include "vm/EnvironmentObject.h"
+#include "vm/Stack.h"
+
+namespace js {
+namespace jit {
+
+//
+// An optimized frame that has been rematerialized with values read out of
+// Snapshots.
+//
+class RematerializedFrame
+{
+ // See DebugScopes::updateLiveScopes.
+ bool prevUpToDate_;
+
+ // Propagated to the Baseline frame once this is popped.
+ bool isDebuggee_;
+
+ // Has an initial environment has been pushed on the environment chain for
+ // function frames that need a CallObject or eval frames that need a
+ // VarEnvironmentObject?
+ bool hasInitialEnv_;
+
+ // Is this frame constructing?
+ bool isConstructing_;
+
+ // If true, this frame has been on the stack when
+ // |js::SavedStacks::saveCurrentStack| was called, and so there is a
+ // |js::SavedFrame| object cached for this frame.
+ bool hasCachedSavedFrame_;
+
+ // The fp of the top frame associated with this possibly inlined frame.
+ uint8_t* top_;
+
+ // The bytecode at the time of rematerialization.
+ jsbytecode* pc_;
+
+ size_t frameNo_;
+ unsigned numActualArgs_;
+
+ JSScript* script_;
+ JSObject* envChain_;
+ JSFunction* callee_;
+ ArgumentsObject* argsObj_;
+
+ Value returnValue_;
+ Value thisArgument_;
+ Value newTarget_;
+ Value slots_[1];
+
+ RematerializedFrame(JSContext* cx, uint8_t* top, unsigned numActualArgs,
+ InlineFrameIterator& iter, MaybeReadFallback& fallback);
+
+ public:
+ static RematerializedFrame* New(JSContext* cx, uint8_t* top, InlineFrameIterator& iter,
+ MaybeReadFallback& fallback);
+
+ // Rematerialize all remaining frames pointed to by |iter| into |frames|
+ // in older-to-younger order, e.g., frames[0] is the oldest frame.
+ static MOZ_MUST_USE bool RematerializeInlineFrames(JSContext* cx, uint8_t* top,
+ InlineFrameIterator& iter,
+ MaybeReadFallback& fallback,
+ GCVector<RematerializedFrame*>& frames);
+
+ // Free a vector of RematerializedFrames; takes care to call the
+ // destructor. Also clears the vector.
+ static void FreeInVector(GCVector<RematerializedFrame*>& frames);
+
+ bool prevUpToDate() const {
+ return prevUpToDate_;
+ }
+ void setPrevUpToDate() {
+ prevUpToDate_ = true;
+ }
+ void unsetPrevUpToDate() {
+ prevUpToDate_ = false;
+ }
+
+ bool isDebuggee() const {
+ return isDebuggee_;
+ }
+ void setIsDebuggee() {
+ isDebuggee_ = true;
+ }
+ void unsetIsDebuggee() {
+ MOZ_ASSERT(!script()->isDebuggee());
+ isDebuggee_ = false;
+ }
+
+ uint8_t* top() const {
+ return top_;
+ }
+ JSScript* outerScript() const {
+ JitFrameLayout* jsFrame = (JitFrameLayout*)top_;
+ return ScriptFromCalleeToken(jsFrame->calleeToken());
+ }
+ jsbytecode* pc() const {
+ return pc_;
+ }
+ size_t frameNo() const {
+ return frameNo_;
+ }
+ bool inlined() const {
+ return frameNo_ > 0;
+ }
+
+ JSObject* environmentChain() const {
+ return envChain_;
+ }
+
+ template <typename SpecificEnvironment>
+ void pushOnEnvironmentChain(SpecificEnvironment& env) {
+ MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment());
+ envChain_ = &env;
+ if (IsFrameInitialEnvironment(this, env))
+ hasInitialEnv_ = true;
+ }
+
+ template <typename SpecificEnvironment>
+ void popOffEnvironmentChain() {
+ MOZ_ASSERT(envChain_->is<SpecificEnvironment>());
+ envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment();
+ }
+
+ MOZ_MUST_USE bool initFunctionEnvironmentObjects(JSContext* cx);
+ MOZ_MUST_USE bool pushVarEnvironment(JSContext* cx, HandleScope scope);
+
+ bool hasInitialEnvironment() const {
+ return hasInitialEnv_;
+ }
+ CallObject& callObj() const;
+
+ bool hasArgsObj() const {
+ return !!argsObj_;
+ }
+ ArgumentsObject& argsObj() const {
+ MOZ_ASSERT(hasArgsObj());
+ MOZ_ASSERT(script()->needsArgsObj());
+ return *argsObj_;
+ }
+
+ bool isFunctionFrame() const {
+ return !!script_->functionNonDelazifying();
+ }
+ bool isGlobalFrame() const {
+ return script_->isGlobalCode();
+ }
+ bool isModuleFrame() const {
+ return script_->module();
+ }
+
+ JSScript* script() const {
+ return script_;
+ }
+ JSFunction* callee() const {
+ MOZ_ASSERT(isFunctionFrame());
+ MOZ_ASSERT(callee_);
+ return callee_;
+ }
+ Value calleev() const {
+ return ObjectValue(*callee());
+ }
+ Value& thisArgument() {
+ return thisArgument_;
+ }
+
+ bool isConstructing() const {
+ return isConstructing_;
+ }
+
+ bool hasCachedSavedFrame() const {
+ return hasCachedSavedFrame_;
+ }
+
+ void setHasCachedSavedFrame() {
+ hasCachedSavedFrame_ = true;
+ }
+
+ unsigned numFormalArgs() const {
+ return isFunctionFrame() ? callee()->nargs() : 0;
+ }
+ unsigned numActualArgs() const {
+ return numActualArgs_;
+ }
+ unsigned numArgSlots() const {
+ return (std::max)(numFormalArgs(), numActualArgs());
+ }
+
+ Value* argv() {
+ return slots_;
+ }
+ Value* locals() {
+ return slots_ + numArgSlots();
+ }
+
+ Value& unaliasedLocal(unsigned i) {
+ MOZ_ASSERT(i < script()->nfixed());
+ return locals()[i];
+ }
+ Value& unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) {
+ MOZ_ASSERT(i < numFormalArgs());
+ MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals() &&
+ !script()->formalIsAliased(i));
+ return argv()[i];
+ }
+ Value& unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) {
+ MOZ_ASSERT(i < numActualArgs());
+ MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
+ MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
+ return argv()[i];
+ }
+
+ Value newTarget() {
+ MOZ_ASSERT(isFunctionFrame());
+ if (callee()->isArrow())
+ return callee()->getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
+ MOZ_ASSERT_IF(!isConstructing(), newTarget_.isUndefined());
+ return newTarget_;
+ }
+
+ void setReturnValue(const Value& value) {
+ returnValue_ = value;
+ }
+
+ Value& returnValue() {
+ return returnValue_;
+ }
+
+ void trace(JSTracer* trc);
+ void dump();
+};
+
+} // namespace jit
+} // namespace js
+
+namespace JS {
+
+template <>
+struct MapTypeToRootKind<js::jit::RematerializedFrame*>
+{
+ static const RootKind kind = RootKind::Traceable;
+};
+
+template <>
+struct GCPolicy<js::jit::RematerializedFrame*>
+{
+ static js::jit::RematerializedFrame* initial() {
+ return nullptr;
+ }
+
+ static void trace(JSTracer* trc, js::jit::RematerializedFrame** frame, const char* name) {
+ if (*frame)
+ (*frame)->trace(trc);
+ }
+};
+
+} // namespace JS
+
+#endif // jit_RematerializedFrame_h