Bug 960109 - convert JSJitInfo fields to bitfields; r=bz,efaust

This commit is contained in:
Nathan Froyd 2014-01-16 16:30:35 -05:00
Родитель 29bd66584a
Коммит a04f403342
6 изменённых файлов: 102 добавлений и 53 удалений

Просмотреть файл

@ -5905,7 +5905,7 @@ class CGGenericMethod(CGAbstractBindingMethod):
def generate_code(self):
return CGIndenter(CGGeneric(
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
"MOZ_ASSERT(info->type == JSJitInfo::Method);\n"
"MOZ_ASSERT(info->type() == JSJitInfo::Method);\n"
"JSJitMethodOp method = info->method;\n"
"return method(cx, obj, self, JSJitMethodCallArgs(args));"))
@ -6110,7 +6110,7 @@ class CGGenericGetter(CGAbstractBindingMethod):
def generate_code(self):
return CGIndenter(CGGeneric(
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
"MOZ_ASSERT(info->type == JSJitInfo::Getter);\n"
"MOZ_ASSERT(info->type() == JSJitInfo::Getter);\n"
"JSJitGetterOp getter = info->getter;\n"
"return getter(cx, obj, self, JSJitGetterCallArgs(args));"))
@ -6226,7 +6226,7 @@ class CGGenericSetter(CGAbstractBindingMethod):
' return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "%s attribute setter");\n'
"}\n"
"const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
"MOZ_ASSERT(info->type == JSJitInfo::Setter);\n"
"MOZ_ASSERT(info->type() == JSJitInfo::Setter);\n"
"JSJitSetterOp setter = info->setter;\n"
"if (!setter(cx, obj, self, JSJitSetterCallArgs(args))) {\n"
" return false;\n"
@ -6357,16 +6357,16 @@ class CGMemberJITInfo(CGThing):
" %s,\n"
" %s,\n"
" JSJitInfo::%s,\n"
" JSJitInfo::%s, /* aliasSet. Not relevant for setters. */\n"
" %s, /* returnType. Not relevant for setters. */\n"
" %s, /* isInfallible. False in setters. */\n"
" %s, /* isMovable. Not relevant for setters. */\n"
" %s, /* isInSlot. Only relevant for getters. */\n"
" %s, /* isTypedMethod. Only relevant for methods. */\n"
" %s, /* Reserved slot index, if we're stored in a slot, else 0. */\n"
" JSJitInfo::%s /* aliasSet. Not relevant for setters. */\n"
"}" % (opName, protoID, depth, opType,
" %s /* Reserved slot index, if we're stored in a slot, else 0. */\n"
"}" % (opName, protoID, depth, opType, aliasSet,
returnType, failstr, movablestr, slotStr,
typedMethodStr, slotIndex, aliasSet))
typedMethodStr, slotIndex))
if args is not None:
argTypes = "%s_argTypes" % infoName
args = [CGMemberJITInfo.getJSArgType(arg.type) for arg in args]

Просмотреть файл

