зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1649398 - Known class support for MRegExp and folding for MHasClass and MIsCallable. r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D81179
This commit is contained in:
Родитель
79b42c90a6
Коммит
52f794edec
|
@ -1,24 +1,33 @@
|
|||
var IsRegExpObject = getSelfHostedValue("IsRegExpObject");
|
||||
var IsCallable = getSelfHostedValue("IsCallable");
|
||||
|
||||
function array() {
|
||||
var a = [0];
|
||||
assertEq(Array.isArray(a), true);
|
||||
assertEq(typeof a, "object");
|
||||
assertEq(IsRegExpObject(a), false);
|
||||
assertEq(IsCallable(a), false);
|
||||
}
|
||||
|
||||
function array2(x) {
|
||||
var a;
|
||||
if (x) {
|
||||
a = [0]
|
||||
a = [0];
|
||||
} else {
|
||||
a = [1];
|
||||
}
|
||||
assertEq(Array.isArray(a), true);
|
||||
assertEq(typeof a, "object");
|
||||
assertEq(IsRegExpObject(a), false);
|
||||
assertEq(IsCallable(a), false);
|
||||
}
|
||||
|
||||
function object() {
|
||||
var o = {a: 1};
|
||||
assertEq(Array.isArray(o), false);
|
||||
assertEq(typeof o, "object");
|
||||
assertEq(IsRegExpObject(o), false);
|
||||
assertEq(IsCallable(o), false);
|
||||
}
|
||||
|
||||
function object2(x) {
|
||||
|
@ -30,6 +39,8 @@ function object2(x) {
|
|||
}
|
||||
assertEq(Array.isArray(o), false);
|
||||
assertEq(typeof o, "object");
|
||||
assertEq(IsRegExpObject(o), false);
|
||||
assertEq(IsCallable(o), false);
|
||||
}
|
||||
|
||||
function mixed(x) {
|
||||
|
@ -41,20 +52,46 @@ function mixed(x) {
|
|||
}
|
||||
assertEq(Array.isArray(o), x);
|
||||
assertEq(typeof o, "object");
|
||||
assertEq(IsRegExpObject(o), false);
|
||||
assertEq(IsCallable(o), false);
|
||||
}
|
||||
|
||||
function lambda() {
|
||||
function f() {}
|
||||
assertEq(Array.isArray(f), false);
|
||||
assertEq(typeof f, "function");
|
||||
assertEq(IsRegExpObject(f), false);
|
||||
assertEq(IsCallable(f), true);
|
||||
}
|
||||
|
||||
function arrow() {
|
||||
var f = () => {};
|
||||
assertEq(Array.isArray(f), false);
|
||||
assertEq(typeof f, "function");
|
||||
assertEq(IsRegExpObject(f), false);
|
||||
assertEq(IsCallable(f), true);
|
||||
}
|
||||
|
||||
function regexp() {
|
||||
var r = /a/;
|
||||
assertEq(Array.isArray(r), false);
|
||||
assertEq(typeof r, "object");
|
||||
assertEq(IsRegExpObject(r), true);
|
||||
assertEq(IsCallable(r), false);
|
||||
}
|
||||
|
||||
function regexp2(x) {
|
||||
var a;
|
||||
if (x) {
|
||||
a = /a/;
|
||||
} else {
|
||||
a = /b/;
|
||||
}
|
||||
assertEq(Array.isArray(a), false);
|
||||
assertEq(typeof a, "object");
|
||||
assertEq(IsRegExpObject(a), true);
|
||||
assertEq(IsCallable(a), false);
|
||||
}
|
||||
|
||||
var b = true;
|
||||
for (var i = 0; i < 1e4; i++) {
|
||||
|
@ -65,6 +102,8 @@ for (var i = 0; i < 1e4; i++) {
|
|||
mixed(b);
|
||||
lambda();
|
||||
arrow();
|
||||
regexp()
|
||||
regexp2(b);
|
||||
|
||||
b = !b;
|
||||
}
|
||||
|
|
|
@ -5097,6 +5097,9 @@ KnownClass jit::GetObjectKnownClass(const MDefinition* def) {
|
|||
case MDefinition::Opcode::FunctionWithProto:
|
||||
return KnownClass::Function;
|
||||
|
||||
case MDefinition::Opcode::RegExp:
|
||||
return KnownClass::RegExp;
|
||||
|
||||
case MDefinition::Opcode::Phi: {
|
||||
if (def->numOperands() == 0) {
|
||||
return KnownClass::None;
|
||||
|
@ -5138,6 +5141,8 @@ const JSClass* jit::GetObjectKnownJSClass(const MDefinition* def) {
|
|||
return &ArrayObject::class_;
|
||||
case KnownClass::Function:
|
||||
return &JSFunction::class_;
|
||||
case KnownClass::RegExp:
|
||||
return &RegExpObject::class_;
|
||||
case KnownClass::None:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ bool DeadIfUnused(const MDefinition* def);
|
|||
|
||||
bool IsDiscardable(const MDefinition* def);
|
||||
|
||||
enum class KnownClass { PlainObject, Array, Function, None };
|
||||
enum class KnownClass { PlainObject, Array, Function, RegExp, None };
|
||||
KnownClass GetObjectKnownClass(const MDefinition* def);
|
||||
const JSClass* GetObjectKnownJSClass(const MDefinition* def);
|
||||
|
||||
|
|
|
@ -3587,6 +3587,7 @@ MDefinition* MTypeOf::foldsTo(TempAllocator& alloc) {
|
|||
switch (known) {
|
||||
case KnownClass::Array:
|
||||
case KnownClass::PlainObject:
|
||||
case KnownClass::RegExp:
|
||||
type = JSTYPE_OBJECT;
|
||||
break;
|
||||
case KnownClass::Function:
|
||||
|
@ -5908,6 +5909,30 @@ MDefinition* MGuardToClass::foldsTo(TempAllocator& alloc) {
|
|||
return object();
|
||||
}
|
||||
|
||||
MDefinition* MHasClass::foldsTo(TempAllocator& alloc) {
|
||||
const JSClass* clasp = GetObjectKnownJSClass(object());
|
||||
if (!clasp) {
|
||||
return this;
|
||||
}
|
||||
|
||||
AssertKnownClass(alloc, this, object());
|
||||
return MConstant::New(alloc, BooleanValue(getClass() == clasp));
|
||||
}
|
||||
|
||||
MDefinition* MIsCallable::foldsTo(TempAllocator& alloc) {
|
||||
if (input()->type() != MIRType::Object) {
|
||||
return this;
|
||||
}
|
||||
|
||||
KnownClass known = GetObjectKnownClass(input());
|
||||
if (known == KnownClass::None) {
|
||||
return this;
|
||||
}
|
||||
|
||||
AssertKnownClass(alloc, this, input());
|
||||
return MConstant::New(alloc, BooleanValue(known == KnownClass::Function));
|
||||
}
|
||||
|
||||
MDefinition* MIsArray::foldsTo(TempAllocator& alloc) {
|
||||
if (input()->type() != MIRType::Object) {
|
||||
return this;
|
||||
|
|
|
@ -10776,6 +10776,7 @@ class MIsCallable : public MUnaryInstruction,
|
|||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, object))
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||
};
|
||||
|
||||
|
@ -10853,6 +10854,8 @@ class MHasClass : public MUnaryInstruction, public SingleObjectPolicy::Data {
|
|||
NAMED_OPERANDS((0, object))
|
||||
|
||||
const JSClass* getClass() const { return class_; }
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
if (!ins->isHasClass()) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче