diff options
Diffstat (limited to 'js/src/jit/RematerializedFrame.cpp')
-rw-r--r-- | js/src/jit/RematerializedFrame.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/js/src/jit/RematerializedFrame.cpp b/js/src/jit/RematerializedFrame.cpp new file mode 100644 index 0000000000..752b6d61a7 --- /dev/null +++ b/js/src/jit/RematerializedFrame.cpp @@ -0,0 +1,221 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * 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/. */ + +#include "jit/RematerializedFrame.h" + +#include <algorithm> +#include <utility> + +#include "debugger/DebugAPI.h" +#include "jit/Bailouts.h" +#include "js/friend/DumpFunctions.h" // js::DumpValue +#include "vm/ArgumentsObject.h" + +#include "vm/EnvironmentObject-inl.h" +#include "vm/JSScript-inl.h" + +using namespace js; +using namespace jit; + +struct CopyValueToRematerializedFrame { + Value* slots; + + explicit CopyValueToRematerializedFrame(Value* slots) : slots(slots) {} + + void operator()(const Value& v) { *slots++ = v; } +}; + +RematerializedFrame::RematerializedFrame(JSContext* cx, uint8_t* top, + unsigned numActualArgs, + InlineFrameIterator& iter, + MaybeReadFallback& fallback) + : prevUpToDate_(false), + isDebuggee_(iter.script()->isDebuggee()), + hasInitialEnv_(false), + isConstructing_(iter.isConstructing()), + hasCachedSavedFrame_(false), + top_(top), + pc_(iter.pc()), + frameNo_(iter.frameNo()), + numActualArgs_(numActualArgs), + script_(iter.script()), + envChain_(nullptr), + argsObj_(nullptr) { + if (iter.isFunctionFrame()) { + callee_ = iter.callee(fallback); + } else { + callee_ = nullptr; + } + + CopyValueToRematerializedFrame op(slots_); + iter.readFrameArgsAndLocals(cx, op, op, &envChain_, &hasInitialEnv_, + &returnValue_, &argsObj_, &thisArgument_, + &newTarget_, ReadFrame_Actuals, fallback); +} + +/* static */ +RematerializedFrame* RematerializedFrame::New(JSContext* cx, uint8_t* top, + InlineFrameIterator& iter, + MaybeReadFallback& fallback) { + unsigned numFormals = + iter.isFunctionFrame() ? iter.calleeTemplate()->nargs() : 0; + unsigned argSlots = std::max(numFormals, iter.numActualArgs()); + unsigned extraSlots = argSlots + iter.script()->nfixed(); + + // One Value slot is included in sizeof(RematerializedFrame), so we can + // reduce the extra slot count by one. However, if there are zero slot + // allocations total, then reducing the slots by one will lead to + // the memory allocation being smaller than sizeof(RematerializedFrame). + if (extraSlots > 0) { + extraSlots -= 1; + } + + RematerializedFrame* buf = + cx->pod_calloc_with_extra<RematerializedFrame, Value>(extraSlots); + if (!buf) { + return nullptr; + } + + return new (buf) + RematerializedFrame(cx, top, iter.numActualArgs(), iter, fallback); +} + +/* static */ +bool RematerializedFrame::RematerializeInlineFrames( + JSContext* cx, uint8_t* top, InlineFrameIterator& iter, + MaybeReadFallback& fallback, RematerializedFrameVector& frames) { + Rooted<RematerializedFrameVector> tempFrames(cx, + RematerializedFrameVector(cx)); + if (!tempFrames.resize(iter.frameCount())) { + return false; + } + + while (true) { + size_t frameNo = iter.frameNo(); + tempFrames[frameNo].reset( + RematerializedFrame::New(cx, top, iter, fallback)); + if (!tempFrames[frameNo]) { + return false; + } + if (tempFrames[frameNo]->environmentChain()) { + if (!EnsureHasEnvironmentObjects(cx, tempFrames[frameNo].get().get())) { + return false; + } + } + + if (!iter.more()) { + break; + } + ++iter; + } + + frames = std::move(tempFrames.get()); + return true; +} + +CallObject& RematerializedFrame::callObj() const { + MOZ_ASSERT(hasInitialEnvironment()); + MOZ_ASSERT(callee()->needsCallObject()); + + JSObject* env = environmentChain(); + while (!env->is<CallObject>()) { + env = env->enclosingEnvironment(); + } + return env->as<CallObject>(); +} + +bool RematerializedFrame::initFunctionEnvironmentObjects(JSContext* cx) { + return js::InitFunctionEnvironmentObjects(cx, this); +} + +bool RematerializedFrame::pushVarEnvironment(JSContext* cx, HandleScope scope) { + return js::PushVarEnvironmentObject(cx, scope, this); +} + +void RematerializedFrame::trace(JSTracer* trc) { + TraceRoot(trc, &script_, "remat ion frame script"); + TraceRoot(trc, &envChain_, "remat ion frame env chain"); + if (callee_) { + TraceRoot(trc, &callee_, "remat ion frame callee"); + } + if (argsObj_) { + TraceRoot(trc, &argsObj_, "remat ion frame argsobj"); + } + TraceRoot(trc, &returnValue_, "remat ion frame return value"); + TraceRoot(trc, &thisArgument_, "remat ion frame this"); + TraceRoot(trc, &newTarget_, "remat ion frame newTarget"); + TraceRootRange(trc, numArgSlots() + script_->nfixed(), slots_, + "remat ion frame stack"); +} + +void RematerializedFrame::dump() { + fprintf(stderr, " Rematerialized Ion Frame%s\n", + inlined() ? " (inlined)" : ""); + if (isFunctionFrame()) { + fprintf(stderr, " callee fun: "); +#ifdef DEBUG + DumpValue(ObjectValue(*callee())); +#else + fprintf(stderr, "?\n"); +#endif + } else { + fprintf(stderr, " global frame, no callee\n"); + } + + fprintf(stderr, " file %s line %u offset %zu\n", script()->filename(), + script()->lineno(), script()->pcToOffset(pc())); + + fprintf(stderr, " script = %p\n", (void*)script()); + + if (isFunctionFrame()) { + fprintf(stderr, " env chain: "); +#ifdef DEBUG + DumpValue(ObjectValue(*environmentChain())); +#else + fprintf(stderr, "?\n"); +#endif + + if (hasArgsObj()) { + fprintf(stderr, " args obj: "); +#ifdef DEBUG + DumpValue(ObjectValue(argsObj())); +#else + fprintf(stderr, "?\n"); +#endif + } + + fprintf(stderr, " this: "); +#ifdef DEBUG + DumpValue(thisArgument()); +#else + fprintf(stderr, "?\n"); +#endif + + for (unsigned i = 0; i < numActualArgs(); i++) { + if (i < numFormalArgs()) { + fprintf(stderr, " formal (arg %u): ", i); + } else { + fprintf(stderr, " overflown (arg %u): ", i); + } +#ifdef DEBUG + DumpValue(argv()[i]); +#else + fprintf(stderr, "?\n"); +#endif + } + + for (unsigned i = 0; i < script()->nfixed(); i++) { + fprintf(stderr, " local %u: ", i); +#ifdef DEBUG + DumpValue(locals()[i]); +#else + fprintf(stderr, "?\n"); +#endif + } + } + + fputc('\n', stderr); +} |