mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 914132 part 3 - Inline |typeof object| if the input is known to be non-callable and does not emulate undefined. r=bhackett
This commit is contained in:
parent
3ccd5b1fef
commit
0c229fcfa2
@ -6433,18 +6433,28 @@ CodeGenerator::visitTypeOfV(LTypeOfV *lir)
|
||||
Register output = ToRegister(lir->output());
|
||||
Register tag = masm.splitTagForTest(value);
|
||||
|
||||
OutOfLineTypeOfV *ool = new OutOfLineTypeOfV(lir);
|
||||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
|
||||
JSRuntime *rt = GetIonContext()->runtime;
|
||||
|
||||
// Jump to the OOL path if the value is an object. Objects are complicated
|
||||
// since they may have a typeof hook.
|
||||
masm.branchTestObject(Assembler::Equal, tag, ool->entry());
|
||||
|
||||
Label done;
|
||||
|
||||
OutOfLineTypeOfV *ool = NULL;
|
||||
if (lir->mir()->inputMaybeCallableOrEmulatesUndefined()) {
|
||||
// The input may be a callable object (result is "function") or may
|
||||
// emulate undefined (result is "undefined"). Use an OOL path.
|
||||
ool = new OutOfLineTypeOfV(lir);
|
||||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
|
||||
masm.branchTestObject(Assembler::Equal, tag, ool->entry());
|
||||
} else {
|
||||
// Input is not callable and does not emulate undefined, so if
|
||||
// it's an object the result is always "object".
|
||||
Label notObject;
|
||||
masm.branchTestObject(Assembler::NotEqual, tag, ¬Object);
|
||||
masm.movePtr(ImmGCPtr(rt->atomState.object), output);
|
||||
masm.jump(&done);
|
||||
masm.bind(¬Object);
|
||||
}
|
||||
|
||||
Label notNumber;
|
||||
masm.branchTestNumber(Assembler::NotEqual, tag, ¬Number);
|
||||
masm.movePtr(ImmGCPtr(rt->atomState.number), output);
|
||||
@ -6472,7 +6482,8 @@ CodeGenerator::visitTypeOfV(LTypeOfV *lir)
|
||||
masm.movePtr(ImmGCPtr(rt->atomState.string), output);
|
||||
|
||||
masm.bind(&done);
|
||||
masm.bind(ool->rejoin());
|
||||
if (ool)
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -8934,6 +8934,8 @@ IonBuilder::jsop_typeof()
|
||||
MDefinition *input = current->pop();
|
||||
MTypeOf *ins = MTypeOf::New(input, input->type());
|
||||
|
||||
ins->infer(cx);
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
||||
|
@ -215,6 +215,19 @@ MaybeEmulatesUndefined(JSContext *cx, MDefinition *op)
|
||||
return types->hasObjectFlags(cx, types::OBJECT_FLAG_EMULATES_UNDEFINED);
|
||||
}
|
||||
|
||||
static bool
|
||||
MaybeCallable(JSContext *cx, MDefinition *op)
|
||||
{
|
||||
if (!op->mightBeType(MIRType_Object))
|
||||
return false;
|
||||
|
||||
types::StackTypeSet *types = op->resultTypeSet();
|
||||
if (!types)
|
||||
return true;
|
||||
|
||||
return types->maybeCallable();
|
||||
}
|
||||
|
||||
void
|
||||
MTest::infer(JSContext *cx)
|
||||
{
|
||||
@ -1883,6 +1896,15 @@ MTypeOf::foldsTo(bool useValueNumbers)
|
||||
return MConstant::New(StringValue(TypeName(type, rt)));
|
||||
}
|
||||
|
||||
void
|
||||
MTypeOf::infer(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(inputMaybeCallableOrEmulatesUndefined());
|
||||
|
||||
if (!MaybeEmulatesUndefined(cx, input()) && !MaybeCallable(cx, input()))
|
||||
markInputNotCallableOrEmulatesUndefined();
|
||||
}
|
||||
|
||||
MBitAnd *
|
||||
MBitAnd::New(MDefinition *left, MDefinition *right)
|
||||
{
|
||||
|
@ -2895,9 +2895,11 @@ class MTypeOf
|
||||
public BoxInputsPolicy
|
||||
{
|
||||
MIRType inputType_;
|
||||
bool inputMaybeCallableOrEmulatesUndefined_;
|
||||
|
||||
MTypeOf(MDefinition *def, MIRType inputType)
|
||||
: MUnaryInstruction(def), inputType_(inputType)
|
||||
: MUnaryInstruction(def), inputType_(inputType),
|
||||
inputMaybeCallableOrEmulatesUndefined_(true)
|
||||
{
|
||||
setResultType(MIRType_String);
|
||||
setMovable();
|
||||
@ -2916,7 +2918,16 @@ class MTypeOf
|
||||
MIRType inputType() const {
|
||||
return inputType_;
|
||||
}
|
||||
|
||||
MDefinition *foldsTo(bool useValueNumbers);
|
||||
void infer(JSContext *cx);
|
||||
|
||||
bool inputMaybeCallableOrEmulatesUndefined() const {
|
||||
return inputMaybeCallableOrEmulatesUndefined_;
|
||||
}
|
||||
void markInputNotCallableOrEmulatesUndefined() {
|
||||
inputMaybeCallableOrEmulatesUndefined_ = false;
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
|
@ -1106,6 +1106,32 @@ StackTypeSet::isDOMClass()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
StackTypeSet::maybeCallable()
|
||||
{
|
||||
if (!maybeObject())
|
||||
return false;
|
||||
|
||||
if (unknownObject())
|
||||
return true;
|
||||
|
||||
unsigned count = getObjectCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
Class *clasp;
|
||||
if (JSObject *object = getSingleObject(i))
|
||||
clasp = object->getClass();
|
||||
else if (TypeObject *object = getTypeObject(i))
|
||||
clasp = object->clasp;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (clasp->isCallable())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
StackTypeSet::getCommonPrototype()
|
||||
{
|
||||
|
@ -625,6 +625,9 @@ class StackTypeSet : public TypeSet
|
||||
/* Whether all objects have JSCLASS_IS_DOMJSCLASS set. */
|
||||
bool isDOMClass();
|
||||
|
||||
/* Whether clasp->isCallable() is true for one or more objects in this set. */
|
||||
bool maybeCallable();
|
||||
|
||||
/* Get the single value which can appear in this type set, otherwise NULL. */
|
||||
JSObject *getSingleton();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user