diff --git a/js/js2/icodegenerator.cpp b/js/js2/icodegenerator.cpp index 58d01e1b8ad5..fba28abc33b9 100644 --- a/js/js2/icodegenerator.cpp +++ b/js/js2/icodegenerator.cpp @@ -245,9 +245,9 @@ TypedRegister ICodeGenerator::newArray() -TypedRegister ICodeGenerator::loadName(const StringAtom &name) +TypedRegister ICodeGenerator::loadName(const StringAtom &name, JSType *t) { - TypedRegister dest(getTempRegister(), &Any_Type); + TypedRegister dest(getTempRegister(), t); LoadName *instr = new LoadName(dest, &name); iCode->push_back(instr); return dest; @@ -444,10 +444,17 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1, TypedRegister source2) { ASSERT(source1.first != NotARegister); - ASSERT(source2.first != NotARegister); + ASSERT(source2.first != NotARegister); TypedRegister dest(getTempRegister(), &Any_Type); - GenericBinaryOP *instr = new GenericBinaryOP(dest, BinaryOperator::mapICodeOp(op), source1, source2); - iCode->push_back(instr); + + if ((source1.second == &Number_Type) && (source2.second == &Number_Type)) { + Arithmetic *instr = new Arithmetic(op, dest, source1, source2); + iCode->push_back(instr); + } + else { + GenericBinaryOP *instr = new GenericBinaryOP(dest, BinaryOperator::mapICodeOp(op), source1, source2); + iCode->push_back(instr); + } return dest; } @@ -735,7 +742,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode:: case Var: break; case Name: - v = loadName(name); + v = loadName(name, v.second); break; case Slot: v = getSlot(thisBase, slotIndex); @@ -747,7 +754,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode:: default: NOT_REACHED("Bad lvalue kind"); } - ret = op(mapExprNodeToICodeOp(use), v, ret); + ret = binaryOp(mapExprNodeToICodeOp(use), v, ret); // fall thru... case ExprNode::assignment: switch (lValueKind) { @@ -774,7 +781,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode:: ret = v; break; case Name: - ret = loadName(name); + ret = loadName(name, v.second); break; case Slot: ret = getSlot(thisBase, slotIndex); @@ -791,20 +798,20 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode:: case ExprNode::preIncrement: switch (lValueKind) { case Var: - ret = op(xcrementOp, v, loadImmediate(1.0)); + ret = binaryOp(xcrementOp, v, loadImmediate(1.0)); break; case Name: - ret = loadName(name); - ret = op(xcrementOp, ret, loadImmediate(1.0)); + ret = loadName(name, v.second); + ret = binaryOp(xcrementOp, ret, loadImmediate(1.0)); saveName(name, ret); break; case Slot: - ret = op(xcrementOp, getSlot(thisBase, slotIndex), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getSlot(thisBase, slotIndex), loadImmediate(1.0)); setSlot(thisBase, slotIndex, ret); break; case Static: case Constructor: - ret = op(xcrementOp, getStatic(mClass, name), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getStatic(mClass, name), loadImmediate(1.0)); setStatic(mClass, name, ret); break; default: @@ -900,7 +907,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I } } if ((lValueKind == Property) && (base.first == NotARegister)) - base = loadName(baseName); + base = loadName(baseName, base.second); } else { base = genExpr(b->op1); @@ -961,7 +968,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I ret = v; break; } - ret = op(mapExprNodeToICodeOp(use), v, ret); + ret = binaryOp(mapExprNodeToICodeOp(use), v, ret); // fall thru... case ExprNode::assignment: switch (lValueKind) { @@ -1000,15 +1007,15 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I switch (lValueKind) { case Constructor: case Static: - ret = op(xcrementOp, getStatic(clazz, fieldName), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getStatic(clazz, fieldName), loadImmediate(1.0)); setStatic(clazz, fieldName, ret); break; case Property: - ret = op(xcrementOp, getProperty(base, fieldName), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getProperty(base, fieldName), loadImmediate(1.0)); setProperty(base, fieldName, ret); break; case Slot: - ret = op(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0)); setSlot(base, slotIndex, ret); break; default: @@ -1182,7 +1189,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, TypedRegister base = genExpr(b->op1); TypedRegister index = genExpr(b->op2); ret = getElement(base, index); - ret = op(xcrementOp, ret, loadImmediate(1.0)); + ret = binaryOp(xcrementOp, ret, loadImmediate(1.0)); setElement(base, index, ret); } else @@ -1237,11 +1244,6 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - - if ((r1.second == &Integer_Type) && (r2.second == &Integer_Type)) { - op(mapExprNodeToICodeOp(p->getKind()), r1, r2); - } - ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); } break; @@ -1296,7 +1298,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, TypedRegister base = genExpr(lb->op1); TypedRegister index = genExpr(lb->op2); TypedRegister v = getElement(base, index); - ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret); + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), v, ret); setElement(base, index, ret); } else @@ -1313,7 +1315,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2); + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); if (trueBranch || falseBranch) { if (trueBranch == NULL) branchFalse(falseBranch, ret); @@ -1331,7 +1333,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - ret = op(mapExprNodeToICodeOp(p->getKind()), r2, r1); // will return reverse case + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r2, r1); // will return reverse case if (trueBranch || falseBranch) { if (trueBranch == NULL) branchFalse(falseBranch, ret); @@ -1350,7 +1352,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2); + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); if (trueBranch || falseBranch) { if (trueBranch == NULL) branchFalse(falseBranch, ret); @@ -1855,7 +1857,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) setLabel(nextCaseLabel); nextCaseLabel = getLabel(); TypedRegister r = genExpr(c->expr); - TypedRegister eq = op(COMPARE_EQ, r, sc); + TypedRegister eq = binaryOp(COMPARE_EQ, r, sc); lastBranch = branchFalse(nextCaseLabel, eq); } else { diff --git a/js/js2/icodegenerator.h b/js/js2/icodegenerator.h index 83f4a42e5304..10e69ddfeb28 100644 --- a/js/js2/icodegenerator.h +++ b/js/js2/icodegenerator.h @@ -265,7 +265,7 @@ namespace ICG { TypedRegister cast(TypedRegister arg, JSType *toType); TypedRegister super(); - TypedRegister loadName(const StringAtom &name); + TypedRegister loadName(const StringAtom &name, JSType *t = &Any_Type); void saveName(const StringAtom &name, TypedRegister value); TypedRegister nameXcr(const StringAtom &name, ICodeOp op); diff --git a/js/js2/interpreter.cpp b/js/js2/interpreter.cpp index 8a41e41bf967..b708491e3328 100644 --- a/js/js2/interpreter.cpp +++ b/js/js2/interpreter.cpp @@ -1011,49 +1011,182 @@ using JSString throughout. } } break; + case SHIFTLEFT: - case SHIFTRIGHT: - case USHIFTRIGHT: - case AND: - case OR: - case XOR: - case ADD: - case SUBTRACT: - case MULTIPLY: - case DIVIDE: - case REMAINDER: - case COMPARE_LT: - case COMPARE_LE: - case COMPARE_EQ: - case STRICT_EQ: { - // - // XXX if Package 'Operators' has not been seen, these operators cannot have been - // overridden, so we should use a different dispatch and execute the default - // behaviour inline instead, - // Arithmetic* a = static_cast(instruction); JSValue& dest = (*registers)[dst(a).first]; JSValue& r1 = (*registers)[src1(a).first]; JSValue& r2 = (*registers)[src2(a).first]; - const JSValue ovr = findBinaryOverride(r1, r2, BinaryOperator::mapICodeOp(instruction->op())); - JSFunction *target = ovr.function; - if (target->isNative()) { - JSValues argv(2); - argv[0] = r1; - argv[1] = r2; - dest = static_cast(target)->mCode(r1, r2); - break; - } - else { - mLinkage = new Linkage(mLinkage, ++mPC, - mActivation, mGlobal, dst(a)); - mActivation = new Activation(target->getICode(), r1, r2); - registers = &mActivation->mRegisters; - mPC = mActivation->mICode->its_iCode->begin(); - endPC = mActivation->mICode->its_iCode->end(); - continue; - } + JSValue num1(r1.toInt32()); + JSValue num2(r2.toUInt32()); + dest = JSValue(num1.i32 << (num2.u32 & 0x1F)); + } + break; + case SHIFTRIGHT: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toInt32()); + JSValue num2(r2.toUInt32()); + dest = JSValue(num1.i32 >> (num2.u32 & 0x1F)); + } + break; + case USHIFTRIGHT: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toUInt32()); + JSValue num2(r2.toUInt32()); + dest = JSValue(num1.u32 >> (num2.u32 & 0x1F)); + } + break; + case AND: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toInt32()); + JSValue num2(r2.toInt32()); + dest = JSValue(num1.i32 & num2.i32); + } + break; + case OR: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toInt32()); + JSValue num2(r2.toInt32()); + dest = JSValue(num1.i32 | num2.i32); + } + break; + case XOR: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toInt32()); + JSValue num2(r2.toInt32()); + dest = JSValue(num1.i32 ^ num2.i32); + } + break; + case ADD: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(r1.f64 + r2.f64); + } + break; + case SUBTRACT: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(r1.f64 - r2.f64); + } + break; + case MULTIPLY: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(r1.f64 * r2.f64); + } + break; + case DIVIDE: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(r1.f64 / r2.f64); + } + break; + case REMAINDER: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(fmod(r1.f64, r2.f64)); + } + break; + case COMPARE_LT: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + if (r1.isNaN() || r2.isNaN()) + dest = JSValue(); + else + dest = JSValue(r1.f64 < r2.f64); + } + break; + case COMPARE_LE: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + if (r1.isNaN() || r2.isNaN()) + dest = JSValue(); + else + dest = JSValue(r1.f64 <= r2.f64); + } + break; + case COMPARE_EQ: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + if (r1.isNaN() || r2.isNaN()) + dest = JSValue(); + else + dest = JSValue(r1.f64 == r2.f64); + } + break; + case STRICT_EQ: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + if (r1.isNaN() || r2.isNaN()) + dest = kFalseValue; + else + dest = JSValue(r1.f64 == r2.f64); } break; diff --git a/js/js2/js2.cpp b/js/js2/js2.cpp index 29ad3ed83030..58359bc624d3 100644 --- a/js/js2/js2.cpp +++ b/js/js2/js2.cpp @@ -171,6 +171,15 @@ static JSValue load(Context *cx, const JSValues &argv) return result; } +#include +static JSValue time(Context *cx, const JSValues &argv) +{ + struct _timeb timebuffer; + _ftime(&timebuffer); + + return JSValue((double)timebuffer.time * 1000 + timebuffer.millitm); +} + static void readEvalPrint(FILE *in, World &world) { Context cx(world, &global); @@ -180,6 +189,7 @@ static void readEvalPrint(FILE *in, World &world) global.defineNativeFunction(world.identifiers[widenCString("print")], print); global.defineNativeFunction(world.identifiers[widenCString("dump")], dump); global.defineNativeFunction(world.identifiers[widenCString("load")], load); + global.defineNativeFunction(world.identifiers[widenCString("time")], time); String buffer; string line; diff --git a/js2/src/icodegenerator.cpp b/js2/src/icodegenerator.cpp index 58d01e1b8ad5..fba28abc33b9 100644 --- a/js2/src/icodegenerator.cpp +++ b/js2/src/icodegenerator.cpp @@ -245,9 +245,9 @@ TypedRegister ICodeGenerator::newArray() -TypedRegister ICodeGenerator::loadName(const StringAtom &name) +TypedRegister ICodeGenerator::loadName(const StringAtom &name, JSType *t) { - TypedRegister dest(getTempRegister(), &Any_Type); + TypedRegister dest(getTempRegister(), t); LoadName *instr = new LoadName(dest, &name); iCode->push_back(instr); return dest; @@ -444,10 +444,17 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1, TypedRegister source2) { ASSERT(source1.first != NotARegister); - ASSERT(source2.first != NotARegister); + ASSERT(source2.first != NotARegister); TypedRegister dest(getTempRegister(), &Any_Type); - GenericBinaryOP *instr = new GenericBinaryOP(dest, BinaryOperator::mapICodeOp(op), source1, source2); - iCode->push_back(instr); + + if ((source1.second == &Number_Type) && (source2.second == &Number_Type)) { + Arithmetic *instr = new Arithmetic(op, dest, source1, source2); + iCode->push_back(instr); + } + else { + GenericBinaryOP *instr = new GenericBinaryOP(dest, BinaryOperator::mapICodeOp(op), source1, source2); + iCode->push_back(instr); + } return dest; } @@ -735,7 +742,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode:: case Var: break; case Name: - v = loadName(name); + v = loadName(name, v.second); break; case Slot: v = getSlot(thisBase, slotIndex); @@ -747,7 +754,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode:: default: NOT_REACHED("Bad lvalue kind"); } - ret = op(mapExprNodeToICodeOp(use), v, ret); + ret = binaryOp(mapExprNodeToICodeOp(use), v, ret); // fall thru... case ExprNode::assignment: switch (lValueKind) { @@ -774,7 +781,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode:: ret = v; break; case Name: - ret = loadName(name); + ret = loadName(name, v.second); break; case Slot: ret = getSlot(thisBase, slotIndex); @@ -791,20 +798,20 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode:: case ExprNode::preIncrement: switch (lValueKind) { case Var: - ret = op(xcrementOp, v, loadImmediate(1.0)); + ret = binaryOp(xcrementOp, v, loadImmediate(1.0)); break; case Name: - ret = loadName(name); - ret = op(xcrementOp, ret, loadImmediate(1.0)); + ret = loadName(name, v.second); + ret = binaryOp(xcrementOp, ret, loadImmediate(1.0)); saveName(name, ret); break; case Slot: - ret = op(xcrementOp, getSlot(thisBase, slotIndex), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getSlot(thisBase, slotIndex), loadImmediate(1.0)); setSlot(thisBase, slotIndex, ret); break; case Static: case Constructor: - ret = op(xcrementOp, getStatic(mClass, name), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getStatic(mClass, name), loadImmediate(1.0)); setStatic(mClass, name, ret); break; default: @@ -900,7 +907,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I } } if ((lValueKind == Property) && (base.first == NotARegister)) - base = loadName(baseName); + base = loadName(baseName, base.second); } else { base = genExpr(b->op1); @@ -961,7 +968,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I ret = v; break; } - ret = op(mapExprNodeToICodeOp(use), v, ret); + ret = binaryOp(mapExprNodeToICodeOp(use), v, ret); // fall thru... case ExprNode::assignment: switch (lValueKind) { @@ -1000,15 +1007,15 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I switch (lValueKind) { case Constructor: case Static: - ret = op(xcrementOp, getStatic(clazz, fieldName), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getStatic(clazz, fieldName), loadImmediate(1.0)); setStatic(clazz, fieldName, ret); break; case Property: - ret = op(xcrementOp, getProperty(base, fieldName), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getProperty(base, fieldName), loadImmediate(1.0)); setProperty(base, fieldName, ret); break; case Slot: - ret = op(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0)); + ret = binaryOp(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0)); setSlot(base, slotIndex, ret); break; default: @@ -1182,7 +1189,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, TypedRegister base = genExpr(b->op1); TypedRegister index = genExpr(b->op2); ret = getElement(base, index); - ret = op(xcrementOp, ret, loadImmediate(1.0)); + ret = binaryOp(xcrementOp, ret, loadImmediate(1.0)); setElement(base, index, ret); } else @@ -1237,11 +1244,6 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - - if ((r1.second == &Integer_Type) && (r2.second == &Integer_Type)) { - op(mapExprNodeToICodeOp(p->getKind()), r1, r2); - } - ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); } break; @@ -1296,7 +1298,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, TypedRegister base = genExpr(lb->op1); TypedRegister index = genExpr(lb->op2); TypedRegister v = getElement(base, index); - ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret); + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), v, ret); setElement(base, index, ret); } else @@ -1313,7 +1315,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2); + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); if (trueBranch || falseBranch) { if (trueBranch == NULL) branchFalse(falseBranch, ret); @@ -1331,7 +1333,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - ret = op(mapExprNodeToICodeOp(p->getKind()), r2, r1); // will return reverse case + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r2, r1); // will return reverse case if (trueBranch || falseBranch) { if (trueBranch == NULL) branchFalse(falseBranch, ret); @@ -1350,7 +1352,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, BinaryExprNode *b = static_cast(p); TypedRegister r1 = genExpr(b->op1); TypedRegister r2 = genExpr(b->op2); - ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2); + ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); if (trueBranch || falseBranch) { if (trueBranch == NULL) branchFalse(falseBranch, ret); @@ -1855,7 +1857,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) setLabel(nextCaseLabel); nextCaseLabel = getLabel(); TypedRegister r = genExpr(c->expr); - TypedRegister eq = op(COMPARE_EQ, r, sc); + TypedRegister eq = binaryOp(COMPARE_EQ, r, sc); lastBranch = branchFalse(nextCaseLabel, eq); } else { diff --git a/js2/src/icodegenerator.h b/js2/src/icodegenerator.h index 83f4a42e5304..10e69ddfeb28 100644 --- a/js2/src/icodegenerator.h +++ b/js2/src/icodegenerator.h @@ -265,7 +265,7 @@ namespace ICG { TypedRegister cast(TypedRegister arg, JSType *toType); TypedRegister super(); - TypedRegister loadName(const StringAtom &name); + TypedRegister loadName(const StringAtom &name, JSType *t = &Any_Type); void saveName(const StringAtom &name, TypedRegister value); TypedRegister nameXcr(const StringAtom &name, ICodeOp op); diff --git a/js2/src/interpreter.cpp b/js2/src/interpreter.cpp index 8a41e41bf967..b708491e3328 100644 --- a/js2/src/interpreter.cpp +++ b/js2/src/interpreter.cpp @@ -1011,49 +1011,182 @@ using JSString throughout. } } break; + case SHIFTLEFT: - case SHIFTRIGHT: - case USHIFTRIGHT: - case AND: - case OR: - case XOR: - case ADD: - case SUBTRACT: - case MULTIPLY: - case DIVIDE: - case REMAINDER: - case COMPARE_LT: - case COMPARE_LE: - case COMPARE_EQ: - case STRICT_EQ: { - // - // XXX if Package 'Operators' has not been seen, these operators cannot have been - // overridden, so we should use a different dispatch and execute the default - // behaviour inline instead, - // Arithmetic* a = static_cast(instruction); JSValue& dest = (*registers)[dst(a).first]; JSValue& r1 = (*registers)[src1(a).first]; JSValue& r2 = (*registers)[src2(a).first]; - const JSValue ovr = findBinaryOverride(r1, r2, BinaryOperator::mapICodeOp(instruction->op())); - JSFunction *target = ovr.function; - if (target->isNative()) { - JSValues argv(2); - argv[0] = r1; - argv[1] = r2; - dest = static_cast(target)->mCode(r1, r2); - break; - } - else { - mLinkage = new Linkage(mLinkage, ++mPC, - mActivation, mGlobal, dst(a)); - mActivation = new Activation(target->getICode(), r1, r2); - registers = &mActivation->mRegisters; - mPC = mActivation->mICode->its_iCode->begin(); - endPC = mActivation->mICode->its_iCode->end(); - continue; - } + JSValue num1(r1.toInt32()); + JSValue num2(r2.toUInt32()); + dest = JSValue(num1.i32 << (num2.u32 & 0x1F)); + } + break; + case SHIFTRIGHT: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toInt32()); + JSValue num2(r2.toUInt32()); + dest = JSValue(num1.i32 >> (num2.u32 & 0x1F)); + } + break; + case USHIFTRIGHT: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toUInt32()); + JSValue num2(r2.toUInt32()); + dest = JSValue(num1.u32 >> (num2.u32 & 0x1F)); + } + break; + case AND: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toInt32()); + JSValue num2(r2.toInt32()); + dest = JSValue(num1.i32 & num2.i32); + } + break; + case OR: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toInt32()); + JSValue num2(r2.toInt32()); + dest = JSValue(num1.i32 | num2.i32); + } + break; + case XOR: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + JSValue num1(r1.toInt32()); + JSValue num2(r2.toInt32()); + dest = JSValue(num1.i32 ^ num2.i32); + } + break; + case ADD: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(r1.f64 + r2.f64); + } + break; + case SUBTRACT: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(r1.f64 - r2.f64); + } + break; + case MULTIPLY: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(r1.f64 * r2.f64); + } + break; + case DIVIDE: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(r1.f64 / r2.f64); + } + break; + case REMAINDER: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + dest = JSValue(fmod(r1.f64, r2.f64)); + } + break; + case COMPARE_LT: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + if (r1.isNaN() || r2.isNaN()) + dest = JSValue(); + else + dest = JSValue(r1.f64 < r2.f64); + } + break; + case COMPARE_LE: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + if (r1.isNaN() || r2.isNaN()) + dest = JSValue(); + else + dest = JSValue(r1.f64 <= r2.f64); + } + break; + case COMPARE_EQ: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + if (r1.isNaN() || r2.isNaN()) + dest = JSValue(); + else + dest = JSValue(r1.f64 == r2.f64); + } + break; + case STRICT_EQ: + { + Arithmetic* a = static_cast(instruction); + JSValue& dest = (*registers)[dst(a).first]; + JSValue& r1 = (*registers)[src1(a).first]; + JSValue& r2 = (*registers)[src2(a).first]; + ASSERT(r1.isNumber()); + ASSERT(r2.isNumber()); + if (r1.isNaN() || r2.isNaN()) + dest = kFalseValue; + else + dest = JSValue(r1.f64 == r2.f64); } break; diff --git a/js2/tests/cpp/js2_shell.cpp b/js2/tests/cpp/js2_shell.cpp index 29ad3ed83030..58359bc624d3 100644 --- a/js2/tests/cpp/js2_shell.cpp +++ b/js2/tests/cpp/js2_shell.cpp @@ -171,6 +171,15 @@ static JSValue load(Context *cx, const JSValues &argv) return result; } +#include +static JSValue time(Context *cx, const JSValues &argv) +{ + struct _timeb timebuffer; + _ftime(&timebuffer); + + return JSValue((double)timebuffer.time * 1000 + timebuffer.millitm); +} + static void readEvalPrint(FILE *in, World &world) { Context cx(world, &global); @@ -180,6 +189,7 @@ static void readEvalPrint(FILE *in, World &world) global.defineNativeFunction(world.identifiers[widenCString("print")], print); global.defineNativeFunction(world.identifiers[widenCString("dump")], dump); global.defineNativeFunction(world.identifiers[widenCString("load")], load); + global.defineNativeFunction(world.identifiers[widenCString("time")], time); String buffer; string line;