Bug 996422 - Part 1: Make TypeSets work with MIRTypes directly. (r=bhackett)

This commit is contained in:
Shu-yu Guo 2014-04-22 18:23:27 -07:00
parent 95a78e55c8
commit 0529a14819
7 changed files with 118 additions and 103 deletions

View File

@ -477,7 +477,7 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock *entry, jsbytecode *start, jsbytecod
if (js_CodeSpec[*last].format & JOF_TYPESET) { if (js_CodeSpec[*last].format & JOF_TYPESET) {
types::TemporaryTypeSet *typeSet = bytecodeTypes(last); types::TemporaryTypeSet *typeSet = bytecodeTypes(last);
if (!typeSet->empty()) { if (!typeSet->empty()) {
MIRType type = MIRTypeFromValueType(typeSet->getKnownTypeTag()); MIRType type = typeSet->getKnownMIRType();
if (!phi->addBackedgeType(type, typeSet)) if (!phi->addBackedgeType(type, typeSet))
return false; return false;
} }
@ -889,9 +889,7 @@ IonBuilder::rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIn
JS_ASSERT(param->isParameter() || param->isGetArgumentsObjectArg()); JS_ASSERT(param->isParameter() || param->isGetArgumentsObjectArg());
types::TemporaryTypeSet *types = param->resultTypeSet(); types::TemporaryTypeSet *types = param->resultTypeSet();
JSValueType definiteType = types->getKnownTypeTag(); MDefinition *actual = ensureDefiniteType(param, types->getKnownMIRType());
MDefinition *actual = ensureDefiniteType(param, definiteType);
if (actual == param) if (actual == param)
return; return;
@ -5194,7 +5192,7 @@ ArgumentTypesMatch(MDefinition *def, types::StackTypeSet *calleeTypes)
if (def->type() == MIRType_Object) if (def->type() == MIRType_Object)
return calleeTypes->unknownObject(); return calleeTypes->unknownObject();
return calleeTypes->mightBeType(ValueTypeFromMIRType(def->type())); return calleeTypes->mightBeMIRType(def->type());
} }
bool bool
@ -5219,7 +5217,7 @@ IonBuilder::testNeedsArgumentCheck(JSFunction *target, CallInfo &callInfo)
return true; return true;
} }
for (size_t i = callInfo.argc(); i < target->nargs(); i++) { for (size_t i = callInfo.argc(); i < target->nargs(); i++) {
if (!types::TypeScript::ArgTypes(targetScript, i)->mightBeType(JSVAL_TYPE_UNDEFINED)) if (!types::TypeScript::ArgTypes(targetScript, i)->mightBeMIRType(MIRType_Undefined))
return true; return true;
} }
@ -5320,7 +5318,7 @@ DOMCallNeedsBarrier(const JSJitInfo* jitinfo, types::TemporaryTypeSet *types)
return true; return true;
// No need for a barrier if we're already expecting the type we'll produce. // No need for a barrier if we're already expecting the type we'll produce.
return jitinfo->returnType() != types->getKnownTypeTag(); return MIRTypeFromValueType(jitinfo->returnType()) != types->getKnownMIRType();
} }
bool bool
@ -5373,8 +5371,8 @@ IonBuilder::jsop_eval(uint32_t argc)
// same. This is not guaranteed if a primitive string/number/etc. // same. This is not guaranteed if a primitive string/number/etc.
// is passed through to the eval invoke as the primitive may be // is passed through to the eval invoke as the primitive may be
// boxed into different objects if accessed via 'this'. // boxed into different objects if accessed via 'this'.
JSValueType type = thisTypes->getKnownTypeTag(); MIRType type = thisTypes->getKnownMIRType();
if (type != JSVAL_TYPE_OBJECT && type != JSVAL_TYPE_NULL && type != JSVAL_TYPE_UNDEFINED) if (type != MIRType_Object && type != MIRType_Null && type != MIRType_Undefined)
return abort("Direct eval from script with maybe-primitive 'this'"); return abort("Direct eval from script with maybe-primitive 'this'");
CallInfo callInfo(alloc(), /* constructing = */ false); CallInfo callInfo(alloc(), /* constructing = */ false);
@ -5958,7 +5956,7 @@ IonBuilder::newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool
alloc_->lifoAlloc()->new_<types::TemporaryTypeSet>(existingType); alloc_->lifoAlloc()->new_<types::TemporaryTypeSet>(existingType);
if (!typeSet) if (!typeSet)
return nullptr; return nullptr;
MIRType type = MIRTypeFromValueType(typeSet->getKnownTypeTag()); MIRType type = typeSet->getKnownMIRType();
if (!phi->addBackedgeType(type, typeSet)) if (!phi->addBackedgeType(type, typeSet))
return nullptr; return nullptr;
} }
@ -6259,8 +6257,7 @@ IonBuilder::pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed,
// to that point will explicitly monitor the new type. // to that point will explicitly monitor the new type.
if (!needsBarrier) { if (!needsBarrier) {
JSValueType type = observed->getKnownTypeTag(); MDefinition *replace = ensureDefiniteType(def, observed->getKnownMIRType());
MDefinition *replace = ensureDefiniteType(def, type);
if (replace != def) { if (replace != def) {
current->pop(); current->pop();
current->push(replace); current->push(replace);
@ -6294,7 +6291,7 @@ IonBuilder::pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *obser
const JSJitInfo *jitinfo = func->jitInfo(); const JSJitInfo *jitinfo = func->jitInfo();
bool barrier = DOMCallNeedsBarrier(jitinfo, observed); bool barrier = DOMCallNeedsBarrier(jitinfo, observed);
// Need to be a bit careful: if jitinfo->returnType is JSVAL_TYPE_DOUBLE but // Need to be a bit careful: if jitinfo->returnType is JSVAL_TYPE_DOUBLE but
// types->getKnownTypeTag() is JSVAL_TYPE_INT32, then don't unconditionally // types->getKnownMIRType() is MIRType_Int32, then don't unconditionally
// unbox as a double. Instead, go ahead and barrier on having an int type, // unbox as a double. Instead, go ahead and barrier on having an int type,
// since we know we need a barrier anyway due to the type mismatch. This is // since we know we need a barrier anyway due to the type mismatch. This is
// the only situation in which TI actually has more information about the // the only situation in which TI actually has more information about the
@ -6302,11 +6299,11 @@ IonBuilder::pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *obser
// JSVAL_TYPE_UNKNOWN. // JSVAL_TYPE_UNKNOWN.
MDefinition* replace = ins; MDefinition* replace = ins;
if (jitinfo->returnType() != JSVAL_TYPE_DOUBLE || if (jitinfo->returnType() != JSVAL_TYPE_DOUBLE ||
observed->getKnownTypeTag() != JSVAL_TYPE_INT32) { observed->getKnownMIRType() != MIRType_Int32) {
JS_ASSERT(jitinfo->returnType() == JSVAL_TYPE_UNKNOWN || JS_ASSERT(jitinfo->returnType() == JSVAL_TYPE_UNKNOWN ||
observed->getKnownTypeTag() == JSVAL_TYPE_UNKNOWN || observed->getKnownMIRType() == MIRType_Value ||
jitinfo->returnType() == observed->getKnownTypeTag()); MIRTypeFromValueType(jitinfo->returnType()) == observed->getKnownMIRType());
replace = ensureDefiniteType(ins, jitinfo->returnType()); replace = ensureDefiniteType(ins, MIRTypeFromValueType(jitinfo->returnType()));
if (replace != ins) { if (replace != ins) {
current->pop(); current->pop();
current->push(replace); current->push(replace);
@ -6319,30 +6316,29 @@ IonBuilder::pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *obser
} }
MDefinition * MDefinition *
IonBuilder::ensureDefiniteType(MDefinition *def, JSValueType definiteType) IonBuilder::ensureDefiniteType(MDefinition *def, MIRType definiteType)
{ {
MInstruction *replace; MInstruction *replace;
switch (definiteType) { switch (definiteType) {
case JSVAL_TYPE_UNDEFINED: case MIRType_Undefined:
def->setImplicitlyUsedUnchecked(); def->setImplicitlyUsedUnchecked();
replace = MConstant::New(alloc(), UndefinedValue()); replace = MConstant::New(alloc(), UndefinedValue());
break; break;
case JSVAL_TYPE_NULL: case MIRType_Null:
def->setImplicitlyUsedUnchecked(); def->setImplicitlyUsedUnchecked();
replace = MConstant::New(alloc(), NullValue()); replace = MConstant::New(alloc(), NullValue());
break; break;
case JSVAL_TYPE_UNKNOWN: case MIRType_Value:
return def; return def;
default: { default: {
MIRType replaceType = MIRTypeFromValueType(definiteType);
if (def->type() != MIRType_Value) { if (def->type() != MIRType_Value) {
JS_ASSERT(def->type() == replaceType); JS_ASSERT(def->type() == definiteType);
return def; return def;
} }
replace = MUnbox::New(alloc(), def, replaceType, MUnbox::Infallible); replace = MUnbox::New(alloc(), def, definiteType, MUnbox::Infallible);
break; break;
} }
} }
@ -6359,7 +6355,7 @@ IonBuilder::ensureDefiniteTypeSet(MDefinition *def, types::TemporaryTypeSet *typ
// Use ensureDefiniteType to do unboxing. If that happened the type can // Use ensureDefiniteType to do unboxing. If that happened the type can
// be added on the newly created unbox operation. // be added on the newly created unbox operation.
MDefinition *replace = ensureDefiniteType(def, types->getKnownTypeTag()); MDefinition *replace = ensureDefiniteType(def, types->getKnownMIRType());
if (replace != def) { if (replace != def) {
replace->setResultTypeSet(types); replace->setResultTypeSet(types);
return replace; return replace;
@ -6428,22 +6424,22 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc
JSObject *singleton = types->getSingleton(); JSObject *singleton = types->getSingleton();
JSValueType knownType = types->getKnownTypeTag(); MIRType knownType = types->getKnownMIRType();
if (!barrier) { if (!barrier) {
if (singleton) { if (singleton) {
// Try to inline a known constant value. // Try to inline a known constant value.
if (testSingletonProperty(staticObject, name) == singleton) if (testSingletonProperty(staticObject, name) == singleton)
return pushConstant(ObjectValue(*singleton)); return pushConstant(ObjectValue(*singleton));
} }
if (knownType == JSVAL_TYPE_UNDEFINED) if (knownType == MIRType_Undefined)
return pushConstant(UndefinedValue()); return pushConstant(UndefinedValue());
if (knownType == JSVAL_TYPE_NULL) if (knownType == MIRType_Null)
return pushConstant(NullValue()); return pushConstant(NullValue());
} }
MInstruction *obj = constant(ObjectValue(*staticObject)); MInstruction *obj = constant(ObjectValue(*staticObject));
MIRType rvalType = MIRTypeFromValueType(types->getKnownTypeTag()); MIRType rvalType = types->getKnownMIRType();
if (barrier) if (barrier)
rvalType = MIRType_Value; rvalType = MIRType_Value;
@ -6526,9 +6522,9 @@ IonBuilder::setStaticName(JSObject *staticObject, PropertyName *name)
// If the property has a known type, we may be able to optimize typed stores by not // If the property has a known type, we may be able to optimize typed stores by not
// storing the type tag. // storing the type tag.
MIRType slotType = MIRType_None; MIRType slotType = MIRType_None;
JSValueType knownType = property.knownTypeTag(constraints()); MIRType knownType = property.knownMIRType(constraints());
if (knownType != JSVAL_TYPE_UNKNOWN) if (knownType != MIRType_Value)
slotType = MIRTypeFromValueType(knownType); slotType = knownType;
bool needsBarrier = property.needsBarrier(constraints()); bool needsBarrier = property.needsBarrier(constraints());
return storeSlot(obj, property.maybeTypes()->definiteSlot(), NumFixedSlots(staticObject), return storeSlot(obj, property.maybeTypes()->definiteSlot(), NumFixedSlots(staticObject),
@ -6593,11 +6589,10 @@ bool
IonBuilder::jsop_intrinsic(PropertyName *name) IonBuilder::jsop_intrinsic(PropertyName *name)
{ {
types::TemporaryTypeSet *types = bytecodeTypes(pc); types::TemporaryTypeSet *types = bytecodeTypes(pc);
JSValueType type = types->getKnownTypeTag();
// If we haven't executed this opcode yet, we need to get the intrinsic // If we haven't executed this opcode yet, we need to get the intrinsic
// value and monitor the result. // value and monitor the result.
if (type == JSVAL_TYPE_UNKNOWN) { if (types->empty()) {
MCallGetIntrinsicValue *ins = MCallGetIntrinsicValue::New(alloc(), name); MCallGetIntrinsicValue *ins = MCallGetIntrinsicValue::New(alloc(), name);
current->add(ins); current->add(ins);
@ -6632,23 +6627,23 @@ IonBuilder::jsop_bindname(PropertyName *name)
return resumeAfter(ins); return resumeAfter(ins);
} }
static JSValueType static MIRType
GetElemKnownType(bool needsHoleCheck, types::TemporaryTypeSet *types) GetElemKnownType(bool needsHoleCheck, types::TemporaryTypeSet *types)
{ {
JSValueType knownType = types->getKnownTypeTag(); MIRType knownType = types->getKnownMIRType();
// Null and undefined have no payload so they can't be specialized. // Null and undefined have no payload so they can't be specialized.
// Since folding null/undefined while building SSA is not safe (see the // Since folding null/undefined while building SSA is not safe (see the
// comment in IsPhiObservable), we just add an untyped load instruction // comment in IsPhiObservable), we just add an untyped load instruction
// and rely on pushTypeBarrier and DCE to replace it with a null/undefined // and rely on pushTypeBarrier and DCE to replace it with a null/undefined
// constant. // constant.
if (knownType == JSVAL_TYPE_UNDEFINED || knownType == JSVAL_TYPE_NULL) if (knownType == MIRType_Undefined || knownType == MIRType_Null)
knownType = JSVAL_TYPE_UNKNOWN; knownType = MIRType_Value;
// Different architectures may want typed element reads which require // Different architectures may want typed element reads which require
// hole checks to be done as either value or typed reads. // hole checks to be done as either value or typed reads.
if (needsHoleCheck && !LIRGenerator::allowTypedElementHoleCheck()) if (needsHoleCheck && !LIRGenerator::allowTypedElementHoleCheck())
knownType = JSVAL_TYPE_UNKNOWN; knownType = MIRType_Value;
return knownType; return knownType;
} }
@ -7237,10 +7232,10 @@ IonBuilder::getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index)
// Spice up type information. // Spice up type information.
if (index->type() == MIRType_Int32 && !barrier) { if (index->type() == MIRType_Int32 && !barrier) {
bool needHoleCheck = !ElementAccessIsPacked(constraints(), obj); bool needHoleCheck = !ElementAccessIsPacked(constraints(), obj);
JSValueType knownType = GetElemKnownType(needHoleCheck, types); MIRType knownType = GetElemKnownType(needHoleCheck, types);
if (knownType != JSVAL_TYPE_UNKNOWN && knownType != JSVAL_TYPE_DOUBLE) if (knownType != MIRType_Value && knownType != MIRType_Double)
ins->setResultType(MIRTypeFromValueType(knownType)); ins->setResultType(knownType);
} }
if (!pushTypeBarrier(ins, types, barrier)) if (!pushTypeBarrier(ins, types, barrier))
@ -7272,7 +7267,7 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
types->hasType(types::Type::UndefinedType()) && types->hasType(types::Type::UndefinedType()) &&
!ElementAccessHasExtraIndexedProperty(constraints(), obj); !ElementAccessHasExtraIndexedProperty(constraints(), obj);
JSValueType knownType = JSVAL_TYPE_UNKNOWN; MIRType knownType = MIRType_Value;
if (!barrier) if (!barrier)
knownType = GetElemKnownType(needsHoleCheck, types); knownType = GetElemKnownType(needsHoleCheck, types);
@ -7305,7 +7300,7 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
loopDepth_ && loopDepth_ &&
!readOutOfBounds && !readOutOfBounds &&
!needsHoleCheck && !needsHoleCheck &&
knownType == JSVAL_TYPE_DOUBLE && knownType == MIRType_Double &&
objTypes && objTypes &&
objTypes->convertDoubleElements(constraints()) == types::TemporaryTypeSet::AlwaysConvertToDoubles; objTypes->convertDoubleElements(constraints()) == types::TemporaryTypeSet::AlwaysConvertToDoubles;
if (loadDouble) if (loadDouble)
@ -7332,7 +7327,7 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
// If maybeUndefined was true, the typeset must have undefined, and // If maybeUndefined was true, the typeset must have undefined, and
// then either additional types or a barrier. This means we should // then either additional types or a barrier. This means we should
// never have a typed version of LoadElementHole. // never have a typed version of LoadElementHole.
JS_ASSERT(knownType == JSVAL_TYPE_UNKNOWN); JS_ASSERT(knownType == MIRType_Value);
} }
// If the array is being converted to doubles, but we've observed // If the array is being converted to doubles, but we've observed
@ -7353,7 +7348,7 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
// cannot *assume* the result is a double. // cannot *assume* the result is a double.
if (executionMode == ParallelExecution && if (executionMode == ParallelExecution &&
barrier && barrier &&
types->getKnownTypeTag() == JSVAL_TYPE_INT32 && types->getKnownMIRType() == MIRType_Int32 &&
objTypes && objTypes &&
objTypes->convertDoubleElements(constraints()) == types::TemporaryTypeSet::AlwaysConvertToDoubles) objTypes->convertDoubleElements(constraints()) == types::TemporaryTypeSet::AlwaysConvertToDoubles)
{ {
@ -7365,8 +7360,8 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
barrier = false; // Don't need a barrier anymore barrier = false; // Don't need a barrier anymore
} }
if (knownType != JSVAL_TYPE_UNKNOWN) if (knownType != MIRType_Value)
load->setResultType(MIRTypeFromValueType(knownType)); load->setResultType(knownType);
current->push(load); current->push(load);
return pushTypeBarrier(load, types, barrier); return pushTypeBarrier(load, types, barrier);
@ -8049,7 +8044,7 @@ IonBuilder::jsop_length_fastPath()
{ {
types::TemporaryTypeSet *types = bytecodeTypes(pc); types::TemporaryTypeSet *types = bytecodeTypes(pc);
if (types->getKnownTypeTag() != JSVAL_TYPE_INT32) if (types->getKnownMIRType() != MIRType_Int32)
return false; return false;
MDefinition *obj = current->peek(-1); MDefinition *obj = current->peek(-1);
@ -8739,7 +8734,7 @@ IonBuilder::getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
MLoadFixedSlot *fixed = MLoadFixedSlot::New(alloc(), useObj, property.maybeTypes()->definiteSlot()); MLoadFixedSlot *fixed = MLoadFixedSlot::New(alloc(), useObj, property.maybeTypes()->definiteSlot());
if (!barrier) if (!barrier)
fixed->setResultType(MIRTypeFromValueType(types->getKnownTypeTag())); fixed->setResultType(types->getKnownMIRType());
current->add(fixed); current->add(fixed);
current->push(fixed); current->push(fixed);
@ -8797,7 +8792,7 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, PropertyName *name,
} }
// Don't call the getter with a primitive value. // Don't call the getter with a primitive value.
if (objTypes->getKnownTypeTag() != JSVAL_TYPE_OBJECT) { if (objTypes->getKnownMIRType() != MIRType_Object) {
MGuardObject *guardObj = MGuardObject::New(alloc(), obj); MGuardObject *guardObj = MGuardObject::New(alloc(), obj);
current->add(guardObj); current->add(guardObj);
obj = guardObj; obj = guardObj;
@ -8873,7 +8868,7 @@ IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name,
if (shapes.empty() || !CanInlinePropertyOpShapes(shapes)) if (shapes.empty() || !CanInlinePropertyOpShapes(shapes))
return true; return true;
MIRType rvalType = MIRTypeFromValueType(types->getKnownTypeTag()); MIRType rvalType = types->getKnownMIRType();
if (barrier || IsNullOrUndefined(rvalType)) if (barrier || IsNullOrUndefined(rvalType))
rvalType = MIRType_Value; rvalType = MIRType_Value;
@ -8975,7 +8970,7 @@ IonBuilder::getPropTryCache(bool *emitted, PropertyName *name,
if (load->isEffectful() && !resumeAfter(load)) if (load->isEffectful() && !resumeAfter(load))
return false; return false;
MIRType rvalType = MIRTypeFromValueType(types->getKnownTypeTag()); MIRType rvalType = types->getKnownMIRType();
if (barrier || IsNullOrUndefined(rvalType)) if (barrier || IsNullOrUndefined(rvalType))
rvalType = MIRType_Value; rvalType = MIRType_Value;
load->setResultType(rvalType); load->setResultType(rvalType);
@ -9084,7 +9079,7 @@ IonBuilder::setPropTryCommonSetter(bool *emitted, MDefinition *obj,
return true; return true;
// Don't call the setter with a primitive value. // Don't call the setter with a primitive value.
if (objTypes->getKnownTypeTag() != JSVAL_TYPE_OBJECT) { if (objTypes->getKnownMIRType() != MIRType_Object) {
MGuardObject *guardObj = MGuardObject::New(alloc(), obj); MGuardObject *guardObj = MGuardObject::New(alloc(), obj);
current->add(guardObj); current->add(guardObj);
obj = guardObj; obj = guardObj;
@ -9584,7 +9579,7 @@ IonBuilder::jsop_this()
return true; return true;
} }
if (thisTypes->getKnownTypeTag() == JSVAL_TYPE_OBJECT || if (thisTypes->getKnownMIRType() == MIRType_Object ||
(thisTypes->empty() && baselineFrame_ && baselineFrame_->thisType.isSomeObject())) (thisTypes->empty() && baselineFrame_ && baselineFrame_->thisType.isSomeObject()))
{ {
// This is safe, because if the entry type of |this| is an object, it // This is safe, because if the entry type of |this| is an object, it
@ -10037,7 +10032,7 @@ IonBuilder::typeSetToTypeDescrSet(types::TemporaryTypeSet *types,
TypeDescrSet *out) TypeDescrSet *out)
{ {
// Extract TypeDescrSet directly if we can // Extract TypeDescrSet directly if we can
if (!types || types->getKnownTypeTag() != JSVAL_TYPE_OBJECT) if (!types || types->getKnownMIRType() != MIRType_Object)
return true; return true;
// And only known objects. // And only known objects.

View File

@ -354,7 +354,7 @@ class IonBuilder : public MIRGenerator
// returns def. Otherwise, returns an MInstruction that has that definite // returns def. Otherwise, returns an MInstruction that has that definite
// type, infallibly unboxing ins as needed. The new instruction will be // type, infallibly unboxing ins as needed. The new instruction will be
// added to |current| in this case. // added to |current| in this case.
MDefinition *ensureDefiniteType(MDefinition* def, JSValueType definiteType); MDefinition *ensureDefiniteType(MDefinition* def, MIRType definiteType);
// Creates a MDefinition based on the given def improved with type as TypeSet. // Creates a MDefinition based on the given def improved with type as TypeSet.
MDefinition *ensureDefiniteTypeSet(MDefinition* def, types::TemporaryTypeSet *types); MDefinition *ensureDefiniteTypeSet(MDefinition* def, types::TemporaryTypeSet *types);

View File

@ -202,7 +202,7 @@ MIRType
IonBuilder::getInlineReturnType() IonBuilder::getInlineReturnType()
{ {
types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet(); types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
return MIRTypeFromValueType(returnTypes->getKnownTypeTag()); return returnTypes->getKnownMIRType();
} }
IonBuilder::InliningStatus IonBuilder::InliningStatus
@ -1537,7 +1537,7 @@ IonBuilder::inlineNewDenseArrayForParallelExecution(CallInfo &callInfo)
// constructed type objects, so we can only perform the inlining if we // constructed type objects, so we can only perform the inlining if we
// already have one of these type objects. // already have one of these type objects.
types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet(); types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
if (returnTypes->getKnownTypeTag() != JSVAL_TYPE_OBJECT) if (returnTypes->getKnownMIRType() != MIRType_Object)
return InliningStatus_NotInlined; return InliningStatus_NotInlined;
if (returnTypes->unknownObject() || returnTypes->getObjectCount() != 1) if (returnTypes->unknownObject() || returnTypes->getObjectCount() != 1)
return InliningStatus_NotInlined; return InliningStatus_NotInlined;

View File

@ -1122,7 +1122,7 @@ MPhi::typeIncludes(MDefinition *def)
return types->isSubset(this->resultTypeSet()); return types->isSubset(this->resultTypeSet());
if (this->type() == MIRType_Value || types->empty()) if (this->type() == MIRType_Value || types->empty())
return true; return true;
return this->type() == MIRTypeFromValueType(types->getKnownTypeTag()); return this->type() == types->getKnownMIRType();
} }
if (def->type() == MIRType_Value) { if (def->type() == MIRType_Value) {
@ -3065,7 +3065,7 @@ jit::DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinit
types::HeapTypeSetKey elementTypes = object->property(JSID_VOID); types::HeapTypeSetKey elementTypes = object->property(JSID_VOID);
MIRType type = MIRTypeFromValueType(elementTypes.knownTypeTag(constraints)); MIRType type = elementTypes.knownMIRType(constraints);
if (type == MIRType_None) if (type == MIRType_None)
return MIRType_None; return MIRType_None;
@ -3342,7 +3342,7 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
JS_ASSERT(!aggregateProperty.empty()); JS_ASSERT(!aggregateProperty.empty());
MIRType propertyType = MIRTypeFromValueType(aggregateProperty.ref().knownTypeTag(constraints)); MIRType propertyType = aggregateProperty.ref().knownMIRType(constraints);
switch (propertyType) { switch (propertyType) {
case MIRType_Boolean: case MIRType_Boolean:
case MIRType_Int32: case MIRType_Int32:

View File

@ -463,7 +463,7 @@ class MDefinition : public MNode
if (MIRType_Value != this->type()) if (MIRType_Value != this->type())
return false; return false;
return !resultTypeSet() || resultTypeSet()->mightBeType(ValueTypeFromMIRType(type)); return !resultTypeSet() || resultTypeSet()->mightBeMIRType(type);
} }
// Float32 specialization operations (see big comment in IonAnalysis before the Float32 // Float32 specialization operations (see big comment in IonAnalysis before the Float32
@ -8988,9 +8988,7 @@ class MFilterTypeSet
: MUnaryInstruction(def) : MUnaryInstruction(def)
{ {
JS_ASSERT(!types->unknown()); JS_ASSERT(!types->unknown());
setResultType(types->getKnownMIRType());
MIRType type = MIRTypeFromValueType(types->getKnownTypeTag());
setResultType(type);
setResultTypeSet(types); setResultTypeSet(types);
} }
@ -9022,9 +9020,7 @@ class MTypeBarrier
: MUnaryInstruction(def) : MUnaryInstruction(def)
{ {
JS_ASSERT(!types->unknown()); JS_ASSERT(!types->unknown());
setResultType(types->getKnownMIRType());
MIRType type = MIRTypeFromValueType(types->getKnownTypeTag());
setResultType(type);
setResultTypeSet(types); setResultTypeSet(types);
setGuard(); setGuard();
@ -9057,7 +9053,7 @@ class MTypeBarrier
bool alwaysBails() const { bool alwaysBails() const {
// If mirtype of input doesn't agree with mirtype of barrier, // If mirtype of input doesn't agree with mirtype of barrier,
// we will definitely bail. // we will definitely bail.
MIRType type = MIRTypeFromValueType(resultTypeSet()->getKnownTypeTag()); MIRType type = resultTypeSet()->getKnownMIRType();
if (type == MIRType_Value) if (type == MIRType_Value)
return false; return false;
if (input()->type() == MIRType_Value) if (input()->type() == MIRType_Value)

View File

@ -310,16 +310,39 @@ TemporaryTypeSet::TemporaryTypeSet(Type type)
} }
} }
static inline TypeFlags
PrimitiveMIRType(jit::MIRType type)
{
switch (type) {
case jit::MIRType_Undefined:
return TYPE_FLAG_UNDEFINED;
case jit::MIRType_Null:
return TYPE_FLAG_NULL;
case jit::MIRType_Boolean:
return TYPE_FLAG_BOOLEAN;
case jit::MIRType_Int32:
return TYPE_FLAG_INT32;
case jit::MIRType_Double:
return TYPE_FLAG_DOUBLE;
case jit::MIRType_String:
return TYPE_FLAG_STRING;
case jit::MIRType_Magic:
return TYPE_FLAG_LAZYARGS;
default:
MOZ_ASSUME_UNREACHABLE("Bad MIR type");
}
}
bool bool
TypeSet::mightBeType(JSValueType type) TypeSet::mightBeMIRType(jit::MIRType type)
{ {
if (unknown()) if (unknown())
return true; return true;
if (type == JSVAL_TYPE_OBJECT) if (type == jit::MIRType_Object)
return unknownObject() || baseObjectCount() != 0; return unknownObject() || baseObjectCount() != 0;
return baseFlags() & PrimitiveTypeFlag(type); return baseFlags() & PrimitiveMIRType(type);
} }
bool bool
@ -1142,41 +1165,41 @@ HeapTypeSetKey::freeze(CompilerConstraintList *constraints)
constraints->add(alloc->new_<T>(alloc, *this, ConstraintDataFreeze())); constraints->add(alloc->new_<T>(alloc, *this, ConstraintDataFreeze()));
} }
static inline JSValueType static inline jit::MIRType
GetValueTypeFromTypeFlags(TypeFlags flags) GetMIRTypeFromTypeFlags(TypeFlags flags)
{ {
switch (flags) { switch (flags) {
case TYPE_FLAG_UNDEFINED: case TYPE_FLAG_UNDEFINED:
return JSVAL_TYPE_UNDEFINED; return jit::MIRType_Undefined;
case TYPE_FLAG_NULL: case TYPE_FLAG_NULL:
return JSVAL_TYPE_NULL; return jit::MIRType_Null;
case TYPE_FLAG_BOOLEAN: case TYPE_FLAG_BOOLEAN:
return JSVAL_TYPE_BOOLEAN; return jit::MIRType_Boolean;
case TYPE_FLAG_INT32: case TYPE_FLAG_INT32:
return JSVAL_TYPE_INT32; return jit::MIRType_Int32;
case (TYPE_FLAG_INT32 | TYPE_FLAG_DOUBLE): case (TYPE_FLAG_INT32 | TYPE_FLAG_DOUBLE):
return JSVAL_TYPE_DOUBLE; return jit::MIRType_Double;
case TYPE_FLAG_STRING: case TYPE_FLAG_STRING:
return JSVAL_TYPE_STRING; return jit::MIRType_String;
case TYPE_FLAG_LAZYARGS: case TYPE_FLAG_LAZYARGS:
return JSVAL_TYPE_MAGIC; return jit::MIRType_Magic;
case TYPE_FLAG_ANYOBJECT: case TYPE_FLAG_ANYOBJECT:
return JSVAL_TYPE_OBJECT; return jit::MIRType_Object;
default: default:
return JSVAL_TYPE_UNKNOWN; return jit::MIRType_Value;
} }
} }
JSValueType jit::MIRType
TemporaryTypeSet::getKnownTypeTag() TemporaryTypeSet::getKnownMIRType()
{ {
TypeFlags flags = baseFlags(); TypeFlags flags = baseFlags();
JSValueType type; jit::MIRType type;
if (baseObjectCount()) if (baseObjectCount())
type = flags ? JSVAL_TYPE_UNKNOWN : JSVAL_TYPE_OBJECT; type = flags ? jit::MIRType_Value : jit::MIRType_Object;
else else
type = GetValueTypeFromTypeFlags(flags); type = GetMIRTypeFromTypeFlags(flags);
/* /*
* If the type set is totally empty then it will be treated as unknown, * If the type set is totally empty then it will be treated as unknown,
@ -1186,28 +1209,28 @@ TemporaryTypeSet::getKnownTypeTag()
* added to the set. * added to the set.
*/ */
DebugOnly<bool> empty = flags == 0 && baseObjectCount() == 0; DebugOnly<bool> empty = flags == 0 && baseObjectCount() == 0;
JS_ASSERT_IF(empty, type == JSVAL_TYPE_UNKNOWN); JS_ASSERT_IF(empty, type == jit::MIRType_Value);
return type; return type;
} }
JSValueType jit::MIRType
HeapTypeSetKey::knownTypeTag(CompilerConstraintList *constraints) HeapTypeSetKey::knownMIRType(CompilerConstraintList *constraints)
{ {
TypeSet *types = maybeTypes(); TypeSet *types = maybeTypes();
if (!types || types->unknown()) if (!types || types->unknown())
return JSVAL_TYPE_UNKNOWN; return jit::MIRType_Value;
TypeFlags flags = types->baseFlags() & ~TYPE_FLAG_ANYOBJECT; TypeFlags flags = types->baseFlags() & ~TYPE_FLAG_ANYOBJECT;
JSValueType type; jit::MIRType type;
if (types->unknownObject() || types->getObjectCount()) if (types->unknownObject() || types->getObjectCount())
type = flags ? JSVAL_TYPE_UNKNOWN : JSVAL_TYPE_OBJECT; type = flags ? jit::MIRType_Value : jit::MIRType_Object;
else else
type = GetValueTypeFromTypeFlags(flags); type = GetMIRTypeFromTypeFlags(flags);
if (type != JSVAL_TYPE_UNKNOWN) if (type != jit::MIRType_Value)
freeze(constraints); freeze(constraints);
/* /*
@ -1217,7 +1240,7 @@ HeapTypeSetKey::knownTypeTag(CompilerConstraintList *constraints)
* that the exact tag is unknown, as it will stay unknown as more types are * that the exact tag is unknown, as it will stay unknown as more types are
* added to the set. * added to the set.
*/ */
JS_ASSERT_IF(types->empty(), type == JSVAL_TYPE_UNKNOWN); JS_ASSERT_IF(types->empty(), type == jit::MIRType_Value);
return type; return type;
} }
@ -1671,7 +1694,7 @@ TemporaryTypeSet::convertDoubleElements(CompilerConstraintList *constraints)
// Only bother with converting known packed arrays whose possible // Only bother with converting known packed arrays whose possible
// element types are int or double. Other arrays require type tests // element types are int or double. Other arrays require type tests
// when elements are accessed regardless of the conversion. // when elements are accessed regardless of the conversion.
if (property.knownTypeTag(constraints) == JSVAL_TYPE_DOUBLE && if (property.knownMIRType(constraints) == jit::MIRType_Double &&
!type->hasFlags(constraints, OBJECT_FLAG_NON_PACKED)) !type->hasFlags(constraints, OBJECT_FLAG_NON_PACKED))
{ {
maybeConvert = true; maybeConvert = true;

View File

@ -20,6 +20,7 @@
#include "ds/LifoAlloc.h" #include "ds/LifoAlloc.h"
#include "gc/Barrier.h" #include "gc/Barrier.h"
#include "gc/Marking.h" #include "gc/Marking.h"
#include "jit/IonTypes.h"
#include "js/Utility.h" #include "js/Utility.h"
#include "js/Vector.h" #include "js/Vector.h"
@ -562,7 +563,7 @@ class TypeSet
} }
/* Whether any values in this set might have the specified type. */ /* Whether any values in this set might have the specified type. */
bool mightBeType(JSValueType type); bool mightBeMIRType(jit::MIRType type);
/* /*
* Get whether this type set is known to be a subset of other. * Get whether this type set is known to be a subset of other.
@ -654,9 +655,9 @@ class TemporaryTypeSet : public TypeSet
*/ */
/* Get any type tag which all values in this set must have. */ /* Get any type tag which all values in this set must have. */
JSValueType getKnownTypeTag(); jit::MIRType getKnownMIRType();
bool isMagicArguments() { return getKnownTypeTag() == JSVAL_TYPE_MAGIC; } bool isMagicArguments() { return getKnownMIRType() == jit::MIRType_Magic; }
/* Whether this value may be an object. */ /* Whether this value may be an object. */
bool maybeObject() { return unknownObject() || baseObjectCount() > 0; } bool maybeObject() { return unknownObject() || baseObjectCount() > 0; }
@ -1403,7 +1404,7 @@ class HeapTypeSetKey
bool instantiate(JSContext *cx); bool instantiate(JSContext *cx);
void freeze(CompilerConstraintList *constraints); void freeze(CompilerConstraintList *constraints);
JSValueType knownTypeTag(CompilerConstraintList *constraints); jit::MIRType knownMIRType(CompilerConstraintList *constraints);
bool nonData(CompilerConstraintList *constraints); bool nonData(CompilerConstraintList *constraints);
bool nonWritable(CompilerConstraintList *constraints); bool nonWritable(CompilerConstraintList *constraints);
bool isOwnProperty(CompilerConstraintList *constraints); bool isOwnProperty(CompilerConstraintList *constraints);