blob: 255037f767231636add40f1d84594ad29aa1087f [file] [log] [blame]
/* -*- 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 vm_ScopeObject_inl_h
#define vm_ScopeObject_inl_h
#include "ScopeObject.h"
#include "jsinferinlines.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"
template<>
inline bool
JSObject::is<js::ClonedBlockObject>() const
{
return is<js::BlockObject>() && !!getProto();
}
template<>
inline bool
JSObject::is<js::StaticBlockObject>() const
{
return is<js::BlockObject>() && !getProto();
}
inline JSObject *
JSObject::enclosingScope()
{
return is<js::ScopeObject>()
? &as<js::ScopeObject>().enclosingScope()
: is<js::DebugScopeObject>()
? &as<js::DebugScopeObject>().enclosingScope()
: getParent();
}
namespace js {
inline
ScopeCoordinate::ScopeCoordinate(jsbytecode *pc)
: hops(GET_UINT16(pc)), slot(GET_UINT16(pc + 2))
{
JS_ASSERT(JOF_OPTYPE(*pc) == JOF_SCOPECOORD);
}
inline void
ScopeObject::setEnclosingScope(HandleObject obj)
{
JS_ASSERT_IF(obj->is<CallObject>() || obj->is<DeclEnvObject>() || obj->is<BlockObject>(),
obj->isDelegate());
setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*obj));
}
inline const Value &
ScopeObject::aliasedVar(ScopeCoordinate sc)
{
JS_ASSERT(is<CallObject>() || is<ClonedBlockObject>());
return getSlot(sc.slot);
}
inline void
ScopeObject::setAliasedVar(JSContext *cx, ScopeCoordinate sc, PropertyName *name, const Value &v)
{
JS_ASSERT(is<CallObject>() || is<ClonedBlockObject>());
JS_STATIC_ASSERT(CallObject::RESERVED_SLOTS == BlockObject::RESERVED_SLOTS);
// name may be null for non-singletons, whose types do not need to be tracked.
JS_ASSERT_IF(hasSingletonType(), name);
setSlot(sc.slot, v);
if (hasSingletonType())
types::AddTypePropertyId(cx, this, NameToId(name), v);
}
/*static*/ inline size_t
ScopeObject::offsetOfEnclosingScope()
{
return getFixedSlotOffset(SCOPE_CHAIN_SLOT);
}
inline bool
CallObject::isForEval() const
{
JS_ASSERT(getReservedSlot(CALLEE_SLOT).isObjectOrNull());
JS_ASSERT_IF(getReservedSlot(CALLEE_SLOT).isObject(),
getReservedSlot(CALLEE_SLOT).toObject().is<JSFunction>());
return getReservedSlot(CALLEE_SLOT).isNull();
}
inline JSFunction &
CallObject::callee() const
{
return getReservedSlot(CALLEE_SLOT).toObject().as<JSFunction>();
}
inline const Value &
CallObject::aliasedVar(AliasedFormalIter fi)
{
return getSlot(fi.scopeSlot());
}
inline void
CallObject::setAliasedVar(JSContext *cx, AliasedFormalIter fi, PropertyName *name, const Value &v)
{
JS_ASSERT(name == fi->name());
setSlot(fi.scopeSlot(), v);
if (hasSingletonType())
types::AddTypePropertyId(cx, this, NameToId(name), v);
}
/*static*/ inline size_t
CallObject::offsetOfCallee()
{
return getFixedSlotOffset(CALLEE_SLOT);
}
inline uint32_t
NestedScopeObject::stackDepth() const
{
return getReservedSlot(DEPTH_SLOT).toPrivateUint32();
}
inline JSObject &
WithObject::withThis() const
{
return getReservedSlot(THIS_SLOT).toObject();
}
inline JSObject &
WithObject::object() const
{
return *JSObject::getProto();
}
inline uint32_t
BlockObject::slotCount() const
{
return propertyCount();
}
inline unsigned
BlockObject::slotToLocalIndex(const Bindings &bindings, unsigned slot)
{
JS_ASSERT(slot < RESERVED_SLOTS + slotCount());
return bindings.numVars() + stackDepth() + (slot - RESERVED_SLOTS);
}
inline unsigned
BlockObject::localIndexToSlot(const Bindings &bindings, unsigned i)
{
return RESERVED_SLOTS + (i - (bindings.numVars() + stackDepth()));
}
inline const Value &
BlockObject::slotValue(unsigned i)
{
return getSlotRef(RESERVED_SLOTS + i);
}
inline void
BlockObject::setSlotValue(unsigned i, const Value &v)
{
setSlot(RESERVED_SLOTS + i, v);
}
inline void
StaticBlockObject::initPrevBlockChainFromParser(StaticBlockObject *prev)
{
setReservedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(prev));
}
inline void
StaticBlockObject::resetPrevBlockChainFromParser()
{
setReservedSlot(SCOPE_CHAIN_SLOT, UndefinedValue());
}
inline void
StaticBlockObject::initEnclosingStaticScope(JSObject *obj)
{
JS_ASSERT(getReservedSlot(SCOPE_CHAIN_SLOT).isUndefined());
setReservedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(obj));
}
inline StaticBlockObject *
StaticBlockObject::enclosingBlock() const
{
JSObject *obj = getReservedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
return obj && obj->is<StaticBlockObject>() ? &obj->as<StaticBlockObject>() : NULL;
}
inline JSObject *
StaticBlockObject::enclosingStaticScope() const
{
return getReservedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
}
inline void
StaticBlockObject::setStackDepth(uint32_t depth)
{
JS_ASSERT(getReservedSlot(DEPTH_SLOT).isUndefined());
initReservedSlot(DEPTH_SLOT, PrivateUint32Value(depth));
}
inline void
StaticBlockObject::setDefinitionParseNode(unsigned i, frontend::Definition *def)
{
JS_ASSERT(slotValue(i).isUndefined());
setSlotValue(i, PrivateValue(def));
}
inline frontend::Definition *
StaticBlockObject::maybeDefinitionParseNode(unsigned i)
{
Value v = slotValue(i);
return v.isUndefined() ? NULL : reinterpret_cast<frontend::Definition *>(v.toPrivate());
}
inline void
StaticBlockObject::setAliased(unsigned i, bool aliased)
{
JS_ASSERT_IF(i > 0, slotValue(i-1).isBoolean());
setSlotValue(i, BooleanValue(aliased));
if (aliased && !needsClone()) {
setSlotValue(0, MagicValue(JS_BLOCK_NEEDS_CLONE));
JS_ASSERT(needsClone());
}
}
inline bool
StaticBlockObject::isAliased(unsigned i)
{
return slotValue(i).isTrue();
}
inline bool
StaticBlockObject::needsClone()
{
return !slotValue(0).isFalse();
}
inline bool
StaticBlockObject::containsVarAtDepth(uint32_t depth)
{
return depth >= stackDepth() && depth < stackDepth() + slotCount();
}
inline StaticBlockObject &
ClonedBlockObject::staticBlock() const
{
return getProto()->as<StaticBlockObject>();
}
inline const Value &
ClonedBlockObject::var(unsigned i, MaybeCheckAliasing checkAliasing)
{
JS_ASSERT_IF(checkAliasing, staticBlock().isAliased(i));
return slotValue(i);
}
inline void
ClonedBlockObject::setVar(unsigned i, const Value &v, MaybeCheckAliasing checkAliasing)
{
JS_ASSERT_IF(checkAliasing, staticBlock().isAliased(i));
setSlotValue(i, v);
}
} /* namespace js */
#endif /* vm_ScopeObject_inl_h */