Bug 1171177 - Remove UNQUALIFIED_VAROBJ Shape flags in favor of Class-checking. (r=luke)

This commit is contained in:
Shu-yu Guo 2015-06-19 01:21:14 -07:00
parent 77c2695ddd
commit 7bae1e6428
5 changed files with 40 additions and 29 deletions

View File

@ -216,16 +216,35 @@ class JSObject : public js::gc::Cell
return setFlags(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
}
/* See InterpreterFrame::varObj. */
inline bool isQualifiedVarObj();
// A "qualified" varobj is the object on which "qualified" variable
// declarations (i.e., those defined with "var") are kept.
//
// Conceptually, when a var binding is defined, it is defined on the
// innermost qualified varobj on the scope chain.
//
// Function scopes (CallObjects) are qualified varobjs, and there can be
// no other qualified varobj that is more inner for var bindings in that
// function. As such, all references to local var bindings in a function
// may be statically bound to the function scope. This is subject to
// further optimization. Unaliased bindings inside functions reside
// entirely on the frame, not in CallObjects.
//
// Global scopes are also qualified varobjs. It is possible to statically
// know, for a given script, that are no more inner qualified varobjs, so
// free variable references can be statically bound to the global.
//
// Finally, there are non-syntactic qualified varobjs used by embedders
// (e.g., Gecko and XPConnect), as they often wish to run scripts under a
// scope that captures var bindings.
inline bool isQualifiedVarObj() const;
bool setQualifiedVarObj(js::ExclusiveContext* cx) {
return setFlags(cx, js::BaseShape::QUALIFIED_VAROBJ);
}
inline bool isUnqualifiedVarObj();
bool setUnqualifiedVarObj(js::ExclusiveContext* cx) {
return setFlags(cx, js::BaseShape::UNQUALIFIED_VAROBJ);
}
// An "unqualified" varobj is the object on which "unqualified"
// assignments (i.e., bareword assignments for which the LHS does not
// exist on the scope chain) are kept.
inline bool isUnqualifiedVarObj() const;
/*
* Objects with an uncacheable proto can have their prototype mutated

View File

@ -220,24 +220,25 @@ js::DeleteElement(JSContext* cx, HandleObject obj, uint32_t index, ObjectOpResul
/* * */
inline bool
JSObject::isQualifiedVarObj()
JSObject::isQualifiedVarObj() const
{
if (is<js::DebugScopeObject>())
return as<js::DebugScopeObject>().scope().isQualifiedVarObj();
// TODO: We would like to assert that only GlobalObject or
// NonSyntacticVariables object is a qualified varobj, but users of
// js::Execute still need to be vetted. See bug 1171177.
return hasAllFlags(js::BaseShape::QUALIFIED_VAROBJ);
bool rv = hasAllFlags(js::BaseShape::QUALIFIED_VAROBJ);
MOZ_ASSERT_IF(rv,
is<js::GlobalObject>() ||
is<js::CallObject>() ||
is<js::NonSyntacticVariablesObject>() ||
(is<js::DynamicWithObject>() && !as<js::DynamicWithObject>().isSyntactic()));
return rv;
}
inline bool
JSObject::isUnqualifiedVarObj()
JSObject::isUnqualifiedVarObj() const
{
if (is<js::DebugScopeObject>())
return as<js::DebugScopeObject>().scope().isUnqualifiedVarObj();
bool rv = hasAllFlags(js::BaseShape::UNQUALIFIED_VAROBJ);
MOZ_ASSERT_IF(rv, is<js::GlobalObject>() || is<js::NonSyntacticVariablesObject>());
return rv;
return is<js::GlobalObject>() || is<js::NonSyntacticVariablesObject>();
}
namespace js {

View File

@ -247,6 +247,7 @@ GlobalObject::createInternal(JSContext* cx, const Class* clasp)
return nullptr;
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
MOZ_ASSERT(global->isUnqualifiedVarObj());
// Initialize the private slot to null if present, as GC can call class
// hooks before the caller gets to set this to a non-garbage value.
@ -257,8 +258,6 @@ GlobalObject::createInternal(JSContext* cx, const Class* clasp)
if (!global->setQualifiedVarObj(cx))
return nullptr;
if (!global->setUnqualifiedVarObj(cx))
return nullptr;
if (!global->setDelegate(cx))
return nullptr;

View File

@ -579,12 +579,10 @@ NonSyntacticVariablesObject::create(JSContext* cx, Handle<GlobalObject*> global)
if (!obj)
return nullptr;
MOZ_ASSERT(obj->isUnqualifiedVarObj());
if (!obj->setQualifiedVarObj(cx))
return nullptr;
if (!obj->setUnqualifiedVarObj(cx))
return nullptr;
obj->setEnclosingScope(global);
return obj;
}

View File

@ -353,16 +353,10 @@ class BaseShape : public gc::TenuredCell
UNCACHEABLE_PROTO = 0x800,
IMMUTABLE_PROTOTYPE = 0x1000,
// These two flags control which scope a new variables ends up on in the
// scope chain. If the variable is "qualified" (i.e., if it was defined
// using var, let, or const) then it ends up on the lowest scope in the
// chain that has the QUALIFIED_VAROBJ flag set. If it's "unqualified"
// (i.e., if it was introduced without any var, let, or const, which
// incidentally is an error in strict mode) then it goes on the lowest
// scope in the chain with the UNQUALIFIED_VAROBJ flag set (which is
// typically the global).
// See JSObject::isQualifiedVarObj().
QUALIFIED_VAROBJ = 0x2000,
UNQUALIFIED_VAROBJ = 0x4000,
// 0x4000 is unused.
// For a function used as an interpreted constructor, whether a 'new'
// type had constructor information cleared.