Fixed compare bugs. Report results from js2 test cases. Rewrote generic
equal to match ECMA 1.5 git-svn-id: svn://10.0.0.236/trunk@82354 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -1442,12 +1442,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(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<BinaryStmtNode *>(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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
#include <cstring>
|
||||
#include <cfloat>
|
||||
#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
|
||||
|
||||
@@ -1442,12 +1442,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(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<BinaryStmtNode *>(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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
#include <cstring>
|
||||
#include <cfloat>
|
||||
#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
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user