mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-07 20:17:37 +00:00
Bug 996422 - Part 1: Make TypeSets work with MIRTypes directly. (r=bhackett)
This commit is contained in:
parent
95a78e55c8
commit
0529a14819
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user