Dactyloidae/js/src/jit/RematerializedFrame.h

275 lines
7.5 KiB
C++

/* -*- 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