@ -5092,7 +5092,7 @@ IonBuilder::testShouldDOMCall(types::TypeSet *inTypes,
compartment->runtime()->DOMcallbacks()->instanceClassMatchesProto;
const JSJitInfo *jinfo = func->jitInfo();
if (jinfo->type != opType)
if (jinfo->type() != opType)
return false;
for (unsigned i = 0; i < inTypes->getObjectCount(); i++) {
@ -5243,16 +5243,16 @@ DOMCallNeedsBarrier(const JSJitInfo* jitinfo, types::TemporaryTypeSet *types)
{
// If the return type of our DOM native is in "types" already, we don't
// actually need a barrier.
if (jitinfo->returnType == JSVAL_TYPE_UNKNOWN)
if (jitinfo->returnType() == JSVAL_TYPE_UNKNOWN)
return true;
// JSVAL_TYPE_OBJECT doesn't tell us much; we still have to barrier on the
// actual type of the object.
if (jitinfo->returnType == JSVAL_TYPE_OBJECT)
if (jitinfo->returnType() == JSVAL_TYPE_OBJECT)
return true;
// No need for a barrier if we're already expecting the type we'll produce.
return jitinfo->returnType != types->getKnownTypeTag();
return jitinfo->returnType() != types->getKnownTypeTag();
}
bool
@ -6225,12 +6225,12 @@ IonBuilder::pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *obser
// JSValueType than codegen can, short of jitinfo->returnType just being
// JSVAL_TYPE_UNKNOWN.
MDefinition* replace = ins;
if (jitinfo->returnType != JSVAL_TYPE_DOUBLE ||
if (jitinfo->returnType() != JSVAL_TYPE_DOUBLE ||
observed->getKnownTypeTag() != JSVAL_TYPE_INT32) {
JS_ASSERT(jitinfo->returnType == JSVAL_TYPE_UNKNOWN ||
JS_ASSERT(jitinfo->returnType() == JSVAL_TYPE_UNKNOWN ||
observed->getKnownTypeTag() == JSVAL_TYPE_UNKNOWN ||
jitinfo->returnType == observed->getKnownTypeTag());
replace = ensureDefiniteType(ins, jitinfo->returnType);
jitinfo->returnType() == observed->getKnownTypeTag());
replace = ensureDefiniteType(ins, jitinfo->returnType());
if (replace != ins) {
current->pop();
current->push(replace);
@ -8835,7 +8835,7 @@ IonBuilder::setPropTryCommonDOMSetter(bool *emitted, MDefinition *obj,
return true;
// Emit SetDOMProperty.
JS_ASSERT(setter->jitInfo()->type == JSJitInfo::Setter);
JS_ASSERT(setter->jitInfo()->type() == JSJitInfo::Setter);
MSetDOMProperty *set = MSetDOMProperty::New(alloc(), setter->jitInfo()->setter, obj, value);
current->add(set);

Просмотреть файл

@ -671,11 +671,11 @@ MCallDOMNative::getAliasSet() const
const JSJitInfo *jitInfo = getSingleTarget()->jitInfo();
JS_ASSERT(jitInfo);
JS_ASSERT(jitInfo->aliasSet != JSJitInfo::AliasNone);
JS_ASSERT(jitInfo->aliasSet() != JSJitInfo::AliasNone);
// If we don't know anything about the types of our arguments, we have to
// assume that type-coercions can have side-effects, so we need to alias
// everything.
if (jitInfo->aliasSet != JSJitInfo::AliasDOMSets || !jitInfo->isTypedMethodJitInfo())
if (jitInfo->aliasSet() != JSJitInfo::AliasDOMSets || !jitInfo->isTypedMethodJitInfo())
return AliasSet::Store(AliasSet::Any);
uint32_t argIndex = 0;
@ -723,7 +723,7 @@ MCallDOMNative::computeMovable()
JS_ASSERT(jitInfo);
JS_ASSERT_IF(jitInfo->isMovable,
jitInfo->aliasSet != JSJitInfo::AliasEverything);
jitInfo->aliasSet() != JSJitInfo::AliasEverything);
if (jitInfo->isMovable && !isEffectful())
setMovable();

Просмотреть файл

@ -7918,7 +7918,7 @@ class MGetDOMProperty
: info_(jitinfo)
{
JS_ASSERT(jitinfo);
JS_ASSERT(jitinfo->type == JSJitInfo::Getter);
JS_ASSERT(jitinfo->type() == JSJitInfo::Getter);
setOperand(0, obj);
@ -7927,7 +7927,7 @@ class MGetDOMProperty
// We are movable iff the jitinfo says we can be.
if (isDomMovable()) {
JS_ASSERT(jitinfo->aliasSet != JSJitInfo::AliasEverything);
JS_ASSERT(jitinfo->aliasSet() != JSJitInfo::AliasEverything);
setMovable();
}
@ -7957,7 +7957,7 @@ class MGetDOMProperty
return info_->isMovable;
}
JSJitInfo::AliasSet domAliasSet() const {
return info_->aliasSet;
return info_->aliasSet();
}
size_t domMemberSlotIndex() const {
MOZ_ASSERT(info_->isInSlot);

Просмотреть файл

@ -1448,11 +1448,13 @@ typedef bool
void *specializedThis, const JSJitMethodCallArgs& args);
struct JSJitInfo {
enum OpType MOZ_ENUM_TYPE(uint8_t) {
enum OpType {
Getter,
Setter,
Method,
ParallelNative
ParallelNative,
// Must be last
OpTypeCount
};
enum ArgType {
@ -1476,7 +1478,7 @@ struct JSJitInfo {
ArgTypeListEnd = (1 << 31)
};
enum AliasSet MOZ_ENUM_TYPE(uint8_t) {
enum AliasSet {
// An enum that describes what this getter/setter/method aliases. This
// determines what things can be hoisted past this call, and if this
// call is movable what it can be hoisted past.
@ -1491,17 +1493,20 @@ struct JSJitInfo {
// Alias the world. Calling this can change arbitrary values anywhere
// in the system. Most things fall in this bucket.
AliasEverything
AliasEverything,
// Must be last.
AliasSetCount
};
bool hasParallelNative() const
{
return type == ParallelNative;
return type() == ParallelNative;
}
bool isDOMJitInfo() const
{
return type != ParallelNative;
return type() != ParallelNative;
}
bool isTypedMethodJitInfo() const
@ -1509,6 +1514,21 @@ struct JSJitInfo {
return isTypedMethod;
}
OpType type() const
{
return OpType(type_);
}
AliasSet aliasSet() const
{
return AliasSet(aliasSet_);
}
JSValueType returnType() const
{
return JSValueType(returnType_);
}
union {
JSJitGetterOp getter;
JSJitSetterOp setter;
@ -1519,30 +1539,53 @@ struct JSJitInfo {
uint16_t protoID;
uint16_t depth;
// type not being ParallelNative means this is a DOM method. If you
// change that, come up with a different way of implementing
// These fields are carefully packed to take up 4 bytes. If you need more
// bits for whatever reason, please see if you can steal bits from existing
// fields before adding more members to this structure.
#define JITINFO_OP_TYPE_BITS 4
#define JITINFO_ALIAS_SET_BITS 4
#define JITINFO_RETURN_TYPE_BITS 8
// If this field is not ParallelNative, then this is a DOM method.
// If you change that, come up with a different way of implementing
// isDOMJitInfo().
OpType type;
JSValueType returnType; /* The return type tag. Might be JSVAL_TYPE_UNKNOWN */
uint16_t isInfallible : 1; /* Is op fallible? False in setters. */
uint16_t isMovable : 1; /* Is op movable? To be movable the op must
uint32_t type_ : JITINFO_OP_TYPE_BITS;
// The alias set for this op. This is a _minimal_ alias set; in
// particular for a method it does not include whatever argument
// conversions might do. That's covered by argTypes and runtime
// analysis of the actual argument types being passed in.
uint32_t aliasSet_ : JITINFO_ALIAS_SET_BITS;
// The return type tag. Might be JSVAL_TYPE_UNKNOWN.
uint32_t returnType_ : JITINFO_RETURN_TYPE_BITS;
static_assert(OpTypeCount <= (1 << JITINFO_OP_TYPE_BITS),
"Not enough space for OpType");
static_assert(AliasSetCount <= (1 << JITINFO_ALIAS_SET_BITS),
"Not enough space for AliasSet");
static_assert((sizeof(JSValueType) * 8) <= JITINFO_RETURN_TYPE_BITS,
"Not enough space for JSValueType");
#undef JITINFO_RETURN_TYPE_BITS
#undef JITINFO_ALIAS_SET_BITS
#undef JITINFO_OP_TYPE_BITS
uint32_t isInfallible : 1; /* Is op fallible? False in setters. */
uint32_t isMovable : 1; /* Is op movable? To be movable the op must
not AliasEverything, but even that might
not be enough (e.g. in cases when it can
throw). */
// XXXbz should we have a JSValueType for the type of the member?
uint16_t isInSlot : 1; /* True if this is a getter that can get a member
uint32_t isInSlot : 1; /* True if this is a getter that can get a member
from a slot of the "this" object directly. */
uint16_t isTypedMethod : 1; /* True if this is an instance of
uint32_t isTypedMethod : 1; /* True if this is an instance of
JSTypedMethodJitInfo. */
uint16_t slotIndex : 12; /* If isInSlot is true, the index of the slot to
uint32_t slotIndex : 12; /* If isInSlot is true, the index of the slot to
get the value from. Otherwise 0. */
AliasSet aliasSet; /* The alias set for this op. This is a _minimal_
alias set; in particular for a method it does not
include whatever argument conversions might do.
That's covered by argTypes and runtime analysis
of the actual argument types being passed in. */
private:
static void staticAsserts()
{
@ -1555,6 +1598,12 @@ private:
}
};
static_assert(sizeof(JSJitInfo) == (sizeof(void*) + 2 * sizeof(uint32_t)),
"There are several thousand instances of JSJitInfo stored in "
"a binary. Please don't increase its space requirements without "
"verifying that there is no other way forward (better packing, "
"smaller datatypes for fields, subclassing, etc.).");
struct JSTypedMethodJitInfo
{
// We use C-style inheritance here, rather than C++ style inheritance
@ -1604,7 +1653,7 @@ inline int CheckIsParallelNative(JSParallelNative parallelNative);
*/
#define JS_JITINFO_NATIVE_PARALLEL(infoName, parallelOp) \
const JSJitInfo infoName = \
{{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSVAL_TYPE_MISSING,false,false,false,false,0,JSJitInfo::AliasEverything}
{{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSJitInfo::AliasEverything,JSVAL_TYPE_MISSING,false,false,false,false,0}
#define JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(infoName, wrapperName, serialOp) \
bool wrapperName##_ParallelNativeThreadSafeWrapper(js::ForkJoinSlice *slice, unsigned argc, \

Просмотреть файл

@ -4833,14 +4833,14 @@ static const JSJitInfo dom_x_getterinfo = {
{ (JSJitGetterOp)dom_get_x },
0, /* protoID */
0, /* depth */
JSJitInfo::AliasNone, /* aliasSet */
JSJitInfo::Getter,
JSVAL_TYPE_UNKNOWN, /* returnType */
true, /* isInfallible. False in setters. */
true, /* isMovable */
false, /* isInSlot */
false, /* isTypedMethod */
0, /* slotIndex */
JSJitInfo::AliasNone /* aliasSet */
0 /* slotIndex */
};
static const JSJitInfo dom_x_setterinfo = {
@ -4848,13 +4848,13 @@ static const JSJitInfo dom_x_setterinfo = {
0, /* protoID */
0, /* depth */
JSJitInfo::Setter,
JSJitInfo::AliasEverything, /* aliasSet */
JSVAL_TYPE_UNKNOWN, /* returnType */
false, /* isInfallible. False in setters. */
false, /* isMovable. */
false, /* isInSlot */
false, /* isTypedMethod */
0, /* slotIndex */
JSJitInfo::AliasEverything /* aliasSet */
0 /* slotIndex */
};
static const JSJitInfo doFoo_methodinfo = {
@ -4862,13 +4862,13 @@ static const JSJitInfo doFoo_methodinfo = {
0, /* protoID */
0, /* depth */
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet */
JSVAL_TYPE_UNKNOWN, /* returnType */
false, /* isInfallible. False in setters. */
false, /* isMovable */
false, /* isInSlot */
false, /* isTypedMethod */
0, /* slotIndex */
JSJitInfo::AliasEverything /* aliasSet */
0 /* slotIndex */
};
static const JSPropertySpec dom_props[] = {
@ -4925,7 +4925,7 @@ dom_genericGetter(JSContext *cx, unsigned argc, JS::Value *vp)
JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
MOZ_ASSERT(info->type == JSJitInfo::Getter);
MOZ_ASSERT(info->type() == JSJitInfo::Getter);
JSJitGetterOp getter = info->getter;
return getter(cx, obj, val.toPrivate(), JSJitGetterCallArgs(args));
}
@ -4948,7 +4948,7 @@ dom_genericSetter(JSContext* cx, unsigned argc, JS::Value* vp)
JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
MOZ_ASSERT(info->type == JSJitInfo::Setter);
MOZ_ASSERT(info->type() == JSJitInfo::Setter);
JSJitSetterOp setter = info->setter;
if (!setter(cx, obj, val.toPrivate(), JSJitSetterCallArgs(args)))
return false;
@ -4972,7 +4972,7 @@ dom_genericMethod(JSContext* cx, unsigned argc, JS::Value *vp)
JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
MOZ_ASSERT(info->type == JSJitInfo::Method);
MOZ_ASSERT(info->type() == JSJitInfo::Method);
JSJitMethodOp method = info->method;
return method(cx, obj, val.toPrivate(), JSJitMethodCallArgs(args));
}