зеркало из 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() {
|
function array() {
|
||||||
var a = [0];
|
var a = [0];
|
||||||
assertEq(Array.isArray(a), true);
|
assertEq(Array.isArray(a), true);
|
||||||
assertEq(typeof a, "object");
|
assertEq(typeof a, "object");
|
||||||
|
assertEq(IsRegExpObject(a), false);
|
||||||
|
assertEq(IsCallable(a), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function array2(x) {
|
function array2(x) {
|
||||||
var a;
|
var a;
|
||||||
if (x) {
|
if (x) {
|
||||||
a = [0]
|
a = [0];
|
||||||
} else {
|
} else {
|
||||||
a = [1];
|
a = [1];
|
||||||
}
|
}
|
||||||
assertEq(Array.isArray(a), true);
|
assertEq(Array.isArray(a), true);
|
||||||
assertEq(typeof a, "object");
|
assertEq(typeof a, "object");
|
||||||
|
assertEq(IsRegExpObject(a), false);
|
||||||
|
assertEq(IsCallable(a), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function object() {
|
function object() {
|
||||||
var o = {a: 1};
|
var o = {a: 1};
|
||||||
assertEq(Array.isArray(o), false);
|
assertEq(Array.isArray(o), false);
|
||||||
assertEq(typeof o, "object");
|
assertEq(typeof o, "object");
|
||||||
|
assertEq(IsRegExpObject(o), false);
|
||||||
|
assertEq(IsCallable(o), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function object2(x) {
|
function object2(x) {
|
||||||
|
@ -30,6 +39,8 @@ function object2(x) {
|
||||||
}
|
}
|
||||||
assertEq(Array.isArray(o), false);
|
assertEq(Array.isArray(o), false);
|
||||||
assertEq(typeof o, "object");
|
assertEq(typeof o, "object");
|
||||||
|
assertEq(IsRegExpObject(o), false);
|
||||||
|
assertEq(IsCallable(o), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mixed(x) {
|
function mixed(x) {
|
||||||
|
@ -41,20 +52,46 @@ function mixed(x) {
|
||||||
}
|
}
|
||||||
assertEq(Array.isArray(o), x);
|
assertEq(Array.isArray(o), x);
|
||||||
assertEq(typeof o, "object");
|
assertEq(typeof o, "object");
|
||||||
|
assertEq(IsRegExpObject(o), false);
|
||||||
|
assertEq(IsCallable(o), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function lambda() {
|
function lambda() {
|
||||||
function f() {}
|
function f() {}
|
||||||
assertEq(Array.isArray(f), false);
|
assertEq(Array.isArray(f), false);
|
||||||
assertEq(typeof f, "function");
|
assertEq(typeof f, "function");
|
||||||
|
assertEq(IsRegExpObject(f), false);
|
||||||
|
assertEq(IsCallable(f), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrow() {
|
function arrow() {
|
||||||
var f = () => {};
|
var f = () => {};
|
||||||
assertEq(Array.isArray(f), false);
|
assertEq(Array.isArray(f), false);
|
||||||
assertEq(typeof f, "function");
|
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;
|
var b = true;
|
||||||
for (var i = 0; i < 1e4; i++) {
|
for (var i = 0; i < 1e4; i++) {
|
||||||
|
@ -65,6 +102,8 @@ for (var i = 0; i < 1e4; i++) {
|
||||||
mixed(b);
|
mixed(b);
|
||||||
lambda();
|
lambda();
|
||||||
arrow();
|
arrow();
|
||||||
|
regexp()
|
||||||
|
regexp2(b);
|
||||||
|
|
||||||
b = !b;
|
b = !b;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5097,6 +5097,9 @@ KnownClass jit::GetObjectKnownClass(const MDefinition* def) {
|
||||||
case MDefinition::Opcode::FunctionWithProto:
|
case MDefinition::Opcode::FunctionWithProto:
|
||||||
return KnownClass::Function;
|
return KnownClass::Function;
|
||||||
|
|
||||||
|
case MDefinition::Opcode::RegExp:
|
||||||
|
return KnownClass::RegExp;
|
||||||
|
|
||||||
case MDefinition::Opcode::Phi: {
|
case MDefinition::Opcode::Phi: {
|
||||||
if (def->numOperands() == 0) {
|
if (def->numOperands() == 0) {
|
||||||
return KnownClass::None;
|
return KnownClass::None;
|
||||||
|
@ -5138,6 +5141,8 @@ const JSClass* jit::GetObjectKnownJSClass(const MDefinition* def) {
|
||||||
return &ArrayObject::class_;
|
return &ArrayObject::class_;
|
||||||
case KnownClass::Function:
|
case KnownClass::Function:
|
||||||
return &JSFunction::class_;
|
return &JSFunction::class_;
|
||||||
|
case KnownClass::RegExp:
|
||||||
|
return &RegExpObject::class_;
|
||||||
case KnownClass::None:
|
case KnownClass::None:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,7 @@ bool DeadIfUnused(const MDefinition* def);
|
||||||
|
|
||||||
bool IsDiscardable(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);
|
KnownClass GetObjectKnownClass(const MDefinition* def);
|
||||||
const JSClass* GetObjectKnownJSClass(const MDefinition* def);
|
const JSClass* GetObjectKnownJSClass(const MDefinition* def);
|
||||||
|
|
||||||
|
|
|
@ -3587,6 +3587,7 @@ MDefinition* MTypeOf::foldsTo(TempAllocator& alloc) {
|
||||||
switch (known) {
|
switch (known) {
|
||||||
case KnownClass::Array:
|
case KnownClass::Array:
|
||||||
case KnownClass::PlainObject:
|
case KnownClass::PlainObject:
|
||||||
|
case KnownClass::RegExp:
|
||||||
type = JSTYPE_OBJECT;
|
type = JSTYPE_OBJECT;
|
||||||
break;
|
break;
|
||||||
case KnownClass::Function:
|
case KnownClass::Function:
|
||||||
|
@ -5908,6 +5909,30 @@ MDefinition* MGuardToClass::foldsTo(TempAllocator& alloc) {
|
||||||
return object();
|
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) {
|
MDefinition* MIsArray::foldsTo(TempAllocator& alloc) {
|
||||||
if (input()->type() != MIRType::Object) {
|
if (input()->type() != MIRType::Object) {
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -10776,6 +10776,7 @@ class MIsCallable : public MUnaryInstruction,
|
||||||
TRIVIAL_NEW_WRAPPERS
|
TRIVIAL_NEW_WRAPPERS
|
||||||
NAMED_OPERANDS((0, object))
|
NAMED_OPERANDS((0, object))
|
||||||
|
|
||||||
|
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10853,6 +10854,8 @@ class MHasClass : public MUnaryInstruction, public SingleObjectPolicy::Data {
|
||||||
NAMED_OPERANDS((0, object))
|
NAMED_OPERANDS((0, object))
|
||||||
|
|
||||||
const JSClass* getClass() const { return class_; }
|
const JSClass* getClass() const { return class_; }
|
||||||
|
|
||||||
|
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||||
bool congruentTo(const MDefinition* ins) const override {
|
bool congruentTo(const MDefinition* ins) const override {
|
||||||
if (!ins->isHasClass()) {
|
if (!ins->isHasClass()) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче