Type targetted binary operators.

Added 'time()' function as native.
This commit is contained in:
rogerl%netscape.com 2000-07-14 01:00:53 +00:00
Родитель 80ba863217
Коммит 9d9a2397fe
8 изменённых файлов: 424 добавлений и 134 удалений

Просмотреть файл

@ -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;
@ -446,8 +446,15 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1,
ASSERT(source1.first != NotARegister);
ASSERT(source2.first != NotARegister);
TypedRegister dest(getTempRegister(), &Any_Type);
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<BinaryExprNode *>(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<BinaryExprNode *>(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<BinaryExprNode *>(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<BinaryExprNode *>(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 {

Просмотреть файл

@ -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);

Просмотреть файл

@ -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<Arithmetic*>(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<JSBinaryOperator*>(target)->mCode(r1, r2);
JSValue num1(r1.toInt32());
JSValue num2(r2.toUInt32());
dest = JSValue(num1.i32 << (num2.u32 & 0x1F));
}
break;
case SHIFTRIGHT:
{
Arithmetic* a = static_cast<Arithmetic*>(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));
}
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;
break;
case USHIFTRIGHT:
{
Arithmetic* a = static_cast<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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;

Просмотреть файл

@ -171,6 +171,15 @@ static JSValue load(Context *cx, const JSValues &argv)
return result;
}
#include <sys/timeb.h>
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;

Просмотреть файл

@ -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;
@ -446,8 +446,15 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1,
ASSERT(source1.first != NotARegister);
ASSERT(source2.first != NotARegister);
TypedRegister dest(getTempRegister(), &Any_Type);
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<BinaryExprNode *>(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<BinaryExprNode *>(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<BinaryExprNode *>(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<BinaryExprNode *>(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 {

Просмотреть файл

@ -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);

Просмотреть файл

@ -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<Arithmetic*>(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<JSBinaryOperator*>(target)->mCode(r1, r2);
JSValue num1(r1.toInt32());
JSValue num2(r2.toUInt32());
dest = JSValue(num1.i32 << (num2.u32 & 0x1F));
}
break;
case SHIFTRIGHT:
{
Arithmetic* a = static_cast<Arithmetic*>(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));
}
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;
break;
case USHIFTRIGHT:
{
Arithmetic* a = static_cast<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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<Arithmetic*>(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;

Просмотреть файл

@ -171,6 +171,15 @@ static JSValue load(Context *cx, const JSValues &argv)
return result;
}
#include <sys/timeb.h>
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;