diff --git a/mozilla/js/js2/icodegenerator.cpp b/mozilla/js/js2/icodegenerator.cpp index d0c86871f5e..b12d9201e19 100644 --- a/mozilla/js/js2/icodegenerator.cpp +++ b/mozilla/js/js2/icodegenerator.cpp @@ -1442,12 +1442,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r2, r1); + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); // will generate equal/identical code if (trueBranch || falseBranch) { if (trueBranch == NULL) - branchFalse(falseBranch, ret); + branchTrue(falseBranch, ret); else { - branchTrue(trueBranch, ret); + branchFalse(trueBranch, ret); if (falseBranch) branch(falseBranch); } @@ -2104,11 +2104,13 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) case StmtNode::IfElse: { Label *falseLabel = getLabel(); + Label *trueLabel = getLabel(); Label *beyondLabel = getLabel(); BinaryStmtNode *i = static_cast(p); - TypedRegister c = genExpr(i->expr, false, NULL, falseLabel); + TypedRegister c = genExpr(i->expr, false, trueLabel, falseLabel); if (!generatedBoolean(i->expr)) branchFalse(falseLabel, test(c)); + setLabel(trueLabel); genStmt(i->stmt); branch(beyondLabel); setLabel(falseLabel); diff --git a/mozilla/js/js2/interpreter.cpp b/mozilla/js/js2/interpreter.cpp index 80185b04ff8..ab07962d6b5 100644 --- a/mozilla/js/js2/interpreter.cpp +++ b/mozilla/js/js2/interpreter.cpp @@ -372,7 +372,7 @@ static JSValue less_Default(const JSValue& r1, const JSValue& r2) lv = lv.toNumber(); rv = rv.toNumber(); if (lv.isNaN() || rv.isNaN()) - return JSValue(); + return kFalseValue; else return JSValue(lv.f64 < rv.f64); } @@ -388,26 +388,48 @@ static JSValue lessOrEqual_Default(const JSValue& r1, const JSValue& r2) lv = lv.toNumber(); rv = rv.toNumber(); if (lv.isNaN() || rv.isNaN()) - return JSValue(); + return kFalseValue; else return JSValue(lv.f64 <= rv.f64); } } static JSValue equal_Default(const JSValue& r1, const JSValue& r2) { - JSValue lv = r1.toPrimitive(JSValue::Number); - JSValue rv = r2.toPrimitive(JSValue::Number); - if (lv.isString() && rv.isString()) { - return JSValue(bool(lv.string->compare(*rv.string) == 0)); + if (r1.isSameType(r2)) { + if (r1.isUndefined()) return kTrueValue; + if (r1.isNull()) return kTrueValue; + if (r1.isNumber()) { + JSValue lv = r1.toNumber(); // make sure we have f64's + JSValue rv = r2.toNumber(); + if (lv.isNaN() || rv.isNaN()) + return kFalseValue; + else + return JSValue(lv.f64 == rv.f64); // does the right thing for +/- 0 + } + if (r1.isString()) + return JSValue(bool(r1.string->compare(*r2.string) == 0)); + if (r1.isBoolean()) + return JSValue(bool(r1.boolean == r2.boolean)); + if (r1.isObject()) + return JSValue(bool(r1.object == r2.object)); } - else { - lv = lv.toNumber(); - rv = rv.toNumber(); - if (lv.isNaN() || rv.isNaN()) - return JSValue(); - else - return JSValue(lv.f64 == rv.f64); + else { // different types + if (r1.isNull() && r2.isUndefined()) return kTrueValue; + if (r2.isNull() && r1.isUndefined()) return kTrueValue; + if (r1.isNumber() && r2.isString()) + return equal_Default(r1, r2.toNumber()); + if (r2.isNumber() && r1.isString()) + return equal_Default(r1.toNumber(), r2); + if (r1.isBoolean()) + return equal_Default(r1.toNumber(), r2); + if (r2.isBoolean()) + return equal_Default(r1, r2.toNumber()); + if ((r1.isString() || r1.isNumber()) && r2.isObject()) + return equal_Default(r1, r2.toPrimitive()); + if ((r2.isString() || r2.isNumber()) && r1.isObject()) + return equal_Default(r1.toPrimitive(), r2); } + return kFalseValue; } static JSValue identical_Default(const JSValue& r1, const JSValue& r2) { diff --git a/mozilla/js/js2/js2.cpp b/mozilla/js/js2/js2.cpp index d16177044df..8a999d71cf0 100644 --- a/mozilla/js/js2/js2.cpp +++ b/mozilla/js/js2/js2.cpp @@ -347,7 +347,8 @@ static void testCompile() icg.genStmt(s); s = s->next; } - cx.interpret(icg.complete(&Void_Type), JSValues()); + JSValue result = cx.interpret(icg.complete(&Void_Type), JSValues()); + stdOut << "result = " << result << "\n"; } } diff --git a/mozilla/js/js2/jstypes.cpp b/mozilla/js/js2/jstypes.cpp index e85fb4d0a38..f36d2fee532 100644 --- a/mozilla/js/js2/jstypes.cpp +++ b/mozilla/js/js2/jstypes.cpp @@ -267,7 +267,7 @@ static JSValue array_constructor(Context *, const JSValues& argv) return JSValue(result); } else - return JSValue(new JSArray(JSValue::valueToInteger(argv[1]).i32)); + return JSValue(new JSArray(JSValue::valueToInt32(argv[1]).i32)); else return JSValue(new JSArray()); } @@ -358,15 +358,6 @@ JSType Date_Type = JSType(widenCString("Date"), NULL, new JSNativeFunction(date_ // the canonical undefined value, etc. -const JSValue kUndefinedValue; -const JSValue kNaNValue = JSValue(nan); -const JSValue kTrueValue = JSValue(true); -const JSValue kFalseValue = JSValue(false); -const JSValue kNullValue = JSValue((JSObject*)NULL); -const JSValue kNegativeZero = JSValue(-0.0); -const JSValue kPositiveZero = JSValue(0.0); -const JSValue kNegativeInfinity = JSValue(negativeInfinity); -const JSValue kPositiveInfinity = JSValue(positiveInfinity); const JSType *JSValue::getType() const @@ -712,10 +703,10 @@ JSValue JSValue::valueToInteger(const JSValue& value) { JSValue result = valueToNumber(value); ASSERT(result.tag == f64_tag); - result.tag = i32_tag; + result.tag = integer_tag; bool neg = (result.f64 < 0); - result.i32 = (int32)floor((neg) ? -result.f64 : result.f64); - result.i32 = (neg) ? -result.i32 : result.i32; + result.f64 = floor((neg) ? -result.f64 : result.f64); + result.f64 = (neg) ? -result.f64 : result.f64; return result; } diff --git a/mozilla/js/js2/jstypes.h b/mozilla/js/js2/jstypes.h index ecbed79258d..70bc6a4d495 100644 --- a/mozilla/js/js2/jstypes.h +++ b/mozilla/js/js2/jstypes.h @@ -105,7 +105,7 @@ namespace JSTypes { f32_tag, f64_tag, integer_tag, object_tag, array_tag, function_tag, string_tag, boolean_tag, type_tag, - undefined_tag, + undefined_tag, null_tag, uninitialized_tag } Tag; Tag tag; @@ -145,7 +145,7 @@ namespace JSTypes { bool isInitialized() const { return (tag != uninitialized_tag); } bool isUndefined() const { return (tag == undefined_tag); } - bool isNull() const { return ((tag == object_tag) && (this->object == NULL)); } + bool isNull() const { return (tag == null_tag); } bool isNaN() const; bool isNegativeInfinity() const; bool isPositiveInfinity() const; @@ -173,6 +173,16 @@ namespace JSTypes { const JSType *getType() const; // map from tag type to JS2 type + bool isSameType(const JSValue &other) const + { + const JSType *thisType = getType(); + const JSType *otherType = other.getType(); + if (thisType == otherType) + return true; + if (isNumber() && other.isNumber()) + return true; + return false; + } int operator==(const JSValue& value) const; }; diff --git a/mozilla/js/js2/numerics.cpp b/mozilla/js/js2/numerics.cpp index 58d4edbddf5..f7a6088bf99 100644 --- a/mozilla/js/js2/numerics.cpp +++ b/mozilla/js/js2/numerics.cpp @@ -22,9 +22,11 @@ #include #include #include "numerics.h" +#include "jstypes.h" namespace JS = JavaScript; using namespace JavaScript; +using namespace JSTypes; // @@ -225,6 +227,15 @@ InitNumerics::InitNumerics() word1(nan) = 0xFFFFFFFF; } +const JSValue JSTypes::kUndefinedValue; +const JSValue JSTypes::kNaNValue = JSValue(nan); +const JSValue JSTypes::kTrueValue = JSValue(true); +const JSValue JSTypes::kFalseValue = JSValue(false); +const JSValue JSTypes::kNullValue = JSValue(JSValue::Tag::null_tag); +const JSValue JSTypes::kNegativeZero = JSValue(-0.0); +const JSValue JSTypes::kPositiveZero = JSValue(0.0); +const JSValue JSTypes::kNegativeInfinity = JSValue(negativeInfinity); +const JSValue JSTypes::kPositiveInfinity = JSValue(positiveInfinity); // // Portable double-precision floating point to string and back conversions diff --git a/mozilla/js2/src/icodegenerator.cpp b/mozilla/js2/src/icodegenerator.cpp index d0c86871f5e..b12d9201e19 100644 --- a/mozilla/js2/src/icodegenerator.cpp +++ b/mozilla/js2/src/icodegenerator.cpp @@ -1442,12 +1442,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r2, r1); + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); // will generate equal/identical code if (trueBranch || falseBranch) { if (trueBranch == NULL) - branchFalse(falseBranch, ret); + branchTrue(falseBranch, ret); else { - branchTrue(trueBranch, ret); + branchFalse(trueBranch, ret); if (falseBranch) branch(falseBranch); } @@ -2104,11 +2104,13 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) case StmtNode::IfElse: { Label *falseLabel = getLabel(); + Label *trueLabel = getLabel(); Label *beyondLabel = getLabel(); BinaryStmtNode *i = static_cast(p); - TypedRegister c = genExpr(i->expr, false, NULL, falseLabel); + TypedRegister c = genExpr(i->expr, false, trueLabel, falseLabel); if (!generatedBoolean(i->expr)) branchFalse(falseLabel, test(c)); + setLabel(trueLabel); genStmt(i->stmt); branch(beyondLabel); setLabel(falseLabel); diff --git a/mozilla/js2/src/interpreter.cpp b/mozilla/js2/src/interpreter.cpp index 80185b04ff8..ab07962d6b5 100644 --- a/mozilla/js2/src/interpreter.cpp +++ b/mozilla/js2/src/interpreter.cpp @@ -372,7 +372,7 @@ static JSValue less_Default(const JSValue& r1, const JSValue& r2) lv = lv.toNumber(); rv = rv.toNumber(); if (lv.isNaN() || rv.isNaN()) - return JSValue(); + return kFalseValue; else return JSValue(lv.f64 < rv.f64); } @@ -388,26 +388,48 @@ static JSValue lessOrEqual_Default(const JSValue& r1, const JSValue& r2) lv = lv.toNumber(); rv = rv.toNumber(); if (lv.isNaN() || rv.isNaN()) - return JSValue(); + return kFalseValue; else return JSValue(lv.f64 <= rv.f64); } } static JSValue equal_Default(const JSValue& r1, const JSValue& r2) { - JSValue lv = r1.toPrimitive(JSValue::Number); - JSValue rv = r2.toPrimitive(JSValue::Number); - if (lv.isString() && rv.isString()) { - return JSValue(bool(lv.string->compare(*rv.string) == 0)); + if (r1.isSameType(r2)) { + if (r1.isUndefined()) return kTrueValue; + if (r1.isNull()) return kTrueValue; + if (r1.isNumber()) { + JSValue lv = r1.toNumber(); // make sure we have f64's + JSValue rv = r2.toNumber(); + if (lv.isNaN() || rv.isNaN()) + return kFalseValue; + else + return JSValue(lv.f64 == rv.f64); // does the right thing for +/- 0 + } + if (r1.isString()) + return JSValue(bool(r1.string->compare(*r2.string) == 0)); + if (r1.isBoolean()) + return JSValue(bool(r1.boolean == r2.boolean)); + if (r1.isObject()) + return JSValue(bool(r1.object == r2.object)); } - else { - lv = lv.toNumber(); - rv = rv.toNumber(); - if (lv.isNaN() || rv.isNaN()) - return JSValue(); - else - return JSValue(lv.f64 == rv.f64); + else { // different types + if (r1.isNull() && r2.isUndefined()) return kTrueValue; + if (r2.isNull() && r1.isUndefined()) return kTrueValue; + if (r1.isNumber() && r2.isString()) + return equal_Default(r1, r2.toNumber()); + if (r2.isNumber() && r1.isString()) + return equal_Default(r1.toNumber(), r2); + if (r1.isBoolean()) + return equal_Default(r1.toNumber(), r2); + if (r2.isBoolean()) + return equal_Default(r1, r2.toNumber()); + if ((r1.isString() || r1.isNumber()) && r2.isObject()) + return equal_Default(r1, r2.toPrimitive()); + if ((r2.isString() || r2.isNumber()) && r1.isObject()) + return equal_Default(r1.toPrimitive(), r2); } + return kFalseValue; } static JSValue identical_Default(const JSValue& r1, const JSValue& r2) { diff --git a/mozilla/js2/src/jstypes.cpp b/mozilla/js2/src/jstypes.cpp index e85fb4d0a38..f36d2fee532 100644 --- a/mozilla/js2/src/jstypes.cpp +++ b/mozilla/js2/src/jstypes.cpp @@ -267,7 +267,7 @@ static JSValue array_constructor(Context *, const JSValues& argv) return JSValue(result); } else - return JSValue(new JSArray(JSValue::valueToInteger(argv[1]).i32)); + return JSValue(new JSArray(JSValue::valueToInt32(argv[1]).i32)); else return JSValue(new JSArray()); } @@ -358,15 +358,6 @@ JSType Date_Type = JSType(widenCString("Date"), NULL, new JSNativeFunction(date_ // the canonical undefined value, etc. -const JSValue kUndefinedValue; -const JSValue kNaNValue = JSValue(nan); -const JSValue kTrueValue = JSValue(true); -const JSValue kFalseValue = JSValue(false); -const JSValue kNullValue = JSValue((JSObject*)NULL); -const JSValue kNegativeZero = JSValue(-0.0); -const JSValue kPositiveZero = JSValue(0.0); -const JSValue kNegativeInfinity = JSValue(negativeInfinity); -const JSValue kPositiveInfinity = JSValue(positiveInfinity); const JSType *JSValue::getType() const @@ -712,10 +703,10 @@ JSValue JSValue::valueToInteger(const JSValue& value) { JSValue result = valueToNumber(value); ASSERT(result.tag == f64_tag); - result.tag = i32_tag; + result.tag = integer_tag; bool neg = (result.f64 < 0); - result.i32 = (int32)floor((neg) ? -result.f64 : result.f64); - result.i32 = (neg) ? -result.i32 : result.i32; + result.f64 = floor((neg) ? -result.f64 : result.f64); + result.f64 = (neg) ? -result.f64 : result.f64; return result; } diff --git a/mozilla/js2/src/jstypes.h b/mozilla/js2/src/jstypes.h index ecbed79258d..70bc6a4d495 100644 --- a/mozilla/js2/src/jstypes.h +++ b/mozilla/js2/src/jstypes.h @@ -105,7 +105,7 @@ namespace JSTypes { f32_tag, f64_tag, integer_tag, object_tag, array_tag, function_tag, string_tag, boolean_tag, type_tag, - undefined_tag, + undefined_tag, null_tag, uninitialized_tag } Tag; Tag tag; @@ -145,7 +145,7 @@ namespace JSTypes { bool isInitialized() const { return (tag != uninitialized_tag); } bool isUndefined() const { return (tag == undefined_tag); } - bool isNull() const { return ((tag == object_tag) && (this->object == NULL)); } + bool isNull() const { return (tag == null_tag); } bool isNaN() const; bool isNegativeInfinity() const; bool isPositiveInfinity() const; @@ -173,6 +173,16 @@ namespace JSTypes { const JSType *getType() const; // map from tag type to JS2 type + bool isSameType(const JSValue &other) const + { + const JSType *thisType = getType(); + const JSType *otherType = other.getType(); + if (thisType == otherType) + return true; + if (isNumber() && other.isNumber()) + return true; + return false; + } int operator==(const JSValue& value) const; }; diff --git a/mozilla/js2/src/numerics.cpp b/mozilla/js2/src/numerics.cpp index 58d4edbddf5..f7a6088bf99 100644 --- a/mozilla/js2/src/numerics.cpp +++ b/mozilla/js2/src/numerics.cpp @@ -22,9 +22,11 @@ #include #include #include "numerics.h" +#include "jstypes.h" namespace JS = JavaScript; using namespace JavaScript; +using namespace JSTypes; // @@ -225,6 +227,15 @@ InitNumerics::InitNumerics() word1(nan) = 0xFFFFFFFF; } +const JSValue JSTypes::kUndefinedValue; +const JSValue JSTypes::kNaNValue = JSValue(nan); +const JSValue JSTypes::kTrueValue = JSValue(true); +const JSValue JSTypes::kFalseValue = JSValue(false); +const JSValue JSTypes::kNullValue = JSValue(JSValue::Tag::null_tag); +const JSValue JSTypes::kNegativeZero = JSValue(-0.0); +const JSValue JSTypes::kPositiveZero = JSValue(0.0); +const JSValue JSTypes::kNegativeInfinity = JSValue(negativeInfinity); +const JSValue JSTypes::kPositiveInfinity = JSValue(positiveInfinity); // // Portable double-precision floating point to string and back conversions diff --git a/mozilla/js2/tests/cpp/js2_shell.cpp b/mozilla/js2/tests/cpp/js2_shell.cpp index d16177044df..8a999d71cf0 100644 --- a/mozilla/js2/tests/cpp/js2_shell.cpp +++ b/mozilla/js2/tests/cpp/js2_shell.cpp @@ -347,7 +347,8 @@ static void testCompile() icg.genStmt(s); s = s->next; } - cx.interpret(icg.complete(&Void_Type), JSValues()); + JSValue result = cx.interpret(icg.complete(&Void_Type), JSValues()); + stdOut << "result = " << result << "\n"; } }