Bug 1092032 - Bias magic uint32s in ArgumentObject forwarded slots by the maximum JSWhyMagic value to distinguish them from the JSWhyMagic-based magic values. (r=luke)

This commit is contained in:
Shu-yu Guo 2014-10-31 16:46:26 -07:00
parent e5309afe00
commit b6c6dffa24
6 changed files with 29 additions and 8 deletions

View File

@ -244,7 +244,8 @@ typedef enum JSWhyMagic
JS_OPTIMIZED_OUT, /* optimized out slot */
JS_UNINITIALIZED_LEXICAL, /* uninitialized lexical bindings that produce ReferenceError
* on touch. */
JS_GENERIC_MAGIC /* for local use */
JS_GENERIC_MAGIC, /* for local use */
JS_WHY_MAGIC_COUNT
} JSWhyMagic;
#if defined(IS_LITTLE_ENDIAN)

View File

@ -22,7 +22,7 @@ ArgumentsObject::element(uint32_t i) const
{
MOZ_ASSERT(!isElementDeleted(i));
const Value &v = data()->args[i];
if (v.isMagic()) {
if (IsMagicScopeSlotValue(v)) {
CallObject &callobj = getFixedSlot(MAYBE_CALL_SLOT).toObject().as<CallObject>();
return callobj.aliasedVarFromArguments(v);
}
@ -34,8 +34,8 @@ ArgumentsObject::setElement(JSContext *cx, uint32_t i, const Value &v)
{
MOZ_ASSERT(!isElementDeleted(i));
HeapValue &lhs = data()->args[i];
if (lhs.isMagic()) {
uint32_t slot = lhs.magicUint32();
if (IsMagicScopeSlotValue(lhs)) {
uint32_t slot = SlotFromMagicScopeSlotValue(lhs);
CallObject &callobj = getFixedSlot(MAYBE_CALL_SLOT).toObject().as<CallObject>();
for (Shape::Range<NoGC> r(callobj.lastProperty()); !r.empty(); r.popFront()) {
if (r.front().slot() == slot) {

View File

@ -41,7 +41,7 @@ ArgumentsObject::MaybeForwardToCallObject(AbstractFramePtr frame, ArgumentsObjec
if (frame.fun()->isHeavyweight() && script->argsObjAliasesFormals()) {
obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(frame.callObj()));
for (AliasedFormalIter fi(script); fi; fi++)
data->args[fi.frameIndex()] = JS::MagicValueUint32(fi.scopeSlot());
data->args[fi.frameIndex()] = MagicScopeSlotValue(fi.scopeSlot());
}
}
@ -55,7 +55,7 @@ ArgumentsObject::MaybeForwardToCallObject(jit::IonJSFrameLayout *frame, HandleOb
MOZ_ASSERT(callObj && callObj->is<CallObject>());
obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(*callObj.get()));
for (AliasedFormalIter fi(script); fi; fi++)
data->args[fi.frameIndex()] = JS::MagicValueUint32(fi.scopeSlot());
data->args[fi.frameIndex()] = MagicScopeSlotValue(fi.scopeSlot());
}
}

View File

@ -270,6 +270,25 @@ class ArgumentsObject : public NativeObject
return getFixedSlotOffset(INITIAL_LENGTH_SLOT);
}
static Value MagicScopeSlotValue(uint32_t slot) {
// When forwarding slots to a backing CallObject, the slot numbers are
// stored as uint32 magic values. This raises an ambiguity if we have
// also copied JS_OPTIMIZED_OUT magic from a JIT frame or
// JS_UNINITIALIZED_LEXICAL magic on the CallObject. To distinguish
// normal magic values (those with a JSWhyMagic) and uint32 magic
// values, we add the maximum JSWhyMagic value to the slot
// number. This is safe as ARGS_LENGTH_MAX is well below UINT32_MAX.
JS_STATIC_ASSERT(UINT32_MAX - JS_WHY_MAGIC_COUNT > ARGS_LENGTH_MAX);
return JS::MagicValueUint32(slot + JS_WHY_MAGIC_COUNT);
}
static uint32_t SlotFromMagicScopeSlotValue(const Value &v) {
JS_STATIC_ASSERT(UINT32_MAX - JS_WHY_MAGIC_COUNT > ARGS_LENGTH_MAX);
return v.magicUint32() - JS_WHY_MAGIC_COUNT;
}
static bool IsMagicScopeSlotValue(const Value &v) {
return v.isMagic() && v.magicUint32() > JS_WHY_MAGIC_COUNT;
}
static void MaybeForwardToCallObject(AbstractFramePtr frame, ArgumentsObject *obj,
ArgumentsData *data);
static void MaybeForwardToCallObject(jit::IonJSFrameLayout *frame, HandleObject callObj,

View File

@ -48,7 +48,7 @@ CallObject::setAliasedVar(JSContext *cx, AliasedFormalIter fi, PropertyName *nam
inline void
CallObject::setAliasedVarFromArguments(JSContext *cx, const Value &argsValue, jsid id, const Value &v)
{
setSlot(argsValue.magicUint32(), v);
setSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue), v);
if (hasSingletonType())
types::AddTypePropertyId(cx, this, id, v);
}

View File

@ -12,6 +12,7 @@
#include "jsweakmap.h"
#include "gc/Barrier.h"
#include "vm/ArgumentsObject.h"
#include "vm/ProxyObject.h"
namespace js {
@ -301,7 +302,7 @@ class CallObject : public ScopeObject
* CallObject to access.
*/
const Value &aliasedVarFromArguments(const Value &argsValue) {
return getSlot(argsValue.magicUint32());
return getSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue));
}
inline void setAliasedVarFromArguments(JSContext *cx, const Value &argsValue, jsid id,
const Value &v);