backout 183decadb9ac

This commit is contained in:
Tom Schuster 2012-07-18 13:52:02 +02:00
parent 374edb776d
commit 4e9abfc0e4
9 changed files with 19 additions and 705 deletions

View File

@ -1660,7 +1660,7 @@ CodeGenerator::visitBinaryV(LBinaryV *lir)
bool
CodeGenerator::visitCompareS(LCompareS *lir)
{
JSOp op = lir->jsop();
JSOp op = lir->mir()->jsop();
Register left = ToRegister(lir->left());
Register right = ToRegister(lir->right());
Register output = ToRegister(lir->output());
@ -1834,215 +1834,6 @@ CodeGenerator::visitIsNullOrUndefinedAndBranch(LIsNullOrUndefinedAndBranch *lir)
return true;
}
static JSType
StringToJSType(JSContext *cx, JSLinearString *str)
{
JSRuntime *rt = cx->runtime;
if (EqualStrings(str, rt->atomState.typeAtoms[JSTYPE_STRING]))
return JSTYPE_STRING;
if (EqualStrings(str, rt->atomState.typeAtoms[JSTYPE_NUMBER]))
return JSTYPE_NUMBER;
if (EqualStrings(str, rt->atomState.typeAtoms[JSTYPE_BOOLEAN]))
return JSTYPE_BOOLEAN;
if (EqualStrings(str, rt->atomState.typeAtoms[JSTYPE_VOID]))
return JSTYPE_VOID;
if (EqualStrings(str, rt->atomState.typeAtoms[JSTYPE_OBJECT]))
return JSTYPE_OBJECT;
if (EqualStrings(str, rt->atomState.typeAtoms[JSTYPE_FUNCTION]))
return JSTYPE_FUNCTION;
if (EqualStrings(str, rt->atomState.typeAtoms[JSTYPE_XML]))
return JSTYPE_XML;
return JSTYPE_LIMIT;
}
bool
CodeGenerator::visitTypeOfIs(LTypeOfIs *lir)
{
JSOp op = lir->jsop();
const ValueOperand value = ToValue(lir, LTypeOfIs::Value);
Register output = ToRegister(lir->output());
JSContext *cx = gen->cx;
JSLinearString *str = lir->value().toString()->ensureLinear(cx);
if (!str)
return false;
JSType type = StringToJSType(cx, str);
Assembler::Condition cond = JSOpToCondition(op);
if (type == JSTYPE_STRING) {
cond = masm.testString(cond, value);
emitSet(cond, output);
} else if (type == JSTYPE_NUMBER) {
cond = masm.testNumber(cond, value);
emitSet(cond, output);
} else if (type == JSTYPE_BOOLEAN) {
cond = masm.testBoolean(cond, value);
emitSet(cond, output);
} else if (type == JSTYPE_VOID) {
cond = masm.testUndefined(cond, value);
emitSet(cond, output);
} else if (type == JSTYPE_OBJECT) {
Register tag = masm.splitTagForTest(value);
Label isObject, isntObject, done;
masm.branchTestNull(Assembler::Equal, tag, &isObject);
masm.branchTestObject(Assembler::NotEqual, tag, &isntObject);
Register object = masm.extractObject(value, output);
masm.loadObjClass(object, output);
// JSFunction is special, because there is no Call hook in Class for them.
masm.cmpPtr(output, ImmWord(&FunctionClass));
masm.j(Assembler::Equal, &isntObject);
// The typeof hook could tell us anything, eg. "xml".
masm.cmpPtr(Address(output, offsetof(Class, ops.typeOf)), ImmWord(reinterpret_cast<void *>(NULL)));
if (!bailoutIf(Assembler::NotEqual, lir->snapshot()))
return false;
// Per ES5 everything which has no [[Call]] is an object.
masm.cmpPtr(Address(output, offsetof(Class, call)), ImmWord(reinterpret_cast<void *>(NULL)));
masm.j(Assembler::NotEqual, &isntObject);
masm.bind(&isObject);
masm.move32(Imm32(op == JSOP_EQ || op == JSOP_STRICTEQ), output);
masm.jump(&done);
masm.bind(&isntObject);
masm.move32(Imm32(op == JSOP_NE || op == JSOP_STRICTNE), output);
masm.bind(&done);
} else if (type == JSTYPE_FUNCTION) {
Register tag = masm.splitTagForTest(value);
Label isFunction, isntFunction, done;
masm.branchTestObject(Assembler::NotEqual, tag, &isntFunction);
Register object = masm.extractObject(value, output);
masm.loadObjClass(object, output);
masm.cmpPtr(output, ImmWord(&FunctionClass));
masm.j(Assembler::Equal, &isFunction);
masm.cmpPtr(Address(output, offsetof(Class, ops.typeOf)), ImmWord(reinterpret_cast<void *>(NULL)));
if (!bailoutIf(Assembler::NotEqual, lir->snapshot()))
return false;
masm.cmpPtr(Address(output, offsetof(Class, call)), ImmWord(reinterpret_cast<void *>(NULL)));
masm.j(Assembler::Equal, &isntFunction);
masm.bind(&isFunction);
masm.move32(Imm32(op == JSOP_EQ || op == JSOP_STRICTEQ), output);
masm.jump(&done);
masm.bind(&isntFunction);
masm.move32(Imm32(op == JSOP_NE || op == JSOP_STRICTNE), output);
masm.bind(&done);
} else if (type == JSTYPE_XML) {
// Don't even really bother.
cond = masm.testObject(Assembler::Equal, value);
if (!bailoutIf(cond, lir->snapshot()))
return false;
masm.move32(Imm32(op == JSOP_NE || op == JSOP_STRICTNE), output);
} else {
JS_ASSERT(type == JSTYPE_LIMIT);
// This happens for code like |typeof x == 'banana'|, because this would never be
// equal to any type we can always return false.
masm.move32(Imm32(op == JSOP_NE || op == JSOP_STRICTNE), output);
}
return true;
}
bool
CodeGenerator::visitTypeOfIsAndBranch(LTypeOfIsAndBranch *lir)
{
JSOp op = lir->jsop();
const ValueOperand value = ToValue(lir, LTypeOfIsAndBranch::Value);
JSContext *cx = gen->cx;
JSLinearString *str = lir->value().toString()->ensureLinear(cx);
if (!str)
return false;
JSType type = StringToJSType(cx, str);
MBasicBlock *ifTrue;
MBasicBlock *ifFalse;
if (op == JSOP_EQ || op == JSOP_STRICTEQ) {
ifTrue = lir->ifTrue();
ifFalse = lir->ifFalse();
} else {
// Swap branches.
ifTrue = lir->ifFalse();
ifFalse = lir->ifTrue();
}
if (type == JSTYPE_STRING) {
Assembler::Condition cond = masm.testString(Assembler::Equal, value);
emitBranch(cond, ifTrue, ifFalse);
} else if (type == JSTYPE_NUMBER) {
Assembler::Condition cond = masm.testNumber(Assembler::Equal, value);
emitBranch(cond, ifTrue, ifFalse);
} else if (type == JSTYPE_BOOLEAN) {
Assembler::Condition cond = masm.testBoolean(Assembler::Equal, value);
emitBranch(cond, ifTrue, ifFalse);
} else if (type == JSTYPE_VOID) {
Assembler::Condition cond = masm.testUndefined(Assembler::Equal, value);
emitBranch(cond, ifTrue, ifFalse);
} else if (type == JSTYPE_OBJECT) {
Register tag = masm.splitTagForTest(value);
Register temp = ToRegister(lir->temp());
masm.branchTestNull(Assembler::Equal, tag, ifTrue->lir()->label());
masm.branchTestObject(Assembler::NotEqual, tag, ifFalse->lir()->label());
Register object = masm.extractObject(value, temp);
masm.loadObjClass(object, temp);
masm.cmpPtr(temp, ImmWord(&FunctionClass));
masm.j(Assembler::Equal, ifFalse->lir()->label());
masm.cmpPtr(Address(temp, offsetof(Class, ops.typeOf)), ImmWord(reinterpret_cast<void *>(NULL)));
if (!bailoutIf(Assembler::NotEqual, lir->snapshot()))
return false;
masm.cmpPtr(Address(temp, offsetof(Class, call)), ImmWord(reinterpret_cast<void *>(NULL)));
emitBranch(Assembler::Equal, ifTrue, ifFalse);
} else if (type == JSTYPE_FUNCTION) {
Register tag = masm.splitTagForTest(value);
Register temp = ToRegister(lir->temp());
masm.branchTestObject(Assembler::NotEqual, tag, ifFalse->lir()->label());
Register object = masm.extractObject(value, temp);
masm.loadObjClass(object, temp);
masm.cmpPtr(temp, ImmWord(&FunctionClass));
masm.j(Assembler::Equal, ifTrue->lir()->label());
masm.cmpPtr(Address(temp, offsetof(Class, ops.typeOf)), ImmWord(reinterpret_cast<void *>(NULL)));
if (!bailoutIf(Assembler::NotEqual, lir->snapshot()))
return false;
masm.cmpPtr(Address(temp, offsetof(Class, call)), ImmWord(reinterpret_cast<void *>(NULL)));
emitBranch(Assembler::NotEqual, ifTrue, ifFalse);
} else if (type == JSTYPE_XML) {
// Don't even really bother.
Assembler::Condition cond = masm.testObject(Assembler::Equal, value);
if (!bailoutIf(cond, lir->snapshot()))
return false;
masm.jump(ifFalse->lir()->label());
} else {
JS_ASSERT(type == JSTYPE_LIMIT);
masm.jump(ifFalse->lir()->label());
}
return true;
}
bool
CodeGenerator::visitConcat(LConcat *lir)
{

View File

@ -147,8 +147,6 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitCompareV(LCompareV *lir);
bool visitIsNullOrUndefined(LIsNullOrUndefined *lir);
bool visitIsNullOrUndefinedAndBranch(LIsNullOrUndefinedAndBranch *lir);
bool visitTypeOfIs(LTypeOfIs *lir);
bool visitTypeOfIsAndBranch(LTypeOfIsAndBranch *lir);
bool visitConcat(LConcat *lir);
bool visitCharCodeAt(LCharCodeAt *lir);
bool visitFromCharCode(LFromCharCode *lir);

View File

@ -862,20 +862,13 @@ class LCompareD : public LInstructionHelper<1, 2, 0>
class LCompareS : public LInstructionHelper<1, 2, 0>
{
JSOp jsop_;
public:
LIR_HEADER(CompareS);
LCompareS(JSOp jsop, const LAllocation &left, const LAllocation &right)
: jsop_(jsop)
{
LCompareS(const LAllocation &left, const LAllocation &right) {
setOperand(0, left);
setOperand(1, right);
}
JSOp jsop() const{
return jsop_;
}
const LAllocation *left() {
return getOperand(0);
}
@ -1073,71 +1066,6 @@ class LIsNullOrUndefinedAndBranch : public LInstructionHelper<0, BOX_PIECES, 0>
}
};
class LTypeOfIs : public LInstructionHelper<1, BOX_PIECES, 0>
{
JSOp op_;
const js::Value v_;
public:
LIR_HEADER(TypeOfIs);
LTypeOfIs(JSOp op, const js::Value &v)
: op_(op), v_(v)
{ }
static const size_t Value = 0;
JSOp jsop() {
return op_;
}
js::Value value() {
return v_;
}
const LDefinition *output() {
return getDef(0);
}
};
class LTypeOfIsAndBranch : public LInstructionHelper<0, BOX_PIECES, 1>
{
JSOp jsop_;
const js::Value v_;
MBasicBlock *ifTrue_;
MBasicBlock *ifFalse_;
public:
LIR_HEADER(TypeOfIsAndBranch);
LTypeOfIsAndBranch(JSOp jsop, const js::Value &v, const LDefinition &temp,
MBasicBlock *ifTrue, MBasicBlock *ifFalse)
: jsop_(jsop),
v_(v),
ifTrue_(ifTrue),
ifFalse_(ifFalse)
{
setTemp(0, temp);
}
static const size_t Value = 0;
JSOp jsop() const {
return jsop_;
}
js::Value value() {
return v_;
}
const LDefinition *temp() {
return getTemp(0);
}
MBasicBlock *ifTrue() const {
return ifTrue_;
}
MBasicBlock *ifFalse() const {
return ifFalse_;
}
};
// Not operation on an integer.
class LNotI : public LInstructionHelper<1, 1, 0>
{

View File

@ -92,8 +92,6 @@
_(CompareBAndBranch) \
_(IsNullOrUndefined) \
_(IsNullOrUndefinedAndBranch) \
_(TypeOfIs) \
_(TypeOfIsAndBranch) \
_(AbsI) \
_(AbsD) \
_(SqrtD) \

View File

@ -344,14 +344,6 @@ ReorderComparison(JSOp op, MDefinition **lhsp, MDefinition **rhsp)
return op;
}
inline bool
IsTypeOfCompare(MDefinition *left, MDefinition *right)
{
if (!left->isTypeOf() || !right->isConstant())
return false;
return right->toConstant()->value().isString();
}
bool
LIRGenerator::visitTest(MTest *test)
{
@ -409,23 +401,6 @@ LIRGenerator::visitTest(MTest *test)
return add(lir, comp);
}
if (comp->specialization() == MIRType_String) {
// We can safely reorder, because operand order doesn't matter for LCompareS.
JSOp op = ReorderComparison(comp->jsop(), &left, &right);
if (IsTypeOfCompare(left, right)) {
MTypeOf *typeOf = left->toTypeOf();
LTypeOfIsAndBranch *lir = new LTypeOfIsAndBranch(op, right->toConstant()->value(),
temp(), ifTrue, ifFalse);
if (!useBox(lir, LTypeOfIsAndBranch::Value, typeOf->input()))
return false;
if (!assignSnapshot(lir))
return false;
return add(lir, comp);
}
}
if (comp->specialization() == MIRType_Boolean) {
JS_ASSERT(left->type() == MIRType_Value);
JS_ASSERT(right->type() == MIRType_Boolean);
@ -454,22 +429,22 @@ LIRGenerator::visitInlineFunctionGuard(MInlineFunctionGuard *ins)
return add(lir);
}
inline bool
CanEmitInstructionAtUses(MInstruction *ins, MDefinition::Opcode op)
static inline bool
CanEmitCompareAtUses(MInstruction *ins)
{
if (!ins->canEmitAtUses())
return false;
bool alreadyUsed = false;
bool foundTest = false;
for (MUseIterator iter(ins->usesBegin()); iter != ins->usesEnd(); iter++) {
MNode *node = iter->node();
if (!node->isDefinition())
return false;
if (node->toDefinition()->op() != op)
if (!node->toDefinition()->isTest())
return false;
if (alreadyUsed)
if (foundTest)
return false;
alreadyUsed = true;
foundTest = true;
}
return true;
}
@ -486,11 +461,21 @@ LIRGenerator::visitCompare(MCompare *comp)
if (comp->tryFold(&result))
return define(new LInteger(result), comp);
// Move below the emitAtUses call if we ever implement
// LCompareSAndBranch. Doing this now wouldn't be wrong, but doesn't
// make sense and avoids confusion.
if (comp->specialization() == MIRType_String) {
LCompareS *lir = new LCompareS(useRegister(left), useRegister(right));
if (!define(lir, comp))
return false;
return assignSafepoint(lir, comp);
}
// Sniff out if the output of this compare is used only for a branching.
// If it is, then we willl emit an LCompare*AndBranch instruction in place
// of this compare and any test that uses this compare. Thus, we can
// ignore this Compare.
if (CanEmitInstructionAtUses(comp, MDefinition::Op_Test))
if (CanEmitCompareAtUses(comp))
return emitAtUses(comp);
if (comp->specialization() == MIRType_Int32 || comp->specialization() == MIRType_Object) {
@ -514,26 +499,6 @@ LIRGenerator::visitCompare(MCompare *comp)
return define(lir, comp);
}
if (comp->specialization() == MIRType_String) {
JSOp op = ReorderComparison(comp->jsop(), &left, &right);
if (IsTypeOfCompare(left, right)) {
MTypeOf *typeOf = left->toTypeOf();
LTypeOfIs *lir = new LTypeOfIs(op, right->toConstant()->value());
if (!useBox(lir, LTypeOfIs::Value, typeOf->input()))
return false;
if (!assignSnapshot(lir))
return false;
return define(lir, comp);
}
LCompareS *lir = new LCompareS(op, useRegister(left), useRegister(right));
if (!define(lir, comp))
return false;
return assignSafepoint(lir, comp);
}
JS_ASSERT(IsNullOrUndefined(comp->specialization()));
LIsNullOrUndefined *lir = new LIsNullOrUndefined();
@ -589,9 +554,6 @@ LIRGenerator::visitTypeOf(MTypeOf *ins)
MDefinition *opd = ins->input();
JS_ASSERT(opd->type() == MIRType_Value);
if (CanEmitInstructionAtUses(ins, MDefinition::Op_Compare))
return emitAtUses(ins);
LTypeOfV *lir = new LTypeOfV();
if (!useBox(lir, LTypeOfV::Input, opd))
return false;

View File

@ -1974,7 +1974,6 @@ MacroAssemblerARMCompat::testBoolean(Assembler::Condition cond, const ValueOpera
ma_cmp(value.typeReg(), ImmType(JSVAL_TYPE_BOOLEAN));
return cond;
}
Assembler::Condition
MacroAssemblerARMCompat::testDouble(Assembler::Condition cond, const ValueOperand &value)
{
@ -1986,17 +1985,6 @@ MacroAssemblerARMCompat::testDouble(Assembler::Condition cond, const ValueOperan
return actual;
}
Assembler::Condition
MacroAssemblerARMCompat::testNumber(Assembler::Condition cond, const ValueOperand &value)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Assembler::Condition actual = (cond == Equal)
? BelowOrEqual
: Above;
ma_cmp(value.typeReg(), ImmTag(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
return actual;
}
Assembler::Condition
MacroAssemblerARMCompat::testNull(Assembler::Condition cond, const ValueOperand &value)
{

View File

@ -531,7 +531,6 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
Condition testInt32(Condition cond, const ValueOperand &value);
Condition testBoolean(Condition cond, const ValueOperand &value);
Condition testDouble(Condition cond, const ValueOperand &value);
Condition testNumber(Condition cond, const ValueOperand &value);
Condition testNull(Condition cond, const ValueOperand &value);
Condition testUndefined(Condition cond, const ValueOperand &value);
Condition testString(Condition cond, const ValueOperand &value);

View File

@ -276,10 +276,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
splitTag(src, ScratchReg);
return testDouble(cond, ScratchReg);
}
Condition testNumber(Condition cond, const ValueOperand &src) {
splitTag(src, ScratchReg);
return testNumber(cond, ScratchReg);
}
Condition testNull(Condition cond, const ValueOperand &src) {
splitTag(src, ScratchReg);
return testNull(cond, ScratchReg);

View File

@ -1,346 +0,0 @@
function isObject(x) {
return "object" === typeof x;
}
function isObject2(x) {
if ("object" === typeof x)
return true;
return false;
}
function isBoolean(x) {
return "boolean" === typeof x;
}
function isBoolean2(x) {
if ("boolean" === typeof x)
return true;
return false;
}
function isFunction(x) {
return "function" === typeof x;
}
function isFunction2(x) {
if ("function" === typeof x)
return true;
return false;
}
function isNumber(x) {
return "number" === typeof x;
}
function isNumber2(x) {
if ("number" === typeof x)
return true;
return false;
}
function isString(x) {
return "string" === typeof x;
}
function isString2(x) {
if ("string" === typeof x)
return true;
return false;
}
function isUndefined(x) {
return "undefined" === typeof x;
}
function isUndefined2(x) {
if ("undefined" === typeof x)
return true;
return false;
}
function isBanana(x) {
return "Banana" === typeof x;
}
function isBanana2(x) {
if ("Banana" === typeof x)
return true;
return false;
}
for (var i = 0; i < 100; i++) {
assertEq(isObject(null), true);
assertEq(isObject2(null), true);
assertEq(isBoolean(null), false);
assertEq(isBoolean2(null), false);
assertEq(isFunction(null), false);
assertEq(isFunction2(null), false);
assertEq(isNumber(null), false);
assertEq(isNumber2(null), false);
assertEq(isString(null), false);
assertEq(isString2(null), false);
assertEq(isUndefined(null), false);
assertEq(isUndefined2(null), false);
assertEq(isBanana(null), false);
assertEq(isBanana2(null), false);
assertEq(isObject({}), true);
assertEq(isObject2({}), true);
assertEq(isBoolean({}), false);
assertEq(isBoolean2({}), false);
assertEq(isFunction({}), false);
assertEq(isFunction2({}), false);
assertEq(isNumber({}), false);
assertEq(isNumber2({}), false);
assertEq(isString({}), false);
assertEq(isString2({}), false);
assertEq(isUndefined({}), false);
assertEq(isUndefined2({}), false);
assertEq(isBanana({}), false);
assertEq(isBanana2({}), false);
assertEq(isObject([]), true);
assertEq(isObject2([]), true);
assertEq(isBoolean([]), false);
assertEq(isBoolean2([]), false);
assertEq(isFunction([]), false);
assertEq(isFunction2([]), false);
assertEq(isNumber([]), false);
assertEq(isNumber2([]), false);
assertEq(isString([]), false);
assertEq(isString2([]), false);
assertEq(isUndefined([]), false);
assertEq(isUndefined2([]), false);
assertEq(isBanana([]), false);
assertEq(isBanana2([]), false);
assertEq(isObject(new Date()), true);
assertEq(isObject2(new Date()), true);
assertEq(isBoolean(new Date()), false);
assertEq(isBoolean2(new Date()), false);
assertEq(isFunction(new Date()), false);
assertEq(isFunction2(new Date()), false);
assertEq(isNumber(new Date()), false);
assertEq(isNumber2(new Date()), false);
assertEq(isString(new Date()), false);
assertEq(isString2(new Date()), false);
assertEq(isUndefined(new Date()), false);
assertEq(isUndefined2(new Date()), false);
assertEq(isBanana(new Date()), false);
assertEq(isBanana2(new Date()), false);
assertEq(isObject(new String()), true);
assertEq(isObject2(new String()), true);
assertEq(isBoolean(new String()), false);
assertEq(isBoolean2(new String()), false);
assertEq(isFunction(new String()), false);
assertEq(isFunction2(new String()), false);
assertEq(isNumber(new String()), false);
assertEq(isNumber2(new String()), false);
assertEq(isString(new String()), false);
assertEq(isString2(new String()), false);
assertEq(isUndefined(new String()), false);
assertEq(isUndefined2(new String()), false);
assertEq(isBanana(new String()), false);
assertEq(isBanana2(new String()), false);
assertEq(isObject(new Boolean()), true);
assertEq(isObject2(new Boolean()), true);
assertEq(isBoolean(new Boolean()), false);
assertEq(isBoolean2(new Boolean()), false);
assertEq(isFunction(new Boolean()), false);
assertEq(isFunction2(new Boolean()), false);
assertEq(isNumber(new Boolean()), false);
assertEq(isNumber2(new Boolean()), false);
assertEq(isString(new Boolean()), false);
assertEq(isString2(new Boolean()), false);
assertEq(isUndefined(new Boolean()), false);
assertEq(isUndefined2(new Boolean()), false);
assertEq(isBanana(new Boolean()), false);
assertEq(isBanana2(new Boolean()), false);
assertEq(isObject(Proxy.create({})), true);
assertEq(isObject2(Proxy.create({})), true);
assertEq(isBoolean(Proxy.create({})), false);
assertEq(isBoolean2(Proxy.create({})), false);
assertEq(isFunction(Proxy.create({})), false);
assertEq(isFunction2(Proxy.create({})), false);
assertEq(isNumber(Proxy.create({})), false);
assertEq(isNumber2(Proxy.create({})), false);
assertEq(isString(Proxy.create({})), false);
assertEq(isString2(Proxy.create({})), false);
assertEq(isUndefined(Proxy.create({})), false);
assertEq(isUndefined2(Proxy.create({})), false);
assertEq(isBanana(Proxy.create({})), false);
assertEq(isBanana2(Proxy.create({})), false);
assertEq(isObject(true), false);
assertEq(isObject2(true), false);
assertEq(isBoolean(true), true);
assertEq(isBoolean2(true), true);
assertEq(isFunction(true), false);
assertEq(isFunction2(true), false);
assertEq(isNumber(true), false);
assertEq(isNumber2(true), false);
assertEq(isString(true), false);
assertEq(isString2(true), false);
assertEq(isUndefined(true), false);
assertEq(isUndefined2(true), false);
assertEq(isBanana(true), false);
assertEq(isBanana2(true), false);
assertEq(isObject(false), false);
assertEq(isObject2(false), false);
assertEq(isBoolean(false), true);
assertEq(isBoolean2(false), true);
assertEq(isFunction(false), false);
assertEq(isFunction2(false), false);
assertEq(isNumber(false), false);
assertEq(isNumber2(false), false);
assertEq(isString(false), false);
assertEq(isString2(false), false);
assertEq(isUndefined(false), false);
assertEq(isUndefined2(false), false);
assertEq(isBanana(false), false);
assertEq(isBanana2(false), false);
assertEq(isObject(Function.prototype), false);
assertEq(isObject2(Function.prototype), false);
assertEq(isBoolean(Function.prototype), false);
assertEq(isBoolean2(Function.prototype), false);
assertEq(isFunction(Function.prototype), true);
assertEq(isFunction2(Function.prototype), true);
assertEq(isNumber(Function.prototype), false);
assertEq(isNumber2(Function.prototype), false);
assertEq(isString(Function.prototype), false);
assertEq(isString2(Function.prototype), false);
assertEq(isUndefined(Function.prototype), false);
assertEq(isUndefined2(Function.prototype), false);
assertEq(isBanana(Function.prototype), false);
assertEq(isBanana2(Function.prototype), false);
assertEq(isObject(eval), false);
assertEq(isObject2(eval), false);
assertEq(isBoolean(eval), false);
assertEq(isBoolean2(eval), false);
assertEq(isFunction(eval), true);
assertEq(isFunction2(eval), true);
assertEq(isNumber(eval), false);
assertEq(isNumber2(eval), false);
assertEq(isString(eval), false);
assertEq(isString2(eval), false);
assertEq(isUndefined(eval), false);
assertEq(isUndefined2(eval), false);
assertEq(isBanana(eval), false);
assertEq(isBanana2(eval), false);
assertEq(isObject((function () {}).bind()), false);
assertEq(isObject2((function () {}).bind()), false);
assertEq(isBoolean((function () {}).bind()), false);
assertEq(isBoolean2((function () {}).bind()), false);
assertEq(isFunction((function () {}).bind()), true);
assertEq(isFunction2((function () {}).bind()), true);
assertEq(isNumber((function () {}).bind()), false);
assertEq(isNumber2((function () {}).bind()), false);
assertEq(isString((function () {}).bind()), false);
assertEq(isString2((function () {}).bind()), false);
assertEq(isUndefined((function () {}).bind()), false);
assertEq(isUndefined2((function () {}).bind()), false);
assertEq(isBanana((function () {}).bind()), false);
assertEq(isBanana2((function () {}).bind()), false);
assertEq(isObject(eval), false);
assertEq(isObject2(eval), false);
assertEq(isBoolean(eval), false);
assertEq(isBoolean2(eval), false);
assertEq(isFunction(eval), true);
assertEq(isFunction2(eval), true);
assertEq(isNumber(eval), false);
assertEq(isNumber2(eval), false);
assertEq(isString(eval), false);
assertEq(isString2(eval), false);
assertEq(isUndefined(eval), false);
assertEq(isUndefined2(eval), false);
assertEq(isBanana(eval), false);
assertEq(isBanana2(eval), false);
assertEq(isObject(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isObject2(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isBoolean(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isBoolean2(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isFunction(Proxy.createFunction({}, function () {}, function () {})), true);
assertEq(isFunction2(Proxy.createFunction({}, function () {}, function () {})), true);
assertEq(isNumber(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isNumber2(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isString(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isString2(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isUndefined(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isUndefined2(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isBanana(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isBanana2(Proxy.createFunction({}, function () {}, function () {})), false);
assertEq(isObject(1.5), false);
assertEq(isObject2(1.5), false);
assertEq(isBoolean(1.5), false);
assertEq(isBoolean2(1.5), false);
assertEq(isFunction(1.5), false);
assertEq(isFunction2(1.5), false);
assertEq(isNumber(1.5), true);
assertEq(isNumber2(1.5), true);
assertEq(isString(1.5), false);
assertEq(isString2(1.5), false);
assertEq(isUndefined(1.5), false);
assertEq(isUndefined2(1.5), false);
assertEq(isBanana(1.5), false);
assertEq(isBanana2(1.5), false);
assertEq(isObject(30), false);
assertEq(isObject2(30), false);
assertEq(isBoolean(30), false);
assertEq(isBoolean2(30), false);
assertEq(isFunction(30), false);
assertEq(isFunction2(30), false);
assertEq(isNumber(30), true);
assertEq(isNumber2(30), true);
assertEq(isString(30), false);
assertEq(isString2(30), false);
assertEq(isUndefined(30), false);
assertEq(isUndefined2(30), false);
assertEq(isBanana(30), false);
assertEq(isBanana2(30), false);
assertEq(isObject(NaN), false);
assertEq(isObject2(NaN), false);
assertEq(isBoolean(NaN), false);
assertEq(isBoolean2(NaN), false);
assertEq(isFunction(NaN), false);
assertEq(isFunction2(NaN), false);
assertEq(isNumber(NaN), true);
assertEq(isNumber2(NaN), true);
assertEq(isString(NaN), false);
assertEq(isString2(NaN), false);
assertEq(isUndefined(NaN), false);
assertEq(isUndefined2(NaN), false);
assertEq(isBanana(NaN), false);
assertEq(isBanana2(NaN), false);
assertEq(isObject("test"), false);
assertEq(isObject2("test"), false);
assertEq(isBoolean("test"), false);
assertEq(isBoolean2("test"), false);
assertEq(isFunction("test"), false);
assertEq(isFunction2("test"), false);
assertEq(isNumber("test"), false);
assertEq(isNumber2("test"), false);
assertEq(isString("test"), true);
assertEq(isString2("test"), true);
assertEq(isUndefined("test"), false);
assertEq(isUndefined2("test"), false);
assertEq(isBanana("test"), false);
assertEq(isBanana2("test"), false);
assertEq(isObject(undefined), false);
assertEq(isObject2(undefined), false);
assertEq(isBoolean(undefined), false);
assertEq(isBoolean2(undefined), false);
assertEq(isFunction(undefined), false);
assertEq(isFunction2(undefined), false);
assertEq(isNumber(undefined), false);
assertEq(isNumber2(undefined), false);
assertEq(isString(undefined), false);
assertEq(isString2(undefined), false);
assertEq(isUndefined(undefined), true);
assertEq(isUndefined2(undefined), true);
assertEq(isBanana(undefined), false);
assertEq(isBanana2(undefined), false);
}