diff options
Diffstat (limited to 'js/src/jit/RematerializedFrame.cpp')
-rw-r--r-- | js/src/jit/RematerializedFrame.cpp | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/js/src/jit/RematerializedFrame.cpp b/js/src/jit/RematerializedFrame.cpp new file mode 100644 index 000000000..cb324220c --- /dev/null +++ b/js/src/jit/RematerializedFrame.cpp @@ -0,0 +1,222 @@ +/* -*- 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/. */ + +#include "jit/RematerializedFrame.h" + +#include "mozilla/SizePrintfMacros.h" + +#include "jit/JitFrames.h" +#include "vm/ArgumentsObject.h" +#include "vm/Debugger.h" + +#include "jsscriptinlines.h" +#include "jit/JitFrames-inl.h" +#include "vm/EnvironmentObject-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()), + isConstructing_(iter.isConstructing()), + hasCachedSavedFrame_(false), + top_(top), + pc_(iter.pc()), + frameNo_(iter.frameNo()), + numActualArgs_(numActualArgs), + script_(iter.script()) +{ + 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 = Max(numFormals, iter.numActualArgs()); + size_t numBytes = sizeof(RematerializedFrame) + + (argSlots + iter.script()->nfixed()) * sizeof(Value) - + sizeof(Value); // 1 Value included in sizeof(RematerializedFrame) + + void* buf = cx->pod_calloc<uint8_t>(numBytes); + 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, + GCVector<RematerializedFrame*>& frames) +{ + Rooted<GCVector<RematerializedFrame*>> tempFrames(cx, GCVector<RematerializedFrame*>(cx)); + if (!tempFrames.resize(iter.frameCount())) + return false; + + while (true) { + size_t frameNo = iter.frameNo(); + tempFrames[frameNo].set(RematerializedFrame::New(cx, top, iter, fallback)); + if (!tempFrames[frameNo]) + return false; + if (tempFrames[frameNo]->environmentChain()) { + if (!EnsureHasEnvironmentObjects(cx, tempFrames[frameNo].get())) + return false; + } + + if (!iter.more()) + break; + ++iter; + } + + frames = Move(tempFrames.get()); + return true; +} + +/* static */ void +RematerializedFrame::FreeInVector(GCVector<RematerializedFrame*>& frames) +{ + for (size_t i = 0; i < frames.length(); i++) { + RematerializedFrame* f = frames[i]; + MOZ_ASSERT(!Debugger::inFrameMaps(f)); + f->RematerializedFrame::~RematerializedFrame(); + js_free(f); + } + frames.clear(); +} + +CallObject& +RematerializedFrame::callObj() const +{ + MOZ_ASSERT(hasInitialEnvironment()); + + 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 %" PRIuSIZE " offset %" PRIuSIZE "\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 %d): ", i); + else + fprintf(stderr, " overflown (arg %d): ", i); +#ifdef DEBUG + DumpValue(argv()[i]); +#else + fprintf(stderr, "?\n"); +#endif + } + + for (unsigned i = 0; i < script()->nfixed(); i++) { + fprintf(stderr, " local %d: ", i); +#ifdef DEBUG + DumpValue(locals()[i]); +#else + fprintf(stderr, "?\n"); +#endif + } + } + + fputc('\n', stderr); +} |