зеркало из https://github.com/mozilla/gecko-dev.git
Bug 960109 - convert JSJitInfo fields to bitfields; r=bz,efaust
This commit is contained in:
Родитель
29bd66584a
Коммит
a04f403342
|
@ -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));
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче