зеркало из https://github.com/mozilla/gecko-dev.git
Bug 909717 - Backout due to orange + style nit orange fix on a CLOSED TREE.
This commit is contained in:
Родитель
823658751f
Коммит
9876afe3fd
|
@ -1312,9 +1312,9 @@ CodeGenerator::visitGuardThreadLocalObject(LGuardThreadLocalObject *lir)
|
|||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitTypeBarrierV(LTypeBarrierV *lir)
|
||||
CodeGenerator::visitTypeBarrier(LTypeBarrier *lir)
|
||||
{
|
||||
ValueOperand operand = ToValue(lir, LTypeBarrierV::Input);
|
||||
ValueOperand operand = ToValue(lir, LTypeBarrier::Input);
|
||||
Register scratch = ToTempUnboxRegister(lir->temp());
|
||||
|
||||
Label matched, miss;
|
||||
|
@ -1326,21 +1326,6 @@ CodeGenerator::visitTypeBarrierV(LTypeBarrierV *lir)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitTypeBarrierO(LTypeBarrierO *lir)
|
||||
{
|
||||
Register obj = ToRegister(lir->object());
|
||||
Register scratch = ToTempUnboxRegister(lir->temp());
|
||||
|
||||
Label matched, miss;
|
||||
masm.guardObjectType(obj, lir->mir()->resultTypeSet(), scratch, &matched, &miss);
|
||||
masm.jump(&miss);
|
||||
if (!bailoutFrom(&miss, lir->snapshot()))
|
||||
return false;
|
||||
masm.bind(&matched);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitMonitorTypes(LMonitorTypes *lir)
|
||||
{
|
||||
|
|
|
@ -91,8 +91,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitElements(LElements *lir);
|
||||
bool visitConvertElementsToDoubles(LConvertElementsToDoubles *lir);
|
||||
bool visitMaybeToDoubleElement(LMaybeToDoubleElement *lir);
|
||||
bool visitTypeBarrierV(LTypeBarrierV *lir);
|
||||
bool visitTypeBarrierO(LTypeBarrierO *lir);
|
||||
bool visitTypeBarrier(LTypeBarrier *lir);
|
||||
bool visitMonitorTypes(LMonitorTypes *lir);
|
||||
bool visitPostWriteBarrierO(LPostWriteBarrierO *lir);
|
||||
bool visitPostWriteBarrierV(LPostWriteBarrierV *lir);
|
||||
|
|
|
@ -86,7 +86,7 @@ jit::EliminateDeadResumePointOperands(MIRGenerator *mir, MIRGraph &graph)
|
|||
// parameter passing might be live. Rewriting uses of these terms
|
||||
// in resume points may affect the interpreter's behavior. Rather
|
||||
// than doing a more sophisticated analysis, just ignore these.
|
||||
if (ins->isUnbox() || ins->isParameter() || ins->isTypeBarrier())
|
||||
if (ins->isUnbox() || ins->isParameter())
|
||||
continue;
|
||||
|
||||
// If the instruction's behavior has been constant folded into a
|
||||
|
@ -1286,13 +1286,7 @@ TryEliminateTypeBarrierFromTest(MTypeBarrier *barrier, bool filtersNull, bool fi
|
|||
// types that have been seen in the first access but not the second.
|
||||
|
||||
// A test 'if (x.f)' filters both null and undefined.
|
||||
|
||||
// Disregard the possible unbox added before the Typebarrier for checking.
|
||||
MDefinition *input = barrier->input();
|
||||
if (input->isUnbox() && input->toUnbox()->mode() == MUnbox::TypeBarrier)
|
||||
input = input->toUnbox()->input();
|
||||
|
||||
if (test->getOperand(0) == input && direction == TRUE_BRANCH) {
|
||||
if (test->getOperand(0) == barrier->input() && direction == TRUE_BRANCH) {
|
||||
*eliminated = true;
|
||||
barrier->replaceAllUsesWith(barrier->input());
|
||||
return;
|
||||
|
@ -1306,7 +1300,7 @@ TryEliminateTypeBarrierFromTest(MTypeBarrier *barrier, bool filtersNull, bool fi
|
|||
|
||||
if (compareType != MCompare::Compare_Undefined && compareType != MCompare::Compare_Null)
|
||||
return;
|
||||
if (compare->getOperand(0) != input)
|
||||
if (compare->getOperand(0) != barrier->input())
|
||||
return;
|
||||
|
||||
JSOp op = compare->jsop();
|
||||
|
@ -1338,13 +1332,6 @@ TryEliminateTypeBarrier(MTypeBarrier *barrier, bool *eliminated)
|
|||
const types::StackTypeSet *barrierTypes = barrier->resultTypeSet();
|
||||
const types::StackTypeSet *inputTypes = barrier->input()->resultTypeSet();
|
||||
|
||||
// Disregard the possible unbox added before the Typebarrier.
|
||||
if (barrier->input()->isUnbox() &&
|
||||
barrier->input()->toUnbox()->mode() == MUnbox::TypeBarrier)
|
||||
{
|
||||
inputTypes = barrier->input()->toUnbox()->input()->resultTypeSet();
|
||||
}
|
||||
|
||||
if (!barrierTypes || !inputTypes)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -930,48 +930,46 @@ IonBuilder::addOsrValueTypeBarrier(uint32_t slot, MInstruction **def_,
|
|||
def = barrier;
|
||||
}
|
||||
|
||||
if (type != def->type()) {
|
||||
switch (type) {
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_String:
|
||||
case MIRType_Object:
|
||||
{
|
||||
MUnbox *unbox = MUnbox::New(def, type, MUnbox::Fallible);
|
||||
osrBlock->insertBefore(osrBlock->lastIns(), unbox);
|
||||
osrBlock->rewriteSlot(slot, unbox);
|
||||
def = unbox;
|
||||
break;
|
||||
}
|
||||
switch (type) {
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_String:
|
||||
case MIRType_Object:
|
||||
{
|
||||
MUnbox *unbox = MUnbox::New(def, type, MUnbox::Fallible);
|
||||
osrBlock->insertBefore(osrBlock->lastIns(), unbox);
|
||||
osrBlock->rewriteSlot(slot, unbox);
|
||||
def = unbox;
|
||||
break;
|
||||
}
|
||||
|
||||
case MIRType_Null:
|
||||
{
|
||||
MConstant *c = MConstant::New(NullValue());
|
||||
osrBlock->insertBefore(osrBlock->lastIns(), c);
|
||||
osrBlock->rewriteSlot(slot, c);
|
||||
def = c;
|
||||
break;
|
||||
}
|
||||
case MIRType_Null:
|
||||
{
|
||||
MConstant *c = MConstant::New(NullValue());
|
||||
osrBlock->insertBefore(osrBlock->lastIns(), c);
|
||||
osrBlock->rewriteSlot(slot, c);
|
||||
def = c;
|
||||
break;
|
||||
}
|
||||
|
||||
case MIRType_Undefined:
|
||||
{
|
||||
MConstant *c = MConstant::New(UndefinedValue());
|
||||
osrBlock->insertBefore(osrBlock->lastIns(), c);
|
||||
osrBlock->rewriteSlot(slot, c);
|
||||
def = c;
|
||||
break;
|
||||
}
|
||||
case MIRType_Undefined:
|
||||
{
|
||||
MConstant *c = MConstant::New(UndefinedValue());
|
||||
osrBlock->insertBefore(osrBlock->lastIns(), c);
|
||||
osrBlock->rewriteSlot(slot, c);
|
||||
def = c;
|
||||
break;
|
||||
}
|
||||
|
||||
case MIRType_Magic:
|
||||
JS_ASSERT(lazyArguments_);
|
||||
osrBlock->rewriteSlot(slot, lazyArguments_);
|
||||
def = lazyArguments_;
|
||||
break;
|
||||
case MIRType_Magic:
|
||||
JS_ASSERT(lazyArguments_);
|
||||
osrBlock->rewriteSlot(slot, lazyArguments_);
|
||||
def = lazyArguments_;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
JS_ASSERT(def == osrBlock->getSlot(slot));
|
||||
|
@ -3756,9 +3754,9 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
|||
if (!types->unknown()) {
|
||||
MTypeBarrier *barrier = MTypeBarrier::New(callInfo.thisArg(), cloneTypeSet(types), Bailout_Normal);
|
||||
current->add(barrier);
|
||||
callInfo.setThis(barrier);
|
||||
// object or missing
|
||||
JS_ASSERT(barrier->type() == MIRType_Object || barrier->type() == MIRType_Value);
|
||||
MUnbox *unbox = MUnbox::New(barrier, MIRType_Object, MUnbox::Infallible);
|
||||
current->add(unbox);
|
||||
callInfo.setThis(unbox);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4044,12 +4042,19 @@ IonBuilder::getInlineableGetPropertyCache(CallInfo &callInfo)
|
|||
}
|
||||
|
||||
// Optimize away the following common pattern:
|
||||
// MTypeBarrier[MIRType_Object] <- MGetPropertyCache
|
||||
if (funcDef->isTypeBarrier()) {
|
||||
MTypeBarrier *barrier = funcDef->toTypeBarrier();
|
||||
if (barrier->hasUses())
|
||||
// MUnbox[MIRType_Object, Infallible] <- MTypeBarrier <- MGetPropertyCache
|
||||
if (funcDef->isUnbox()) {
|
||||
MUnbox *unbox = funcDef->toUnbox();
|
||||
if (unbox->mode() != MUnbox::Infallible)
|
||||
return NULL;
|
||||
if (barrier->type() != MIRType_Object)
|
||||
if (unbox->hasUses())
|
||||
return NULL;
|
||||
if (!unbox->input()->isTypeBarrier())
|
||||
return NULL;
|
||||
|
||||
MTypeBarrier *barrier = unbox->input()->toTypeBarrier();
|
||||
// Test if usecount() > 1
|
||||
if (!barrier->hasOneUse())
|
||||
return NULL;
|
||||
if (!barrier->input()->isGetPropertyCache())
|
||||
return NULL;
|
||||
|
@ -4163,16 +4168,16 @@ IonBuilder::inlineTypeObjectFallback(CallInfo &callInfo, MBasicBlock *dispatchBl
|
|||
{
|
||||
// Getting here implies the following:
|
||||
// 1. The call function is an MGetPropertyCache, or an MGetPropertyCache
|
||||
// followed by an MTypeBarrier.
|
||||
JS_ASSERT(callInfo.fun()->isGetPropertyCache() || callInfo.fun()->isTypeBarrier());
|
||||
// followed by an MTypeBarrier, followed by an MUnbox.
|
||||
JS_ASSERT(callInfo.fun()->isGetPropertyCache() || callInfo.fun()->isUnbox());
|
||||
|
||||
// 2. The MGetPropertyCache has inlineable cases by guarding on the TypeObject.
|
||||
JS_ASSERT(dispatch->numCases() > 0);
|
||||
|
||||
// 3. The MGetPropertyCache (and, if applicable, MTypeBarrier) only
|
||||
// 3. The MGetPropertyCache (and, if applicable, MTypeBarrier and MUnbox) only
|
||||
// have at most a single use.
|
||||
JS_ASSERT_IF(callInfo.fun()->isGetPropertyCache(), !cache->hasUses());
|
||||
JS_ASSERT_IF(callInfo.fun()->isTypeBarrier(), cache->useCount() == 1);
|
||||
JS_ASSERT_IF(callInfo.fun()->isUnbox(), cache->hasOneUse());
|
||||
|
||||
// This means that no resume points yet capture the MGetPropertyCache,
|
||||
// so everything from the MGetPropertyCache up until the call is movable.
|
||||
|
@ -4226,14 +4231,19 @@ IonBuilder::inlineTypeObjectFallback(CallInfo &callInfo, MBasicBlock *dispatchBl
|
|||
getPropBlock->addFromElsewhere(cache);
|
||||
getPropBlock->push(cache);
|
||||
} else {
|
||||
MTypeBarrier *barrier = callInfo.fun()->toTypeBarrier();
|
||||
JS_ASSERT(barrier->type() == MIRType_Object);
|
||||
JS_ASSERT(barrier->input()->isGetPropertyCache());
|
||||
JS_ASSERT(barrier->input()->toGetPropertyCache() == cache);
|
||||
MUnbox *unbox = callInfo.fun()->toUnbox();
|
||||
JS_ASSERT(unbox->input()->isTypeBarrier());
|
||||
JS_ASSERT(unbox->type() == MIRType_Object);
|
||||
JS_ASSERT(unbox->mode() == MUnbox::Infallible);
|
||||
|
||||
MTypeBarrier *typeBarrier = unbox->input()->toTypeBarrier();
|
||||
JS_ASSERT(typeBarrier->input()->isGetPropertyCache());
|
||||
JS_ASSERT(typeBarrier->input()->toGetPropertyCache() == cache);
|
||||
|
||||
getPropBlock->addFromElsewhere(cache);
|
||||
getPropBlock->addFromElsewhere(barrier);
|
||||
getPropBlock->push(barrier);
|
||||
getPropBlock->addFromElsewhere(typeBarrier);
|
||||
getPropBlock->addFromElsewhere(unbox);
|
||||
getPropBlock->push(unbox);
|
||||
}
|
||||
|
||||
// Construct an end block with the correct resume point.
|
||||
|
@ -6177,14 +6187,38 @@ IonBuilder::pushTypeBarrier(MInstruction *ins, types::StackTypeSet *observed, bo
|
|||
|
||||
current->pop();
|
||||
|
||||
MInstruction *barrier = MTypeBarrier::New(ins, cloneTypeSet(observed));
|
||||
current->add(barrier);
|
||||
MInstruction *barrier;
|
||||
JSValueType type = observed->getKnownTypeTag();
|
||||
|
||||
if (barrier->type() == MIRType_Undefined)
|
||||
return pushConstant(UndefinedValue());
|
||||
if (barrier->type() == MIRType_Null)
|
||||
return pushConstant(NullValue());
|
||||
// An unbox instruction isn't enough to capture JSVAL_TYPE_OBJECT. Use a type
|
||||
// barrier followed by an infallible unbox.
|
||||
bool isObject = false;
|
||||
if (type == JSVAL_TYPE_OBJECT && !observed->hasType(types::Type::AnyObjectType())) {
|
||||
type = JSVAL_TYPE_UNKNOWN;
|
||||
isObject = true;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case JSVAL_TYPE_UNKNOWN:
|
||||
case JSVAL_TYPE_UNDEFINED:
|
||||
case JSVAL_TYPE_NULL:
|
||||
barrier = MTypeBarrier::New(ins, cloneTypeSet(observed));
|
||||
current->add(barrier);
|
||||
|
||||
if (type == JSVAL_TYPE_UNDEFINED)
|
||||
return pushConstant(UndefinedValue());
|
||||
if (type == JSVAL_TYPE_NULL)
|
||||
return pushConstant(NullValue());
|
||||
if (isObject) {
|
||||
barrier = MUnbox::New(barrier, MIRType_Object, MUnbox::Infallible);
|
||||
current->add(barrier);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MUnbox::Mode mode = ins->isEffectful() ? MUnbox::TypeBarrier : MUnbox::TypeGuard;
|
||||
barrier = MUnbox::New(ins, MIRTypeFromValueType(type), mode);
|
||||
current->add(barrier);
|
||||
}
|
||||
current->push(barrier);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -96,32 +96,13 @@ MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types,
|
|||
JS_ASSERT(scratch != InvalidReg);
|
||||
branchTestObject(NotEqual, tag, miss);
|
||||
Register obj = extractObject(address, scratch);
|
||||
guardObjectType(obj, types, scratch, matched, miss);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TypeSet> void
|
||||
MacroAssembler::guardObjectType(Register obj, const TypeSet *types,
|
||||
Register scratch, Label *matched, Label *miss)
|
||||
{
|
||||
JS_ASSERT(!types->unknown());
|
||||
JS_ASSERT(!types->hasType(types::Type::AnyObjectType()));
|
||||
JS_ASSERT(types->getObjectCount());
|
||||
JS_ASSERT(scratch != InvalidReg);
|
||||
unsigned count = types->getObjectCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (JSObject *object = types->getSingleObject(i))
|
||||
branchPtr(Equal, obj, ImmGCPtr(object), matched);
|
||||
}
|
||||
|
||||
// Note: Some platforms give the same register for obj and scratch.
|
||||
// Make sure when writing to scratch, the obj register isn't used anymore!
|
||||
|
||||
bool hasTypeObjects = false;
|
||||
unsigned count = types->getObjectCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (JSObject *object = types->getSingleObject(i))
|
||||
branchPtr(Equal, obj, ImmGCPtr(object), matched);
|
||||
else
|
||||
hasTypeObjects = true;
|
||||
}
|
||||
|
||||
if (hasTypeObjects) {
|
||||
loadPtr(Address(obj, JSObject::offsetOfType()), scratch);
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
|
@ -161,13 +142,6 @@ template void MacroAssembler::guardTypeSet(const Address &address, const TypeWra
|
|||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const TypeWrapper *types,
|
||||
Register scratch, Label *matched, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardObjectType(Register obj, const types::StackTypeSet *types,
|
||||
Register scratch, Label *matched, Label *miss);
|
||||
template void MacroAssembler::guardObjectType(Register obj, const types::TypeSet *types,
|
||||
Register scratch, Label *matched, Label *miss);
|
||||
template void MacroAssembler::guardObjectType(Register obj, const TypeWrapper *types,
|
||||
Register scratch, Label *matched, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardType(const Address &address, types::Type type,
|
||||
Register scratch, Label *matched, Label *miss);
|
||||
template void MacroAssembler::guardType(const ValueOperand &value, types::Type type,
|
||||
|
|
|
@ -162,9 +162,6 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
template <typename Source, typename TypeSet>
|
||||
void guardTypeSet(const Source &address, const TypeSet *types, Register scratch,
|
||||
Label *matched, Label *miss);
|
||||
template <typename TypeSet>
|
||||
void guardObjectType(Register obj, const TypeSet *types,
|
||||
Register scratch, Label *matched, Label *miss);
|
||||
template <typename Source>
|
||||
void guardType(const Source &address, types::Type type, Register scratch,
|
||||
Label *matched, Label *miss);
|
||||
|
|
|
@ -4449,12 +4449,12 @@ class LGuardThreadLocalObject : public LCallInstructionHelper<0, 2, 1>
|
|||
};
|
||||
|
||||
// Guard that a value is in a TypeSet.
|
||||
class LTypeBarrierV : public LInstructionHelper<0, BOX_PIECES, 1>
|
||||
class LTypeBarrier : public LInstructionHelper<0, BOX_PIECES, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(TypeBarrierV)
|
||||
LIR_HEADER(TypeBarrier)
|
||||
|
||||
LTypeBarrierV(const LDefinition &temp) {
|
||||
LTypeBarrier(const LDefinition &temp) {
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
|
@ -4468,27 +4468,6 @@ class LTypeBarrierV : public LInstructionHelper<0, BOX_PIECES, 1>
|
|||
}
|
||||
};
|
||||
|
||||
// Guard that a object is in a TypeSet.
|
||||
class LTypeBarrierO : public LInstructionHelper<0, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(TypeBarrierO)
|
||||
|
||||
LTypeBarrierO(const LAllocation &obj, const LDefinition &temp) {
|
||||
setOperand(0, obj);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
const MTypeBarrier *mir() const {
|
||||
return mir_->toTypeBarrier();
|
||||
}
|
||||
const LAllocation *object() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Guard that a value is in a TypeSet.
|
||||
class LMonitorTypes : public LInstructionHelper<0, BOX_PIECES, 1>
|
||||
{
|
||||
|
|
|
@ -143,8 +143,7 @@
|
|||
_(GuardObjectType) \
|
||||
_(GuardClass) \
|
||||
_(GuardThreadLocalObject) \
|
||||
_(TypeBarrierV) \
|
||||
_(TypeBarrierO) \
|
||||
_(TypeBarrier) \
|
||||
_(MonitorTypes) \
|
||||
_(PostWriteBarrierO) \
|
||||
_(PostWriteBarrierV) \
|
||||
|
|
|
@ -1840,45 +1840,12 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
|||
bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
|
||||
LDefinition tmp = needTemp ? temp() : tempToUnbox();
|
||||
|
||||
MIRType inputType = ins->getOperand(0)->type();
|
||||
MIRType outputType = ins->type();
|
||||
|
||||
JS_ASSERT(inputType == outputType);
|
||||
JS_ASSERT_IF(ins->certainBail(), outputType == MIRType_Value);
|
||||
|
||||
// Handle typebarrier that will always bail.
|
||||
// (Emit LBail for visibility).
|
||||
if (ins->certainBail()) {
|
||||
JS_ASSERT(outputType == MIRType_Value);
|
||||
|
||||
LBail *bail = new LBail();
|
||||
if (!assignSnapshot(bail, ins->bailoutKind()))
|
||||
return false;
|
||||
return redefine(ins, ins->input()) && add(bail, ins);
|
||||
}
|
||||
|
||||
// Handle typebarrier with Value as input.
|
||||
if (inputType == MIRType_Value) {
|
||||
LTypeBarrierV *barrier = new LTypeBarrierV(tmp);
|
||||
if (!useBox(barrier, LTypeBarrierV::Input, ins->input()))
|
||||
return false;
|
||||
if (!assignSnapshot(barrier, ins->bailoutKind()))
|
||||
return false;
|
||||
return redefine(ins, ins->input()) && add(barrier, ins);
|
||||
}
|
||||
|
||||
// Handle typebarrier with specific TypeObject/SingleObjects.
|
||||
if (inputType == MIRType_Object && !types->hasType(types::Type::AnyObjectType()) &&
|
||||
types->getObjectCount())
|
||||
{
|
||||
LTypeBarrierO *barrier = new LTypeBarrierO(useRegister(ins->getOperand(0)) ,tmp);
|
||||
if (!assignSnapshot(barrier, ins->bailoutKind()))
|
||||
return false;
|
||||
return redefine(ins, ins->getOperand(0)) && add(barrier, ins);
|
||||
}
|
||||
|
||||
// Handle remaining cases: No-op, unbox did everything.
|
||||
return redefine(ins, ins->getOperand(0));
|
||||
LTypeBarrier *barrier = new LTypeBarrier(tmp);
|
||||
if (!useBox(barrier, LTypeBarrier::Input, ins->input()))
|
||||
return false;
|
||||
if (!assignSnapshot(barrier, ins->bailoutKind()))
|
||||
return false;
|
||||
return redefine(ins, ins->input()) && add(barrier, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -620,44 +620,11 @@ MUnbox::printOpcode(FILE *fp) const
|
|||
case Fallible: fprintf(fp, " (fallible)"); break;
|
||||
case Infallible: fprintf(fp, " (infallible)"); break;
|
||||
case TypeBarrier: fprintf(fp, " (typebarrier)"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (mode() == Infallible)
|
||||
return;
|
||||
|
||||
switch(bailoutKind()) {
|
||||
case Bailout_Normal: fprintf(fp, " (normal)"); break;
|
||||
case Bailout_ArgumentCheck: fprintf(fp, " (args)"); break;
|
||||
case Bailout_TypeBarrier: fprintf(fp, " (typebarrier)"); break;
|
||||
case Bailout_Monitor: fprintf(fp, " (monitor)"); break;
|
||||
case Bailout_BoundsCheck: fprintf(fp, " (boundscheck)"); break;
|
||||
case Bailout_ShapeGuard: fprintf(fp, " (shapeguard)"); break;
|
||||
case Bailout_CachedShapeGuard: fprintf(fp, " (cached shapeguard)"); break;
|
||||
case TypeGuard: fprintf(fp, " (typeguard)"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MTypeBarrier::printOpcode(FILE *fp) const
|
||||
{
|
||||
PrintOpcodeName(fp, op());
|
||||
fprintf(fp, " ");
|
||||
getOperand(0)->printName(fp);
|
||||
fprintf(fp, " ");
|
||||
|
||||
switch(bailoutKind()) {
|
||||
case Bailout_Normal: fprintf(fp, " (normal)"); break;
|
||||
case Bailout_ArgumentCheck: fprintf(fp, " (args)"); break;
|
||||
case Bailout_TypeBarrier: fprintf(fp, " (typebarrier)"); break;
|
||||
case Bailout_Monitor: fprintf(fp, " (monitor)"); break;
|
||||
case Bailout_BoundsCheck: fprintf(fp, " (boundscheck)"); break;
|
||||
case Bailout_ShapeGuard: fprintf(fp, " (shapeguard)"); break;
|
||||
case Bailout_CachedShapeGuard: fprintf(fp, " (cached shapeguard)"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MPhi::removeOperand(size_t index)
|
||||
{
|
||||
|
|
|
@ -2129,14 +2129,14 @@ class MUnbox : public MUnaryInstruction, public BoxInputsPolicy
|
|||
enum Mode {
|
||||
Fallible, // Check the type, and deoptimize if unexpected.
|
||||
Infallible, // Type guard is not necessary.
|
||||
TypeBarrier // Guard on the type, and act like a TypeBarrier on failure.
|
||||
TypeBarrier, // Guard on the type, and act like a TypeBarrier on failure.
|
||||
TypeGuard // Guard on the type, and deoptimize otherwise.
|
||||
};
|
||||
|
||||
private:
|
||||
Mode mode_;
|
||||
BailoutKind bailoutKind_;
|
||||
|
||||
MUnbox(MDefinition *ins, MIRType type, Mode mode, BailoutKind kind)
|
||||
MUnbox(MDefinition *ins, MIRType type, Mode mode)
|
||||
: MUnaryInstruction(ins),
|
||||
mode_(mode)
|
||||
{
|
||||
|
@ -2151,24 +2151,17 @@ class MUnbox : public MUnaryInstruction, public BoxInputsPolicy
|
|||
setResultTypeSet(ins->resultTypeSet());
|
||||
setMovable();
|
||||
|
||||
if (mode_ == TypeBarrier)
|
||||
if (mode_ == TypeBarrier || mode_ == TypeGuard)
|
||||
setGuard();
|
||||
|
||||
bailoutKind_ = kind;
|
||||
if (mode_ == TypeGuard)
|
||||
mode_ = Fallible;
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(Unbox)
|
||||
static MUnbox *New(MDefinition *ins, MIRType type, Mode mode)
|
||||
{
|
||||
BailoutKind kind = Bailout_Normal;
|
||||
if (mode == TypeBarrier && ins->isEffectful())
|
||||
kind = Bailout_TypeBarrier;
|
||||
return new MUnbox(ins, type, mode, kind);
|
||||
}
|
||||
|
||||
static MUnbox *New(MDefinition *ins, MIRType type, Mode mode, BailoutKind kind)
|
||||
{
|
||||
return new MUnbox(ins, type, mode, kind);
|
||||
return new MUnbox(ins, type, mode);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
|
@ -2181,7 +2174,9 @@ class MUnbox : public MUnaryInstruction, public BoxInputsPolicy
|
|||
BailoutKind bailoutKind() const {
|
||||
// If infallible, no bailout should be generated.
|
||||
JS_ASSERT(fallible());
|
||||
return bailoutKind_;
|
||||
return mode() == Fallible
|
||||
? Bailout_Normal
|
||||
: Bailout_TypeBarrier;
|
||||
}
|
||||
bool fallible() const {
|
||||
return mode() != Infallible;
|
||||
|
@ -7553,7 +7548,7 @@ class MGuardThreadLocalObject
|
|||
// that value.
|
||||
class MTypeBarrier
|
||||
: public MUnaryInstruction,
|
||||
public TypeBarrierPolicy
|
||||
public BoxInputsPolicy
|
||||
{
|
||||
BailoutKind bailoutKind_;
|
||||
|
||||
|
@ -7561,11 +7556,8 @@ class MTypeBarrier
|
|||
: MUnaryInstruction(def)
|
||||
{
|
||||
JS_ASSERT(!types->unknown());
|
||||
|
||||
MIRType type = MIRTypeFromValueType(types->getKnownTypeTag());
|
||||
setResultType(type);
|
||||
setResultType(MIRType_Value);
|
||||
setResultTypeSet(types);
|
||||
|
||||
setGuard();
|
||||
setMovable();
|
||||
bailoutKind_ = bailoutKind;
|
||||
|
@ -7575,16 +7567,16 @@ class MTypeBarrier
|
|||
INSTRUCTION_HEADER(TypeBarrier)
|
||||
|
||||
static MTypeBarrier *New(MDefinition *def, types::StackTypeSet *types) {
|
||||
BailoutKind kind = def->isEffectful() ? Bailout_TypeBarrier : Bailout_Normal;
|
||||
return new MTypeBarrier(def, types, kind);
|
||||
BailoutKind bailoutKind = def->isEffectful()
|
||||
? Bailout_TypeBarrier
|
||||
: Bailout_Normal;
|
||||
return new MTypeBarrier(def, types, bailoutKind);
|
||||
}
|
||||
static MTypeBarrier *New(MDefinition *def, types::StackTypeSet *types,
|
||||
BailoutKind kind) {
|
||||
return new MTypeBarrier(def, types, kind);
|
||||
BailoutKind bailoutKind) {
|
||||
return new MTypeBarrier(def, types, bailoutKind);
|
||||
}
|
||||
|
||||
void printOpcode(FILE *fp) const;
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
|
@ -7601,17 +7593,6 @@ class MTypeBarrier
|
|||
virtual bool neverHoist() const {
|
||||
return resultTypeSet()->empty();
|
||||
}
|
||||
|
||||
bool certainBail() const {
|
||||
// If mirtype of input doesn't agree with mirtype of barrier,
|
||||
// we will definitely bail.
|
||||
MIRType type = MIRTypeFromValueType(resultTypeSet()->getKnownTypeTag());
|
||||
if (type == MIRType_Value)
|
||||
return false;
|
||||
if (input()->type() == MIRType_Value)
|
||||
return false;
|
||||
return input()->type() != type;
|
||||
}
|
||||
};
|
||||
|
||||
// Like MTypeBarrier, guard that the value is in the given type set. This is
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
#include "jit/Ion.h"
|
||||
#include "jit/IonBuilder.h"
|
||||
#include "jit/IonSpewer.h"
|
||||
#include "jit/MIR.h"
|
||||
#include "jit/AsmJS.h"
|
||||
#include "jit/MIR.h"
|
||||
|
||||
#include "jsinferinlines.h"
|
||||
|
||||
|
|
|
@ -220,52 +220,6 @@ ComparePolicy::adjustInputs(MInstruction *def)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TypeBarrierPolicy::adjustInputs(MInstruction *def)
|
||||
{
|
||||
MTypeBarrier *ins = def->toTypeBarrier();
|
||||
MIRType inputType = ins->getOperand(0)->type();
|
||||
MIRType outputType = ins->type();
|
||||
|
||||
// Input and output type are already in accordance.
|
||||
if (inputType == outputType)
|
||||
return true;
|
||||
|
||||
// Output is a value, currently box the input.
|
||||
// Optimization: decrease resultTypeSet to only include the inputType.
|
||||
// This will remove the need for boxing.
|
||||
if (outputType == MIRType_Value) {
|
||||
JS_ASSERT(inputType != MIRType_Value);
|
||||
ins->replaceOperand(0, boxAt(ins, ins->getOperand(0)));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Input is a value. Unbox the input to the requested type.
|
||||
if (inputType == MIRType_Value) {
|
||||
JS_ASSERT(outputType != MIRType_Value);
|
||||
|
||||
// We can't unbox a value to null/undefined. So keep output also a value.
|
||||
if (IsNullOrUndefined(outputType) || outputType == MIRType_Magic) {
|
||||
ins->setResultType(MIRType_Value);
|
||||
outputType = MIRType_Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
MUnbox *unbox = MUnbox::New(ins->getOperand(0), outputType,
|
||||
MUnbox::TypeBarrier, ins->bailoutKind());
|
||||
ins->block()->insertBefore(ins, unbox);
|
||||
ins->replaceOperand(0, unbox);
|
||||
return true;
|
||||
}
|
||||
|
||||
// In the remaining cases we will alway bail. OutputType doesn't matter.
|
||||
// Take inputType so we can use redefine during lowering.
|
||||
JS_ASSERT(ins->certainBail());
|
||||
ins->setResultType(inputType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestPolicy::adjustInputs(MInstruction *ins)
|
||||
{
|
||||
|
|
|
@ -86,12 +86,6 @@ class TestPolicy : public BoxInputsPolicy
|
|||
bool adjustInputs(MInstruction *ins);
|
||||
};
|
||||
|
||||
class TypeBarrierPolicy : public BoxInputsPolicy
|
||||
{
|
||||
public:
|
||||
bool adjustInputs(MInstruction *ins);
|
||||
};
|
||||
|
||||
class CallPolicy : public BoxInputsPolicy
|
||||
{
|
||||
public:
|
||||
|
|
Загрузка…
Ссылка в новой задаче