Sweeping set of changes to implement closures. Also re-targetted entire

front-end to Cobol and back-end now generates pdp11 assembly code in
spanish.
This commit is contained in:
rogerl%netscape.com 2000-12-08 23:55:39 +00:00
parent 9bf885bd61
commit d11b23802a
22 changed files with 962 additions and 528 deletions

View File

@ -26,6 +26,7 @@
DIVIDE, /* dest, source1, source2 */
ELEM_XCR, /* dest, base, index, value */
GENERIC_BINARY_OP, /* dest, op, source1, source2 */
GET_CLOSURE, /* dest, closure depth */
GET_ELEMENT, /* dest, base, index */
GET_METHOD, /* result, target base, index */
GET_PROP, /* dest, object, prop name */
@ -43,6 +44,7 @@
NEGATE, /* dest, source */
NEW_ARRAY, /* dest */
NEW_CLASS, /* dest, class */
NEW_CLOSURE, /* dest, ICodeModule */
NEW_FUNCTION, /* dest, ICodeModule */
NEW_OBJECT, /* dest, constructor */
NOP, /* do nothing and like it */
@ -402,6 +404,22 @@
}
};
class GetClosure : public Instruction_2<TypedRegister, uint32> {
public:
/* dest, closure depth */
GetClosure (TypedRegister aOp1, uint32 aOp2) :
Instruction_2<TypedRegister, uint32>
(GET_CLOSURE, aOp1, aOp2) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[GET_CLOSURE] << "\t" << mOp1 << ", " << mOp2;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << getRegisterValue(registers, mOp1.first);
return f;
}
};
class GetElement : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
public:
/* dest, base, index */
@ -666,6 +684,22 @@
}
};
class NewClosure : public Instruction_2<TypedRegister, ICodeModule*> {
public:
/* dest, ICodeModule */
NewClosure (TypedRegister aOp1, ICodeModule* aOp2) :
Instruction_2<TypedRegister, ICodeModule*>
(NEW_CLOSURE, aOp1, aOp2) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[NEW_CLOSURE] << "\t" << mOp1 << ", " << "ICodeModule";
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << getRegisterValue(registers, mOp1.first);
return f;
}
};
class NewFunction : public Instruction_2<TypedRegister, ICodeModule*> {
public:
/* dest, ICodeModule */
@ -1165,6 +1199,7 @@
"DIVIDE ",
"ELEM_XCR ",
"GENERIC_BINARY_OP ",
"GET_CLOSURE ",
"GET_ELEMENT ",
"GET_METHOD ",
"GET_PROP ",
@ -1182,6 +1217,7 @@
"NEGATE ",
"NEW_ARRAY ",
"NEW_CLASS ",
"NEW_CLOSURE ",
"NEW_FUNCTION ",
"NEW_OBJECT ",
"NOP ",

View File

@ -73,7 +73,7 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
//
ICodeGenerator::ICodeGenerator(Context *cx, JSClass *aClass, ICodeGeneratorFlags flags)
ICodeGenerator::ICodeGenerator(Context *cx, ICodeGenerator *containingFunction, JSClass *aClass, ICodeGeneratorFlags flags)
: mTopRegister(0),
mExceptionRegister(TypedRegister(NotARegister, &None_Type)),
variableList(new VariableList()),
@ -83,7 +83,8 @@ ICodeGenerator::ICodeGenerator(Context *cx, JSClass *aClass, ICodeGeneratorFlags
mClass(aClass),
mFlags(flags),
pLabels(NULL),
mInitName(cx->getWorld().identifiers["__init__"])
mInitName(cx->getWorld().identifiers["__init__"]),
mContainingFunction(containingFunction)
{
iCode = new InstructionStream();
iCodeOwner = true;
@ -360,7 +361,6 @@ TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, I
TypedRegister ICodeGenerator::getSlot(TypedRegister base, uint32 slot)
{
TypedRegister dest(getTempRegister(), &Any_Type);
@ -498,6 +498,22 @@ TypedRegister ICodeGenerator::bindThis(TypedRegister thisArg, TypedRegister targ
return dest;
}
TypedRegister ICodeGenerator::getClosure(uint32 count)
{
TypedRegister dest(getTempRegister(), &Any_Type);
iCode->push_back(new GetClosure(dest, count));
return dest;
}
TypedRegister ICodeGenerator::newClosure(ICodeModule *icm)
{
TypedRegister dest(getTempRegister(), &Function_Type);
iCode->push_back(new NewClosure(dest, icm));
return dest;
}
TypedRegister ICodeGenerator::getMethod(TypedRegister thisArg, uint32 slotIndex)
{
TypedRegister dest(getTempRegister(), &Any_Type);
@ -735,31 +751,70 @@ static bool isStaticName(JSClass *c, const StringAtom &name, JSType*& type, bool
return false;
}
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, bool lvalue)
ICodeGenerator::LValueKind ICodeGenerator::getVariableByName(const StringAtom &name, TypedRegister &v)
{
v = variableList->findVariable(name);
if (v.first == NotARegister)
v = parameterList->findVariable(name);
if (v.first != NotARegister)
return Var;
return NoKind;
}
ICodeGenerator::LValueKind ICodeGenerator::scanForVariable(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, TypedRegister &base)
{
LValueKind k = getVariableByName(name, v);
if (k == Var) return k;
uint32 count = 0;
ICodeGenerator *upper = mContainingFunction;
while (upper) {
k = upper->getVariableByName(name, v);
if (k == Var) {
base = getClosure(count);
slotIndex = v.first;
return Slot;
}
count++;
upper = upper->mContainingFunction;
}
return NoKind;
}
// find 'name' (unqualified) in the current context.
// for local variable, returns v.first = register number
// for slot/method, returns slotIndex and sets base appropriately
// (note closure vars also get handled this way)
// v.second is set to the type regardless
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, TypedRegister &base, bool lvalue)
{
if (!isWithinWith()) {
v = variableList->findVariable(name);
if (v.first == NotARegister)
v = parameterList->findVariable(name);
if (v.first != NotARegister)
return Var;
LValueKind k = scanForVariable(name, v, slotIndex, base);
if (k != NoKind)
return k;
else {
if (mClass) { // we're compiling a method of a class
if (!isStaticMethod()) {
if (isSlotName(mClass, name, slotIndex, v.second, lvalue))
if (isSlotName(mClass, name, slotIndex, v.second, lvalue)) {
base = TypedRegister(0, mClass);
return Slot;
if (isMethodName(mClass, name, slotIndex))
}
if (isMethodName(mClass, name, slotIndex)) {
base = TypedRegister(0, mClass);
return Method;
}
}
bool isConstructor = false;
if (isStaticName(mClass, name, v.second, isConstructor)) {
return (isConstructor) ? Constructor : Static;
}
}
// last chance - if it's a generic name in the global scope, try to get a type for it
v.second = mContext->getGlobalObject()->getType(name);
return Name;
}
}
// all bet's off, generic name & type
v.second = &Any_Type;
return Name;
}
@ -771,13 +826,12 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
/*JSType *vType = &Any_Type;*/
uint32 slotIndex;
TypedRegister v;
TypedRegister base;
const StringAtom &name = (static_cast<IdentifierExprNode *>(p))->name;
LValueKind lValueKind = resolveIdentifier(name, v, slotIndex, lvalue);
LValueKind lValueKind = resolveIdentifier(name, v, slotIndex, base, lvalue);
JSType *targetType = v.second;
TypedRegister thisBase = TypedRegister(0, mClass ? mClass : &Any_Type);
switch (use) {
case ExprNode::addEquals:
case ExprNode::subtractEquals:
@ -797,7 +851,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
v = loadName(name, v.second);
break;
case Slot:
v = getSlot(thisBase, slotIndex);
v = getSlot(base, slotIndex);
break;
case Static:
case Constructor:
@ -818,7 +872,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
saveName(name, ret);
break;
case Slot:
setSlot(thisBase, slotIndex, ret);
setSlot(base, slotIndex, ret);
break;
case Static:
case Constructor:
@ -837,7 +891,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
ret = loadName(name, v.second);
break;
case Slot:
ret = getSlot(thisBase, slotIndex);
ret = getSlot(base, slotIndex);
break;
case Static:
case Constructor:
@ -859,8 +913,8 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
saveName(name, ret);
break;
case Slot:
ret = binaryOp(xcrementOp, getSlot(thisBase, slotIndex), loadImmediate(1.0));
setSlot(thisBase, slotIndex, ret);
ret = binaryOp(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0));
setSlot(base, slotIndex, ret);
break;
case Static:
case Constructor:
@ -881,7 +935,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
ret = nameXcr(name, xcrementOp);
break;
case Slot:
ret = slotXcr(thisBase, slotIndex, xcrementOp);
ret = slotXcr(base, slotIndex, xcrementOp);
break;
case Static:
case Constructor:
@ -901,7 +955,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
ret = call(loadName(name), args);
break;
case Method:
ret = call(getMethod(thisBase, slotIndex), args);
ret = call(getMethod(base, slotIndex), args);
break;
case Static:
ret = call(getStatic(mClass, name), args);
@ -932,15 +986,20 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] )
}
else {
// we have <expr>.<fieldname>
const StringAtom &fieldName = static_cast<IdentifierExprNode *>(b->op2)->name;
TypedRegister base;
TypedRegister baseBase;
JSClass *clazz = NULL;
JSType *fieldType = &Any_Type;
uint32 slotIndex;
if ((b->op1->getKind() == ExprNode::identifier) && !isWithinWith()) {
// handle <basename>.<fieldname>
const StringAtom &baseName = (static_cast<IdentifierExprNode *>(b->op1))->name;
resolveIdentifier(baseName, base, slotIndex, false);
LValueKind baseKind = resolveIdentifier(baseName, base, slotIndex, baseBase, false);
if (baseKind == Slot) {
base = getSlot(baseBase, slotIndex);
}
//
// handle <class name>.<static field>
//
@ -1570,22 +1629,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
}
break;
case ExprNode::functionLiteral: // XXX FIXME!! This needs to handled by calling genFunction !!!
// - the parameter handling is all wrong
case ExprNode::functionLiteral:
{
FunctionExprNode *f = static_cast<FunctionExprNode *>(p);
ICodeGenerator icg(mContext);
icg.allocateParameter(mContext->getWorld().identifiers["this"], false); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name, false, &Any_Type);
v = v->next;
}
icg.genStmt(f->function.body);
//stdOut << icg;
ICodeModule *icm = icg.complete(extractType(f->function.resultType));
ret = newFunction(icm);
ICodeModule *icm = genFunction(f->function, false, false, NULL);
ret = newClosure(icm);
}
break;
@ -1596,9 +1644,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
ret = genExpr(b->op1);
if (b->op2->getKind() == ExprNode::identifier) {
TypedRegister t;
/*uint32 slotIndex;*/
const StringAtom &name = (static_cast<IdentifierExprNode *>(b->op2))->name;
/*LValueKind lvk = resolveIdentifier(name, t, slotIndex);*/
ASSERT(t.second == &Type_Type);
const JSValue &v = mContext->getGlobalObject()->getVariable(name);
ASSERT(v.isType());
@ -1663,26 +1709,25 @@ JSType *ICodeGenerator::extractType(ExprNode *t)
return type;
}
ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor, JSClass *superclass)
ICodeModule *ICodeGenerator::genFunction(FunctionDefinition &function, bool isStatic, bool isConstructor, JSClass *superclass)
{
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator icg(mContext, mClass, flags);
ICodeGenerator icg(mContext, this, mClass, flags);
icg.allocateParameter(mContext->getWorld().identifiers["this"], false, (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
VariableBinding *v = function.parameters;
bool unnamed = true;
uint32 positionalCount = 0;
StringFormatter s;
while (v) {
if (unnamed && (v == f->function.namedParameters)) { // Track when we hit the first named parameter.
if (unnamed && (v == function.namedParameters)) { // Track when we hit the first named parameter.
icg.parameterList->setPositionalCount(positionalCount);
unnamed = false;
}
// The rest parameter is ignored in this processing - we push it to the end of the list.
// But we need to track whether it comes before or after the |
if (v == f->function.restParameter) {
if (v == function.restParameter) {
icg.parameterList->setRestParameter( (unnamed) ? ParameterList::HasRestParameterBeforeBar : ParameterList::HasRestParameterAfterBar );
}
else {
@ -1708,8 +1753,8 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
if (unnamed) icg.parameterList->setPositionalCount(positionalCount);
// now allocate the rest parameter
if (f->function.restParameter) {
v = f->function.restParameter;
if (function.restParameter) {
v = function.restParameter;
JSType *pType = (v->type == NULL) ? &Array_Type : extractType(v->type);
if (v->name && (v->name->getKind() == ExprNode::identifier))
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name, (v->initializer != NULL), pType);
@ -1718,7 +1763,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
}
// generate the code for optional initializers
v = f->function.optParameters;
v = function.optParameters;
if (v) {
while (v) { // include the rest parameter, as it may have an initializer
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
@ -1731,7 +1776,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
icg.setLabel(l);
}
else { // an un-initialized rest parameter is still an empty array
if (v == f->function.restParameter) {
if (v == function.restParameter) {
Label *l = icg.getLabel();
icg.branchInitialized(l, p);
icg.move(p, icg.newArray());
@ -1754,7 +1799,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
ArgumentList *args = new ArgumentList();
if (superclass) {
bool foundSuperCall = false;
BlockStmtNode *b = f->function.body;
BlockStmtNode *b = function.body;
if (b && b->statements && (b->statements->getKind() == StmtNode::expression)) {
ExprStmtNode *e = static_cast<ExprStmtNode *>(b->statements);
if (e->expr->getKind() == ExprNode::call) {
@ -1779,13 +1824,13 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
icg.call(icg.bindThis(thisValue, icg.getStatic(mClass, mInitName)), args); // ok, so it's mis-named
}
if (f->function.body)
icg.genStmt(f->function.body);
if (function.body)
icg.genStmt(function.body);
if (isConstructor) {
TypedRegister thisValue = TypedRegister(0, mClass);
icg.returnStmt(thisValue);
}
return icg.complete(extractType(f->function.resultType));
return icg.complete(extractType(function.resultType));
}
TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
@ -1900,11 +1945,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (needsInstanceInitializer) {
// constructor code generator. Slot variable
// initializers get added to this function.
ccg = new ICodeGenerator(classContext, thisClass, kNoFlags);
ccg = new ICodeGenerator(classContext, NULL, thisClass, kNoFlags);
ccg->allocateParameter(mContext->getWorld().identifiers["this"], false, thisClass); // always parameter #0
}
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod); // static initializer code generator.
ICodeGenerator scg(classContext, NULL, thisClass, kIsStaticMethod); // static initializer code generator.
// static field inits, plus code to initialize
// static method slots.
StmtNode* s = classStmt->body->statements;
@ -1943,8 +1988,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
bool isConstructor = (s->getKind() == StmtNode::Constructor);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator mcg(classContext, thisClass, flags); // method code generator.
ICodeModule *icm = mcg.genFunction(f, isConstructor, superclass);
ICodeGenerator mcg(classContext, NULL, thisClass, flags); // method code generator.
ICodeModule *icm = mcg.genFunction(f->function, isStatic, isConstructor, superclass);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
if (isConstructor) {
@ -1988,7 +2033,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (!hasDefaultConstructor) {
TypedRegister thisValue = TypedRegister(0, thisClass);
ArgumentList *args = new ArgumentList();
ICodeGenerator icg(classContext, thisClass, kIsStaticMethod);
ICodeGenerator icg(classContext, NULL, thisClass, kIsStaticMethod);
icg.allocateParameter(mContext->getWorld().identifiers["this"], false, thisClass); // always parameter #0
if (superclass)
icg.call(icg.bindThis(thisValue, icg.getStatic(superclass, superclass->getName())), args);
@ -2015,7 +2060,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
case StmtNode::Function:
{
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(p);
ICodeModule *icm = genFunction(f, false, NULL);
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeModule *icm = genFunction(f->function, isStatic, false, NULL);
JSType *resultType = extractType(f->function.resultType);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
@ -2468,8 +2514,8 @@ void ICodeGenerator::readICode(const char *fileName)
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), className, superclass);
JSScope* thisScope = thisClass->getScope();
Context *classContext = new Context(mContext->getWorld(), thisScope);
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod);
ICodeGenerator ccg(classContext, thisClass, kNoFlags);
ICodeGenerator scg(classContext, NULL, thisClass, kIsStaticMethod);
ICodeGenerator ccg(classContext, NULL, thisClass, kNoFlags);
ccg.allocateParameter(mContext->getWorld().identifiers["this"], false, thisClass);
thisClass->defineStatic(mInitName, &Function_Type);
@ -2541,7 +2587,7 @@ void ICodeGenerator::readICode(const char *fileName)
if (!hasDefaultConstructor) {
TypedRegister thisValue = TypedRegister(0, thisClass);
ArgumentList *args = new ArgumentList(0);
ICodeGenerator icg(mContext, thisClass, kIsStaticMethod);
ICodeGenerator icg(mContext, NULL, thisClass, kIsStaticMethod);
icg.allocateParameter(mContext->getWorld().identifiers["this"], false, thisClass); // always parameter #0
if (superclass)
icg.call(icg.bindThis(thisValue, icg.getStatic(superclass, superclass->getName())), args);

View File

@ -217,6 +217,7 @@ namespace ICG {
LabelList *pLabels; // label for each parameter initialization entry point
const StringAtom &mInitName;
ICodeGenerator *mContainingFunction;// outer function for nested functions
std::vector<bool> mPermanentRegister;
@ -260,7 +261,6 @@ namespace ICG {
void endWith() { iCode->push_back(new Without()); }
void startStatement(uint32 pos) { (*mInstructionMap)[iCode->size()] = pos; }
ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind);
@ -272,16 +272,18 @@ namespace ICG {
void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); }
typedef enum { Var, Property, Slot, Static, Constructor, Name, Method } LValueKind;
typedef enum { NoKind, Var, Property, Slot, Static, Constructor, Name, Method } LValueKind;
LValueKind resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, bool lvalue);
LValueKind ICodeGenerator::getVariableByName(const StringAtom &name, TypedRegister &v);
LValueKind ICodeGenerator::scanForVariable(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, TypedRegister &base);
LValueKind resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, TypedRegister &base, bool lvalue);
TypedRegister handleIdentifier(IdentifierExprNode *p, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, ArgumentList *args, bool lvalue);
TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, ArgumentList *args, bool lvalue);
ICodeModule *genFunction(FunctionStmtNode *f, bool isConstructor, JSClass *superClass);
ICodeModule *genFunction(FunctionDefinition &function, bool isStatic, bool isConstructor, JSClass *superClass);
public:
ICodeGenerator(Context *cx, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
ICodeGenerator(Context *cx, ICodeGenerator *containingFunction = NULL, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
~ICodeGenerator()
{
@ -352,6 +354,8 @@ namespace ICG {
TypedRegister directCall(JSFunction *target, ArgumentList *args);
TypedRegister bindThis(TypedRegister thisArg, TypedRegister target);
TypedRegister getMethod(TypedRegister thisArg, uint32 slotIndex);
TypedRegister getClosure(uint32 count);
TypedRegister newClosure(ICodeModule *icm);
void move(TypedRegister destination, TypedRegister source);
TypedRegister logicalNot(TypedRegister source);

View File

@ -45,7 +45,7 @@
namespace JavaScript {
namespace ICodeASM {
static uint icodemap_size = 73;
static uint icodemap_size = 75;
static struct {
char *name;
@ -74,6 +74,7 @@ namespace ICodeASM {
{"DIVIDE", {otRegister, otRegister, otRegister}},
{"ELEM_XCR", {otRegister, otRegister, otRegister, otDouble}},
{"GENERIC_BINARY_OP", {otRegister, otBinaryOp, otRegister, otRegister}},
{"GET_CLOSURE", {otRegister, otUInt32}},
{"GET_ELEMENT", {otRegister, otRegister, otRegister}},
{"GET_METHOD", {otRegister, otRegister, otUInt32}},
{"GET_PROP", {otRegister, otRegister, otStringAtom}},
@ -91,6 +92,7 @@ namespace ICodeASM {
{"NEGATE", {otRegister, otRegister}},
{"NEW_ARRAY", {otRegister}},
{"NEW_CLASS", {otRegister, otJSClass}},
{"NEW_CLOSURE", {otRegister, otICodeModule}},
{"NEW_FUNCTION", {otRegister, otICodeModule}},
{"NEW_OBJECT", {otRegister, otRegister}},
{"NOP", {otNone}},
@ -204,153 +206,159 @@ namespace ICodeASM {
i = new GenericBinaryOP (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<BinaryOperator::BinaryOp>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0), TypedRegister(static_cast<Register>(node->operand[3].data), 0));
break;
case 23:
i = new GetElement (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new GetClosure (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<uint32>(node->operand[1].data));
break;
case 24:
i = new GetMethod (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data));
i = new GetElement (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 25:
i = new GetProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data));
i = new GetMethod (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data));
break;
case 26:
i = new GetSlot (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data));
i = new GetProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data));
break;
case 27:
i = new GetStatic (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data), static_cast<uint32>(node->operand[2].data));
i = new GetSlot (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data));
break;
case 28:
i = new Instanceof (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new GetStatic (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data), static_cast<uint32>(node->operand[2].data));
break;
case 29:
i = new Jsr (reinterpret_cast<Label*>(node->operand[0].data));
i = new Instanceof (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 30:
i = new LoadBoolean (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<bool>(node->operand[1].data));
i = new Jsr (reinterpret_cast<Label*>(node->operand[0].data));
break;
case 31:
i = new LoadImmediate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<double>(node->operand[1].data));
i = new LoadBoolean (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<bool>(node->operand[1].data));
break;
case 32:
i = new LoadName (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data));
i = new LoadImmediate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<double>(node->operand[1].data));
break;
case 33:
i = new LoadString (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSString*>(node->operand[1].data));
i = new LoadName (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data));
break;
case 34:
i = new Move (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new LoadString (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSString*>(node->operand[1].data));
break;
case 35:
i = new Multiply (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Move (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 36:
i = new NameXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data), static_cast<double>(node->operand[2].data));
i = new Multiply (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 37:
i = new Negate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new NameXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data), static_cast<double>(node->operand[2].data));
break;
case 38:
i = new NewArray (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new Negate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 39:
i = new NewClass (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data));
i = new NewArray (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 40:
i = new NewFunction (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<ICodeModule*>(node->operand[1].data));
i = new NewClass (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data));
break;
case 41:
i = new NewObject (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new NewClosure (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<ICodeModule*>(node->operand[1].data));
break;
case 42:
i = new Nop ();
i = new NewFunction (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<ICodeModule*>(node->operand[1].data));
break;
case 43:
i = new Not (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new NewObject (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 44:
i = new Or (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Nop ();
break;
case 45:
i = new Posate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new Not (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 46:
i = new PropXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data), static_cast<double>(node->operand[3].data));
i = new Or (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 47:
i = new Remainder (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Posate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 48:
i = new Return (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new PropXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data), static_cast<double>(node->operand[3].data));
break;
case 49:
i = new ReturnVoid ();
i = new Remainder (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 50:
i = new Rts ();
i = new Return (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 51:
i = new SaveName (reinterpret_cast<const StringAtom*>(node->operand[0].data), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new ReturnVoid ();
break;
case 52:
i = new SetElement (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Rts ();
break;
case 53:
i = new SetProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SaveName (reinterpret_cast<const StringAtom*>(node->operand[0].data), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 54:
i = new SetSlot (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<uint32>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SetElement (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 55:
i = new SetStatic (reinterpret_cast<JSClass*>(node->operand[0].data), static_cast<uint32>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SetProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 56:
i = new Shiftleft (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SetSlot (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<uint32>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 57:
i = new Shiftright (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SetStatic (reinterpret_cast<JSClass*>(node->operand[0].data), static_cast<uint32>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 58:
i = new SlotXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data), static_cast<double>(node->operand[3].data));
i = new Shiftleft (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 59:
i = new StaticXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data), static_cast<uint32>(node->operand[2].data), static_cast<double>(node->operand[3].data));
i = new Shiftright (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 60:
i = new StrictEQ (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SlotXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data), static_cast<double>(node->operand[3].data));
break;
case 61:
i = new StrictNE (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new StaticXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data), static_cast<uint32>(node->operand[2].data), static_cast<double>(node->operand[3].data));
break;
case 62:
i = new Subtract (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new StrictEQ (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 63:
i = new Super (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new StrictNE (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 64:
i = new Test (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new Subtract (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 65:
i = new Throw (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new Super (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 66:
i = new Tryin (reinterpret_cast<Label*>(node->operand[0].data), reinterpret_cast<Label*>(node->operand[1].data));
i = new Test (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 67:
i = new Tryout ();
i = new Throw (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 68:
i = new Ushiftright (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Tryin (reinterpret_cast<Label*>(node->operand[0].data), reinterpret_cast<Label*>(node->operand[1].data));
break;
case 69:
i = new VarXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<double>(node->operand[2].data));
i = new Tryout ();
break;
case 70:
i = new Within (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new Ushiftright (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 71:
i = new Without ();
i = new VarXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<double>(node->operand[2].data));
break;
case 72:
i = new Within (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 73:
i = new Without ();
break;
case 74:
i = new Xor (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;

View File

@ -64,81 +64,6 @@ using namespace JSMathClass;
// These classes are private to the JS interpreter.
/**
*
*/
struct Handler: public gc_base {
Handler(Label *catchLabel, Label *finallyLabel)
: catchTarget(catchLabel), finallyTarget(finallyLabel) {}
Label *catchTarget;
Label *finallyTarget;
};
typedef std::vector<Handler *> CatchStack;
/**
* Represents the current function's invocation state.
*/
struct Activation : public gc_base {
JSValues mRegisters;
ICodeModule* mICode;
CatchStack catchStack;
Activation(ICodeModule* iCode, const JSValues& args)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
// copy arg list to initial registers.
JSValues::iterator dest = mRegisters.begin();
for (JSValues::const_iterator src = args.begin(),
end = args.end(); src != end; ++src, ++dest) {
*dest = *src;
}
}
Activation(ICodeModule* iCode, Activation* caller, const JSValue thisArg,
const ArgumentList* list)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
// copy caller's parameter list to initial registers.
JSValues::iterator dest = mRegisters.begin();
*dest++ = thisArg;
const JSValues& params = caller->mRegisters;
for (ArgumentList::const_iterator src = list->begin(),
end = list->end(); src != end; ++src, ++dest) {
Register r = (*src).first.first;
if (r != NotARegister)
*dest = params[r];
else
*dest = JSValue(JSValue::uninitialized_tag);
}
}
// calling a binary operator, no 'this'
Activation(ICodeModule* iCode, const JSValue thisArg, const JSValue arg1, const JSValue arg2)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
mRegisters[0] = thisArg;
mRegisters[1] = arg1;
mRegisters[2] = arg2;
}
// calling a getter function, no arguments
Activation(ICodeModule* iCode, const JSValue thisArg)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
mRegisters[0] = thisArg;
}
// calling a setter function, 1 argument
Activation(ICodeModule* iCode, const JSValue thisArg, const JSValue arg)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
mRegisters[0] = thisArg;
mRegisters[1] = arg;
}
};
/**
* exception-safe class to save off values.
*/
@ -244,7 +169,7 @@ void Context::loadClass(const char *fileName)
}
JSValues& Context::getRegisters() { return mActivation->mRegisters; }
ICodeModule* Context::getICode() { return mActivation->mICode; }
ICodeModule* Context::getICode() { return mICode; }
/**
* Stores saved state from the *previous* activation, the current
@ -256,11 +181,13 @@ struct Linkage : public Context::Frame, public gc_base {
Activation* mActivation; // caller's activation.
JSScope* mScope;
TypedRegister mResult; // the desired target register for the return value
ICodeModule* mICode; // the caller function
JSClosure* mClosure;
Linkage(Linkage* linkage, InstructionIterator returnPC,
Activation* activation, JSScope* scope, TypedRegister result)
Activation* activation, JSScope* scope, TypedRegister result, ICodeModule* iCode, JSClosure *closure)
: mNext(linkage), mReturnPC(returnPC),
mActivation(activation), mScope(scope), mResult(result)
mActivation(activation), mScope(scope), mResult(result), mICode(iCode), mClosure(closure)
{
}
@ -270,7 +197,7 @@ struct Linkage : public Context::Frame, public gc_base {
{
pc = mReturnPC;
registers = &mActivation->mRegisters;
iCode = mActivation->mICode;
iCode = mICode;
}
};
@ -651,12 +578,13 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
// when invoked with empty args, make sure that 'this' is
// going to be the global object.
mActivation = new Activation(iCode, args);
mICode = iCode;
mActivation = new Activation(mICode->itsMaxRegister, args);
JSValues* registers = &mActivation->mRegisters;
if (args.size() == 0) (*registers)[0] = mGlobal;
mPC = mActivation->mICode->its_iCode->begin();
InstructionIterator endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
InstructionIterator endPC = mICode->its_iCode->end();
// stack of all catch/finally handlers available for the current activation
// to implement jsr/rts for finally code
@ -727,7 +655,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (target->isNative()) {
ArgumentList *params = op3(call);
JSValues argv(params->size() + 1);
argv[0] = target->getThis(); //(*registers)[op3(call).first];
argv[0] = target->getThis();
JSValues::size_type i = 1;
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
src != end; ++src, ++i) {
@ -786,9 +714,6 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
else { // shift the index value down by the number of positional parameters
index = (int)d;
index -= icm->itsParameters->mPositionalCount;
// StringFormatter s;
// s << ((int)d - icm->itsParameters->mPositionalCount);
// argName = &mWorld.identifiers[s];
}
TypedRegister argument = (*args)[i].first; // this is the argument whose name didn't match
@ -834,15 +759,41 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
}
}
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, op1(call));
mActivation = new Activation(icm, mActivation, target->getThis()/*(*registers)[op3(call).first]*/, callArgs);
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, op1(call), mICode, mCurrentClosure);
mICode = icm;
mActivation = new Activation(mICode->itsMaxRegister, mActivation, target->getThis(), callArgs);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
JSClosure *cl = dynamic_cast<JSClosure *>(target);
if (cl)
mCurrentClosure = cl;
continue;
}
}
case NEW_CLOSURE:
{
NewClosure* nc = static_cast<NewClosure*>(instruction);
JSClosure* cl = new JSClosure(src1(nc), mActivation, mCurrentClosure);
(*registers)[dst(nc).first] = cl;
}
break;
case GET_CLOSURE:
{
GetClosure* gc = static_cast<GetClosure*>(instruction);
uint32 count = src1(gc);
JSClosure* cl = mCurrentClosure;
while (count-- > 0) {
ASSERT(cl);
cl = cl->getPrevious();
}
(*registers)[dst(gc).first] = cl->getActivation();
}
break;
case DIRECT_CALL:
{
DirectCall* call = static_cast<DirectCall*>(instruction);
@ -862,11 +813,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, op1(call));
mActivation = new Activation(target->getICode(), mActivation, kNullValue, op3(call));
mActivation, mGlobal, op1(call), mICode, mCurrentClosure);
mICode = target->getICode();
mActivation = new Activation(mICode->itsMaxRegister, mActivation, kNullValue, op3(call));
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
}
@ -887,7 +839,9 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (linkage->mResult.first != NotARegister)
(*registers)[linkage->mResult.first] = kUndefinedValue;
mPC = linkage->mReturnPC;
endPC = mActivation->mICode->its_iCode->end();
mICode = linkage->mICode;
mCurrentClosure = linkage->mClosure;
endPC = mICode->its_iCode->end();
}
continue;
@ -911,7 +865,9 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (linkage->mResult.first != NotARegister)
(*registers)[linkage->mResult.first] = result;
mPC = linkage->mReturnPC;
endPC = mActivation->mICode->its_iCode->end();
mICode = linkage->mICode;
mCurrentClosure = linkage->mClosure;
endPC = mICode->its_iCode->end();
}
continue;
case MOVE:
@ -926,11 +882,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSFunction *getter = mGlobal->getter(*src1(ln));
if (getter) {
ASSERT(!getter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, dst(ln));
mActivation = new Activation(getter->getICode(), kNullValue);
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, dst(ln), mICode, mCurrentClosure);
mICode = getter->getICode();
mActivation = new Activation(mICode->itsMaxRegister, kNullValue);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
else
@ -943,11 +900,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSFunction *setter = mGlobal->setter(*dst(sn));
if (setter) {
ASSERT(!setter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, TypedRegister(NotARegister, &Null_Type));
mActivation = new Activation(setter->getICode(), (*registers)[src1(sn).first], kNullValue);
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, TypedRegister(NotARegister, &Null_Type), mICode, mCurrentClosure);
mICode = setter->getICode();
mActivation = new Activation(mICode->itsMaxRegister, (*registers)[src1(sn).first], kNullValue);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
else
@ -1093,21 +1051,33 @@ using JSString throughout.
GetSlot* gs = static_cast<GetSlot*>(instruction);
JSValue& value = (*registers)[src1(gs).first];
if (value.isObject()) {
JSInstance* inst = static_cast<JSInstance *>(value.object);
if (inst->hasGetter(src2(gs))) {
JSFunction* getter = inst->getter(src2(gs));
ASSERT(!getter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, dst(gs));
mActivation = new Activation(getter->getICode(), value);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
JSInstance* inst = dynamic_cast<JSInstance *>(value.object);
if (inst) {
if (inst->hasGetter(src2(gs))) {
JSFunction* getter = inst->getter(src2(gs));
ASSERT(!getter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, dst(gs), mICode, mCurrentClosure);
mICode = getter->getICode();
mActivation = new Activation(mICode->itsMaxRegister, value);
registers = &mActivation->mRegisters;
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
else
(*registers)[dst(gs).first] = (*inst)[src2(gs)];
}
else {
Activation* act = dynamic_cast<Activation *>(value.object);
if (act) {
(*registers)[dst(gs).first] = act->mRegisters[src2(gs)];
}
else
NOT_REACHED("runtime error");
}
else
(*registers)[dst(gs).first] = (*inst)[src2(gs)];
}
// XXX runtime error
else
NOT_REACHED("runtime error");
}
break;
case SET_SLOT:
@ -1115,20 +1085,33 @@ using JSString throughout.
SetSlot* ss = static_cast<SetSlot*>(instruction);
JSValue& value = (*registers)[dst(ss).first];
if (value.isObject()) {
JSInstance* inst = static_cast<JSInstance *>(value.object);
if (inst->hasSetter(src1(ss))) {
JSFunction* setter = inst->setter(src1(ss));
ASSERT(!setter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, TypedRegister(NotARegister, &Null_Type));
mActivation = new Activation(setter->getICode(), value, (*registers)[src2(ss).first]);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
JSInstance* inst = dynamic_cast<JSInstance *>(value.object);
if (inst) {
if (inst->hasSetter(src1(ss))) {
JSFunction* setter = inst->setter(src1(ss));
ASSERT(!setter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, TypedRegister(NotARegister, &Null_Type), mICode, mCurrentClosure);
mICode = setter->getICode();
mActivation = new Activation(mICode->itsMaxRegister, value, (*registers)[src2(ss).first]);
registers = &mActivation->mRegisters;
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
else
(*inst)[src1(ss)] = (*registers)[src2(ss).first];
}
else {
Activation* act = dynamic_cast<Activation *>(value.object);
if (act) {
act->mRegisters[src1(ss)] = (*registers)[src2(ss).first];
}
else
NOT_REACHED("runtime error");
}
else
(*inst)[src1(ss)] = (*registers)[src2(ss).first];
}
else
NOT_REACHED("runtime error");
}
break;
@ -1154,7 +1137,7 @@ using JSString throughout.
{
GenericBranch* bra =
static_cast<GenericBranch*>(instruction);
mPC = mActivation->mICode->its_iCode->begin() + ofs(bra);
mPC = mICode->its_iCode->begin() + ofs(bra);
continue;
}
break;
@ -1164,7 +1147,7 @@ using JSString throughout.
static_cast<GenericBranch*>(instruction);
ASSERT((*registers)[src1(bc).first].isBoolean());
if ((*registers)[src1(bc).first].boolean) {
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
mPC = mICode->its_iCode->begin() + ofs(bc);
continue;
}
}
@ -1175,7 +1158,7 @@ using JSString throughout.
static_cast<GenericBranch*>(instruction);
ASSERT((*registers)[src1(bc).first].isBoolean());
if (!(*registers)[src1(bc).first].boolean) {
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
mPC = mICode->its_iCode->begin() + ofs(bc);
continue;
}
}
@ -1185,7 +1168,7 @@ using JSString throughout.
GenericBranch* bc =
static_cast<GenericBranch*>(instruction);
if ((*registers)[src1(bc).first].isInitialized()) {
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
mPC = mICode->its_iCode->begin() + ofs(bc);
continue;
}
}
@ -1207,11 +1190,12 @@ using JSString throughout.
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, dst(gbo));
mActivation = new Activation(target->getICode(), kNullValue, r1, r2);
mActivation, mGlobal, dst(gbo), mICode, mCurrentClosure);
mICode = target->getICode();
mActivation = new Activation(mICode->itsMaxRegister, kNullValue, r1, r2);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
}
@ -1513,7 +1497,7 @@ using JSString throughout.
subroutineStack.push(++mPC);
Jsr* jsr = static_cast<Jsr*>(instruction);
uint32 offset = ofs(jsr);
mPC = mActivation->mICode->its_iCode->begin() + offset;
mPC = mICode->its_iCode->begin() + offset;
continue;
}
case RTS:
@ -1561,11 +1545,11 @@ using JSString throughout.
Handler *h = mActivation->catchStack.back();
registers = &mActivation->mRegisters;
if (h->catchTarget) {
mPC = mActivation->mICode->its_iCode->begin() + h->catchTarget->mOffset;
mPC = mICode->its_iCode->begin() + h->catchTarget->mOffset;
}
else {
ASSERT(h->finallyTarget);
mPC = mActivation->mICode->its_iCode->begin() + h->finallyTarget->mOffset;
mPC = mICode->its_iCode->begin() + h->finallyTarget->mOffset;
}
mLinkage = pLinkage;
break;
@ -1577,11 +1561,11 @@ using JSString throughout.
else {
Handler *h = mActivation->catchStack.back();
if (h->catchTarget) {
mPC = mActivation->mICode->its_iCode->begin() + h->catchTarget->mOffset;
mPC = mICode->its_iCode->begin() + h->catchTarget->mOffset;
}
else {
ASSERT(h->finallyTarget);
mPC = mActivation->mICode->its_iCode->begin() + h->finallyTarget->mOffset;
mPC = mICode->its_iCode->begin() + h->finallyTarget->mOffset;
}
continue;
}

View File

@ -40,7 +40,7 @@ namespace Interpreter {
void initContext();
public:
explicit Context(World& world, JSScope* aGlobal)
: mWorld(world), mGlobal(aGlobal), mLinkage(0), mActivation(0), mHasOperatorsPackageLoaded(false) { initContext(); }
: mWorld(world), mGlobal(aGlobal), mLinkage(0), mActivation(0), mHasOperatorsPackageLoaded(false), mCurrentClosure(0) { initContext(); }
World& getWorld() { return mWorld; }
JSScope* getGlobalObject() { return mGlobal; }
@ -102,6 +102,8 @@ namespace Interpreter {
typedef ListenerList::iterator ListenerIterator;
ListenerList mListeners;
Activation* mActivation;
ICodeModule* mICode;
JSClosure* mCurrentClosure;
bool mHasOperatorsPackageLoaded;
InstructionIterator mPC;
@ -110,6 +112,80 @@ namespace Interpreter {
}; /* class Context */
/**
*
*/
struct Handler: public gc_base {
Handler(Label *catchLabel, Label *finallyLabel)
: catchTarget(catchLabel), finallyTarget(finallyLabel) {}
Label *catchTarget;
Label *finallyTarget;
};
typedef std::vector<Handler *> CatchStack;
/**
* Represents the current function's invocation state.
*/
struct Activation : public JSObject {
JSValues mRegisters;
CatchStack catchStack;
Activation(uint32 highRegister, const JSValues& args)
: mRegisters(highRegister + 1)
{
// copy arg list to initial registers.
JSValues::iterator dest = mRegisters.begin();
for (JSValues::const_iterator src = args.begin(),
end = args.end(); src != end; ++src, ++dest) {
*dest = *src;
}
}
Activation(uint32 highRegister, Activation* caller, const JSValue thisArg,
const ArgumentList* list)
: mRegisters(highRegister + 1)
{
// copy caller's parameter list to initial registers.
JSValues::iterator dest = mRegisters.begin();
*dest++ = thisArg;
const JSValues& params = caller->mRegisters;
for (ArgumentList::const_iterator src = list->begin(),
end = list->end(); src != end; ++src, ++dest) {
Register r = (*src).first.first;
if (r != NotARegister)
*dest = params[r];
else
*dest = JSValue(JSValue::uninitialized_tag);
}
}
// calling a binary operator, no 'this'
Activation(uint32 highRegister, const JSValue thisArg, const JSValue arg1, const JSValue arg2)
: mRegisters(highRegister + 1)
{
mRegisters[0] = thisArg;
mRegisters[1] = arg1;
mRegisters[2] = arg2;
}
// calling a getter function, no arguments
Activation(uint32 highRegister, const JSValue thisArg)
: mRegisters(highRegister + 1)
{
mRegisters[0] = thisArg;
}
// calling a setter function, 1 argument
Activation(uint32 highRegister, const JSValue thisArg, const JSValue arg)
: mRegisters(highRegister + 1)
{
mRegisters[0] = thisArg;
mRegisters[1] = arg;
}
}; /* struct Activation */
} /* namespace Interpreter */
} /* namespace JavaScript */

View File

@ -347,11 +347,28 @@ namespace JSClasses {
return gc_base::operator new(n);
}
void* operator new(size_t n, uint32 slotCount)
{
if (slotCount > 0) n += sizeof(JSValue) * (slotCount - 1);
return gc_base::operator new(n);
}
#if !defined(XP_MAC)
void operator delete(void* /*ptr*/) {}
void operator delete(void* /*ptr*/, JSClass* /*thisClass*/) {}
void operator delete(void* /*ptr*/, uint32 /*slotCount*/) {}
#endif
JSInstance(uint32 slotCount)
{
mType = NULL;
// initialize extra slots with undefined.
if (slotCount > 0) {
std::uninitialized_fill(&mSlots[1], &mSlots[1] + (slotCount - 1),
JSTypes::kUndefinedValue);
}
}
JSInstance(JSClass* thisClass)
{
mType = thisClass;

View File

@ -49,6 +49,7 @@ namespace ICG {
} /* namespace ICG */
namespace Interpreter {
class Context;
struct Activation;
} /* namespace Interpreter */
} /* namespace JavaScript */
@ -504,7 +505,6 @@ namespace JSTypes {
static JSObject* FunctionPrototypeObject;
ICodeModule* mICode;
typedef JavaScript::gc_traits_finalizable<JSFunction> traits;
typedef gc_allocator<JSFunction, traits> allocator;
@ -519,7 +519,6 @@ namespace JSTypes {
{
setClass(FunctionString);
}
virtual ~JSFunction();
virtual JSValue getThis() { return kNullValue; }
@ -563,6 +562,21 @@ namespace JSTypes {
void* operator new(size_t) { return allocator::allocate(1); }
};
class JSClosure : public JSFunction {
Interpreter::Activation *mActivation;
JSClosure *mPrevious;
typedef JavaScript::gc_traits_finalizable<JSClosure> traits;
typedef gc_allocator<JSClosure, traits> allocator;
public:
JSClosure(ICodeModule* iCode, Interpreter::Activation *activation, JSClosure *previous)
: JSFunction(iCode), mActivation(activation), mPrevious(previous) {}
JSClosure* getPrevious() { return mPrevious; }
Interpreter::Activation* getActivation() { return mActivation; }
void* operator new(size_t) { return allocator::allocate(1); }
};
/**
* Provides a set of nested scopes.
*/

View File

@ -289,6 +289,18 @@ $ops{"SET_ELEMENT"} =
rem => "base, index, value",
params => [ ("TypedRegister", "TypedRegister", "TypedRegister") ]
};
$ops{"NEW_CLOSURE"} =
{
super => "Instruction_2",
rem => "dest, ICodeModule",
params => [ ("TypedRegister", "ICodeModule*") ]
};
$ops{"GET_CLOSURE"} =
{
super => "Instruction_2",
rem => "dest, closure depth",
params => [ ("TypedRegister", "uint32") ]
};
$ops{"ADD"} = $math_op;
$ops{"SUBTRACT"} = $math_op;
$ops{"MULTIPLY"} = $math_op;

View File

@ -213,7 +213,7 @@ namespace VM {
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
{
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first);
f /* << getRegisterValue(registers, mOp1.first) << ", " */ << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first);
return f;
}
};
@ -229,7 +229,7 @@ namespace VM {
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
{
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first);
f /* << getRegisterValue(registers, mOp1.first) << ", " */ << getRegisterValue(registers, mOp2.first);
return f;
}
};

View File

@ -119,6 +119,14 @@ SOURCE=..\debugger.cpp
# End Source File
# Begin Source File
SOURCE=..\exception.cpp
# End Source File
# Begin Source File
SOURCE=..\exception_msgs.cpp
# End Source File
# Begin Source File
SOURCE=..\hash.cpp
# End Source File
# Begin Source File
@ -147,6 +155,10 @@ SOURCE=..\jstypes.cpp
# End Source File
# Begin Source File
SOURCE=..\lexutils.cpp
# End Source File
# Begin Source File
SOURCE=..\numerics.cpp
# End Source File
# Begin Source File
@ -179,6 +191,10 @@ SOURCE=..\cpucfg.h
# End Source File
# Begin Source File
SOURCE=..\exception.h
# End Source File
# Begin Source File
SOURCE=..\gc_allocator.h
# End Source File
# Begin Source File
@ -219,6 +235,10 @@ SOURCE=..\jstypes.h
# End Source File
# Begin Source File
SOURCE=..\lexutils.h
# End Source File
# Begin Source File
SOURCE=..\nodefactory.h
# End Source File
# Begin Source File

View File

@ -26,6 +26,7 @@
DIVIDE, /* dest, source1, source2 */
ELEM_XCR, /* dest, base, index, value */
GENERIC_BINARY_OP, /* dest, op, source1, source2 */
GET_CLOSURE, /* dest, closure depth */
GET_ELEMENT, /* dest, base, index */
GET_METHOD, /* result, target base, index */
GET_PROP, /* dest, object, prop name */
@ -43,6 +44,7 @@
NEGATE, /* dest, source */
NEW_ARRAY, /* dest */
NEW_CLASS, /* dest, class */
NEW_CLOSURE, /* dest, ICodeModule */
NEW_FUNCTION, /* dest, ICodeModule */
NEW_OBJECT, /* dest, constructor */
NOP, /* do nothing and like it */
@ -402,6 +404,22 @@
}
};
class GetClosure : public Instruction_2<TypedRegister, uint32> {
public:
/* dest, closure depth */
GetClosure (TypedRegister aOp1, uint32 aOp2) :
Instruction_2<TypedRegister, uint32>
(GET_CLOSURE, aOp1, aOp2) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[GET_CLOSURE] << "\t" << mOp1 << ", " << mOp2;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << getRegisterValue(registers, mOp1.first);
return f;
}
};
class GetElement : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
public:
/* dest, base, index */
@ -666,6 +684,22 @@
}
};
class NewClosure : public Instruction_2<TypedRegister, ICodeModule*> {
public:
/* dest, ICodeModule */
NewClosure (TypedRegister aOp1, ICodeModule* aOp2) :
Instruction_2<TypedRegister, ICodeModule*>
(NEW_CLOSURE, aOp1, aOp2) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[NEW_CLOSURE] << "\t" << mOp1 << ", " << "ICodeModule";
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << getRegisterValue(registers, mOp1.first);
return f;
}
};
class NewFunction : public Instruction_2<TypedRegister, ICodeModule*> {
public:
/* dest, ICodeModule */
@ -1165,6 +1199,7 @@
"DIVIDE ",
"ELEM_XCR ",
"GENERIC_BINARY_OP ",
"GET_CLOSURE ",
"GET_ELEMENT ",
"GET_METHOD ",
"GET_PROP ",
@ -1182,6 +1217,7 @@
"NEGATE ",
"NEW_ARRAY ",
"NEW_CLASS ",
"NEW_CLOSURE ",
"NEW_FUNCTION ",
"NEW_OBJECT ",
"NOP ",

View File

@ -73,7 +73,7 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
//
ICodeGenerator::ICodeGenerator(Context *cx, JSClass *aClass, ICodeGeneratorFlags flags)
ICodeGenerator::ICodeGenerator(Context *cx, ICodeGenerator *containingFunction, JSClass *aClass, ICodeGeneratorFlags flags)
: mTopRegister(0),
mExceptionRegister(TypedRegister(NotARegister, &None_Type)),
variableList(new VariableList()),
@ -83,7 +83,8 @@ ICodeGenerator::ICodeGenerator(Context *cx, JSClass *aClass, ICodeGeneratorFlags
mClass(aClass),
mFlags(flags),
pLabels(NULL),
mInitName(cx->getWorld().identifiers["__init__"])
mInitName(cx->getWorld().identifiers["__init__"]),
mContainingFunction(containingFunction)
{
iCode = new InstructionStream();
iCodeOwner = true;
@ -360,7 +361,6 @@ TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, I
TypedRegister ICodeGenerator::getSlot(TypedRegister base, uint32 slot)
{
TypedRegister dest(getTempRegister(), &Any_Type);
@ -498,6 +498,22 @@ TypedRegister ICodeGenerator::bindThis(TypedRegister thisArg, TypedRegister targ
return dest;
}
TypedRegister ICodeGenerator::getClosure(uint32 count)
{
TypedRegister dest(getTempRegister(), &Any_Type);
iCode->push_back(new GetClosure(dest, count));
return dest;
}
TypedRegister ICodeGenerator::newClosure(ICodeModule *icm)
{
TypedRegister dest(getTempRegister(), &Function_Type);
iCode->push_back(new NewClosure(dest, icm));
return dest;
}
TypedRegister ICodeGenerator::getMethod(TypedRegister thisArg, uint32 slotIndex)
{
TypedRegister dest(getTempRegister(), &Any_Type);
@ -735,31 +751,70 @@ static bool isStaticName(JSClass *c, const StringAtom &name, JSType*& type, bool
return false;
}
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, bool lvalue)
ICodeGenerator::LValueKind ICodeGenerator::getVariableByName(const StringAtom &name, TypedRegister &v)
{
v = variableList->findVariable(name);
if (v.first == NotARegister)
v = parameterList->findVariable(name);
if (v.first != NotARegister)
return Var;
return NoKind;
}
ICodeGenerator::LValueKind ICodeGenerator::scanForVariable(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, TypedRegister &base)
{
LValueKind k = getVariableByName(name, v);
if (k == Var) return k;
uint32 count = 0;
ICodeGenerator *upper = mContainingFunction;
while (upper) {
k = upper->getVariableByName(name, v);
if (k == Var) {
base = getClosure(count);
slotIndex = v.first;
return Slot;
}
count++;
upper = upper->mContainingFunction;
}
return NoKind;
}
// find 'name' (unqualified) in the current context.
// for local variable, returns v.first = register number
// for slot/method, returns slotIndex and sets base appropriately
// (note closure vars also get handled this way)
// v.second is set to the type regardless
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, TypedRegister &base, bool lvalue)
{
if (!isWithinWith()) {
v = variableList->findVariable(name);
if (v.first == NotARegister)
v = parameterList->findVariable(name);
if (v.first != NotARegister)
return Var;
LValueKind k = scanForVariable(name, v, slotIndex, base);
if (k != NoKind)
return k;
else {
if (mClass) { // we're compiling a method of a class
if (!isStaticMethod()) {
if (isSlotName(mClass, name, slotIndex, v.second, lvalue))
if (isSlotName(mClass, name, slotIndex, v.second, lvalue)) {
base = TypedRegister(0, mClass);
return Slot;
if (isMethodName(mClass, name, slotIndex))
}
if (isMethodName(mClass, name, slotIndex)) {
base = TypedRegister(0, mClass);
return Method;
}
}
bool isConstructor = false;
if (isStaticName(mClass, name, v.second, isConstructor)) {
return (isConstructor) ? Constructor : Static;
}
}
// last chance - if it's a generic name in the global scope, try to get a type for it
v.second = mContext->getGlobalObject()->getType(name);
return Name;
}
}
// all bet's off, generic name & type
v.second = &Any_Type;
return Name;
}
@ -771,13 +826,12 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
/*JSType *vType = &Any_Type;*/
uint32 slotIndex;
TypedRegister v;
TypedRegister base;
const StringAtom &name = (static_cast<IdentifierExprNode *>(p))->name;
LValueKind lValueKind = resolveIdentifier(name, v, slotIndex, lvalue);
LValueKind lValueKind = resolveIdentifier(name, v, slotIndex, base, lvalue);
JSType *targetType = v.second;
TypedRegister thisBase = TypedRegister(0, mClass ? mClass : &Any_Type);
switch (use) {
case ExprNode::addEquals:
case ExprNode::subtractEquals:
@ -797,7 +851,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
v = loadName(name, v.second);
break;
case Slot:
v = getSlot(thisBase, slotIndex);
v = getSlot(base, slotIndex);
break;
case Static:
case Constructor:
@ -818,7 +872,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
saveName(name, ret);
break;
case Slot:
setSlot(thisBase, slotIndex, ret);
setSlot(base, slotIndex, ret);
break;
case Static:
case Constructor:
@ -837,7 +891,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
ret = loadName(name, v.second);
break;
case Slot:
ret = getSlot(thisBase, slotIndex);
ret = getSlot(base, slotIndex);
break;
case Static:
case Constructor:
@ -859,8 +913,8 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
saveName(name, ret);
break;
case Slot:
ret = binaryOp(xcrementOp, getSlot(thisBase, slotIndex), loadImmediate(1.0));
setSlot(thisBase, slotIndex, ret);
ret = binaryOp(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0));
setSlot(base, slotIndex, ret);
break;
case Static:
case Constructor:
@ -881,7 +935,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
ret = nameXcr(name, xcrementOp);
break;
case Slot:
ret = slotXcr(thisBase, slotIndex, xcrementOp);
ret = slotXcr(base, slotIndex, xcrementOp);
break;
case Static:
case Constructor:
@ -901,7 +955,7 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
ret = call(loadName(name), args);
break;
case Method:
ret = call(getMethod(thisBase, slotIndex), args);
ret = call(getMethod(base, slotIndex), args);
break;
case Static:
ret = call(getStatic(mClass, name), args);
@ -932,15 +986,20 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] )
}
else {
// we have <expr>.<fieldname>
const StringAtom &fieldName = static_cast<IdentifierExprNode *>(b->op2)->name;
TypedRegister base;
TypedRegister baseBase;
JSClass *clazz = NULL;
JSType *fieldType = &Any_Type;
uint32 slotIndex;
if ((b->op1->getKind() == ExprNode::identifier) && !isWithinWith()) {
// handle <basename>.<fieldname>
const StringAtom &baseName = (static_cast<IdentifierExprNode *>(b->op1))->name;
resolveIdentifier(baseName, base, slotIndex, false);
LValueKind baseKind = resolveIdentifier(baseName, base, slotIndex, baseBase, false);
if (baseKind == Slot) {
base = getSlot(baseBase, slotIndex);
}
//
// handle <class name>.<static field>
//
@ -1570,22 +1629,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
}
break;
case ExprNode::functionLiteral: // XXX FIXME!! This needs to handled by calling genFunction !!!
// - the parameter handling is all wrong
case ExprNode::functionLiteral:
{
FunctionExprNode *f = static_cast<FunctionExprNode *>(p);
ICodeGenerator icg(mContext);
icg.allocateParameter(mContext->getWorld().identifiers["this"], false); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name, false, &Any_Type);
v = v->next;
}
icg.genStmt(f->function.body);
//stdOut << icg;
ICodeModule *icm = icg.complete(extractType(f->function.resultType));
ret = newFunction(icm);
ICodeModule *icm = genFunction(f->function, false, false, NULL);
ret = newClosure(icm);
}
break;
@ -1596,9 +1644,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
ret = genExpr(b->op1);
if (b->op2->getKind() == ExprNode::identifier) {
TypedRegister t;
/*uint32 slotIndex;*/
const StringAtom &name = (static_cast<IdentifierExprNode *>(b->op2))->name;
/*LValueKind lvk = resolveIdentifier(name, t, slotIndex);*/
ASSERT(t.second == &Type_Type);
const JSValue &v = mContext->getGlobalObject()->getVariable(name);
ASSERT(v.isType());
@ -1663,26 +1709,25 @@ JSType *ICodeGenerator::extractType(ExprNode *t)
return type;
}
ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor, JSClass *superclass)
ICodeModule *ICodeGenerator::genFunction(FunctionDefinition &function, bool isStatic, bool isConstructor, JSClass *superclass)
{
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator icg(mContext, mClass, flags);
ICodeGenerator icg(mContext, this, mClass, flags);
icg.allocateParameter(mContext->getWorld().identifiers["this"], false, (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
VariableBinding *v = function.parameters;
bool unnamed = true;
uint32 positionalCount = 0;
StringFormatter s;
while (v) {
if (unnamed && (v == f->function.namedParameters)) { // Track when we hit the first named parameter.
if (unnamed && (v == function.namedParameters)) { // Track when we hit the first named parameter.
icg.parameterList->setPositionalCount(positionalCount);
unnamed = false;
}
// The rest parameter is ignored in this processing - we push it to the end of the list.
// But we need to track whether it comes before or after the |
if (v == f->function.restParameter) {
if (v == function.restParameter) {
icg.parameterList->setRestParameter( (unnamed) ? ParameterList::HasRestParameterBeforeBar : ParameterList::HasRestParameterAfterBar );
}
else {
@ -1708,8 +1753,8 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
if (unnamed) icg.parameterList->setPositionalCount(positionalCount);
// now allocate the rest parameter
if (f->function.restParameter) {
v = f->function.restParameter;
if (function.restParameter) {
v = function.restParameter;
JSType *pType = (v->type == NULL) ? &Array_Type : extractType(v->type);
if (v->name && (v->name->getKind() == ExprNode::identifier))
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name, (v->initializer != NULL), pType);
@ -1718,7 +1763,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
}
// generate the code for optional initializers
v = f->function.optParameters;
v = function.optParameters;
if (v) {
while (v) { // include the rest parameter, as it may have an initializer
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
@ -1731,7 +1776,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
icg.setLabel(l);
}
else { // an un-initialized rest parameter is still an empty array
if (v == f->function.restParameter) {
if (v == function.restParameter) {
Label *l = icg.getLabel();
icg.branchInitialized(l, p);
icg.move(p, icg.newArray());
@ -1754,7 +1799,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
ArgumentList *args = new ArgumentList();
if (superclass) {
bool foundSuperCall = false;
BlockStmtNode *b = f->function.body;
BlockStmtNode *b = function.body;
if (b && b->statements && (b->statements->getKind() == StmtNode::expression)) {
ExprStmtNode *e = static_cast<ExprStmtNode *>(b->statements);
if (e->expr->getKind() == ExprNode::call) {
@ -1779,13 +1824,13 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
icg.call(icg.bindThis(thisValue, icg.getStatic(mClass, mInitName)), args); // ok, so it's mis-named
}
if (f->function.body)
icg.genStmt(f->function.body);
if (function.body)
icg.genStmt(function.body);
if (isConstructor) {
TypedRegister thisValue = TypedRegister(0, mClass);
icg.returnStmt(thisValue);
}
return icg.complete(extractType(f->function.resultType));
return icg.complete(extractType(function.resultType));
}
TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
@ -1900,11 +1945,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (needsInstanceInitializer) {
// constructor code generator. Slot variable
// initializers get added to this function.
ccg = new ICodeGenerator(classContext, thisClass, kNoFlags);
ccg = new ICodeGenerator(classContext, NULL, thisClass, kNoFlags);
ccg->allocateParameter(mContext->getWorld().identifiers["this"], false, thisClass); // always parameter #0
}
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod); // static initializer code generator.
ICodeGenerator scg(classContext, NULL, thisClass, kIsStaticMethod); // static initializer code generator.
// static field inits, plus code to initialize
// static method slots.
StmtNode* s = classStmt->body->statements;
@ -1943,8 +1988,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
bool isConstructor = (s->getKind() == StmtNode::Constructor);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator mcg(classContext, thisClass, flags); // method code generator.
ICodeModule *icm = mcg.genFunction(f, isConstructor, superclass);
ICodeGenerator mcg(classContext, NULL, thisClass, flags); // method code generator.
ICodeModule *icm = mcg.genFunction(f->function, isStatic, isConstructor, superclass);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
if (isConstructor) {
@ -1988,7 +2033,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (!hasDefaultConstructor) {
TypedRegister thisValue = TypedRegister(0, thisClass);
ArgumentList *args = new ArgumentList();
ICodeGenerator icg(classContext, thisClass, kIsStaticMethod);
ICodeGenerator icg(classContext, NULL, thisClass, kIsStaticMethod);
icg.allocateParameter(mContext->getWorld().identifiers["this"], false, thisClass); // always parameter #0
if (superclass)
icg.call(icg.bindThis(thisValue, icg.getStatic(superclass, superclass->getName())), args);
@ -2015,7 +2060,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
case StmtNode::Function:
{
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(p);
ICodeModule *icm = genFunction(f, false, NULL);
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeModule *icm = genFunction(f->function, isStatic, false, NULL);
JSType *resultType = extractType(f->function.resultType);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
@ -2468,8 +2514,8 @@ void ICodeGenerator::readICode(const char *fileName)
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), className, superclass);
JSScope* thisScope = thisClass->getScope();
Context *classContext = new Context(mContext->getWorld(), thisScope);
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod);
ICodeGenerator ccg(classContext, thisClass, kNoFlags);
ICodeGenerator scg(classContext, NULL, thisClass, kIsStaticMethod);
ICodeGenerator ccg(classContext, NULL, thisClass, kNoFlags);
ccg.allocateParameter(mContext->getWorld().identifiers["this"], false, thisClass);
thisClass->defineStatic(mInitName, &Function_Type);
@ -2541,7 +2587,7 @@ void ICodeGenerator::readICode(const char *fileName)
if (!hasDefaultConstructor) {
TypedRegister thisValue = TypedRegister(0, thisClass);
ArgumentList *args = new ArgumentList(0);
ICodeGenerator icg(mContext, thisClass, kIsStaticMethod);
ICodeGenerator icg(mContext, NULL, thisClass, kIsStaticMethod);
icg.allocateParameter(mContext->getWorld().identifiers["this"], false, thisClass); // always parameter #0
if (superclass)
icg.call(icg.bindThis(thisValue, icg.getStatic(superclass, superclass->getName())), args);

View File

@ -217,6 +217,7 @@ namespace ICG {
LabelList *pLabels; // label for each parameter initialization entry point
const StringAtom &mInitName;
ICodeGenerator *mContainingFunction;// outer function for nested functions
std::vector<bool> mPermanentRegister;
@ -260,7 +261,6 @@ namespace ICG {
void endWith() { iCode->push_back(new Without()); }
void startStatement(uint32 pos) { (*mInstructionMap)[iCode->size()] = pos; }
ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind);
@ -272,16 +272,18 @@ namespace ICG {
void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); }
typedef enum { Var, Property, Slot, Static, Constructor, Name, Method } LValueKind;
typedef enum { NoKind, Var, Property, Slot, Static, Constructor, Name, Method } LValueKind;
LValueKind resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, bool lvalue);
LValueKind ICodeGenerator::getVariableByName(const StringAtom &name, TypedRegister &v);
LValueKind ICodeGenerator::scanForVariable(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, TypedRegister &base);
LValueKind resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex, TypedRegister &base, bool lvalue);
TypedRegister handleIdentifier(IdentifierExprNode *p, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, ArgumentList *args, bool lvalue);
TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, ArgumentList *args, bool lvalue);
ICodeModule *genFunction(FunctionStmtNode *f, bool isConstructor, JSClass *superClass);
ICodeModule *genFunction(FunctionDefinition &function, bool isStatic, bool isConstructor, JSClass *superClass);
public:
ICodeGenerator(Context *cx, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
ICodeGenerator(Context *cx, ICodeGenerator *containingFunction = NULL, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
~ICodeGenerator()
{
@ -352,6 +354,8 @@ namespace ICG {
TypedRegister directCall(JSFunction *target, ArgumentList *args);
TypedRegister bindThis(TypedRegister thisArg, TypedRegister target);
TypedRegister getMethod(TypedRegister thisArg, uint32 slotIndex);
TypedRegister getClosure(uint32 count);
TypedRegister newClosure(ICodeModule *icm);
void move(TypedRegister destination, TypedRegister source);
TypedRegister logicalNot(TypedRegister source);

View File

@ -45,7 +45,7 @@
namespace JavaScript {
namespace ICodeASM {
static uint icodemap_size = 73;
static uint icodemap_size = 75;
static struct {
char *name;
@ -74,6 +74,7 @@ namespace ICodeASM {
{"DIVIDE", {otRegister, otRegister, otRegister}},
{"ELEM_XCR", {otRegister, otRegister, otRegister, otDouble}},
{"GENERIC_BINARY_OP", {otRegister, otBinaryOp, otRegister, otRegister}},
{"GET_CLOSURE", {otRegister, otUInt32}},
{"GET_ELEMENT", {otRegister, otRegister, otRegister}},
{"GET_METHOD", {otRegister, otRegister, otUInt32}},
{"GET_PROP", {otRegister, otRegister, otStringAtom}},
@ -91,6 +92,7 @@ namespace ICodeASM {
{"NEGATE", {otRegister, otRegister}},
{"NEW_ARRAY", {otRegister}},
{"NEW_CLASS", {otRegister, otJSClass}},
{"NEW_CLOSURE", {otRegister, otICodeModule}},
{"NEW_FUNCTION", {otRegister, otICodeModule}},
{"NEW_OBJECT", {otRegister, otRegister}},
{"NOP", {otNone}},
@ -204,153 +206,159 @@ namespace ICodeASM {
i = new GenericBinaryOP (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<BinaryOperator::BinaryOp>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0), TypedRegister(static_cast<Register>(node->operand[3].data), 0));
break;
case 23:
i = new GetElement (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new GetClosure (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<uint32>(node->operand[1].data));
break;
case 24:
i = new GetMethod (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data));
i = new GetElement (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 25:
i = new GetProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data));
i = new GetMethod (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data));
break;
case 26:
i = new GetSlot (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data));
i = new GetProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data));
break;
case 27:
i = new GetStatic (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data), static_cast<uint32>(node->operand[2].data));
i = new GetSlot (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data));
break;
case 28:
i = new Instanceof (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new GetStatic (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data), static_cast<uint32>(node->operand[2].data));
break;
case 29:
i = new Jsr (reinterpret_cast<Label*>(node->operand[0].data));
i = new Instanceof (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 30:
i = new LoadBoolean (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<bool>(node->operand[1].data));
i = new Jsr (reinterpret_cast<Label*>(node->operand[0].data));
break;
case 31:
i = new LoadImmediate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<double>(node->operand[1].data));
i = new LoadBoolean (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<bool>(node->operand[1].data));
break;
case 32:
i = new LoadName (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data));
i = new LoadImmediate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<double>(node->operand[1].data));
break;
case 33:
i = new LoadString (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSString*>(node->operand[1].data));
i = new LoadName (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data));
break;
case 34:
i = new Move (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new LoadString (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSString*>(node->operand[1].data));
break;
case 35:
i = new Multiply (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Move (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 36:
i = new NameXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data), static_cast<double>(node->operand[2].data));
i = new Multiply (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 37:
i = new Negate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new NameXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data), static_cast<double>(node->operand[2].data));
break;
case 38:
i = new NewArray (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new Negate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 39:
i = new NewClass (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data));
i = new NewArray (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 40:
i = new NewFunction (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<ICodeModule*>(node->operand[1].data));
i = new NewClass (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data));
break;
case 41:
i = new NewObject (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new NewClosure (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<ICodeModule*>(node->operand[1].data));
break;
case 42:
i = new Nop ();
i = new NewFunction (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<ICodeModule*>(node->operand[1].data));
break;
case 43:
i = new Not (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new NewObject (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 44:
i = new Or (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Nop ();
break;
case 45:
i = new Posate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new Not (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 46:
i = new PropXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data), static_cast<double>(node->operand[3].data));
i = new Or (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 47:
i = new Remainder (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Posate (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 48:
i = new Return (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new PropXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<const StringAtom*>(node->operand[2].data), static_cast<double>(node->operand[3].data));
break;
case 49:
i = new ReturnVoid ();
i = new Remainder (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 50:
i = new Rts ();
i = new Return (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 51:
i = new SaveName (reinterpret_cast<const StringAtom*>(node->operand[0].data), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new ReturnVoid ();
break;
case 52:
i = new SetElement (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Rts ();
break;
case 53:
i = new SetProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SaveName (reinterpret_cast<const StringAtom*>(node->operand[0].data), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 54:
i = new SetSlot (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<uint32>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SetElement (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 55:
i = new SetStatic (reinterpret_cast<JSClass*>(node->operand[0].data), static_cast<uint32>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SetProp (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<const StringAtom*>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 56:
i = new Shiftleft (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SetSlot (TypedRegister(static_cast<Register>(node->operand[0].data), 0), static_cast<uint32>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 57:
i = new Shiftright (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SetStatic (reinterpret_cast<JSClass*>(node->operand[0].data), static_cast<uint32>(node->operand[1].data), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 58:
i = new SlotXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data), static_cast<double>(node->operand[3].data));
i = new Shiftleft (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 59:
i = new StaticXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data), static_cast<uint32>(node->operand[2].data), static_cast<double>(node->operand[3].data));
i = new Shiftright (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 60:
i = new StrictEQ (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new SlotXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<uint32>(node->operand[2].data), static_cast<double>(node->operand[3].data));
break;
case 61:
i = new StrictNE (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new StaticXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSClass*>(node->operand[1].data), static_cast<uint32>(node->operand[2].data), static_cast<double>(node->operand[3].data));
break;
case 62:
i = new Subtract (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new StrictEQ (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 63:
i = new Super (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new StrictNE (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 64:
i = new Test (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
i = new Subtract (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 65:
i = new Throw (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new Super (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 66:
i = new Tryin (reinterpret_cast<Label*>(node->operand[0].data), reinterpret_cast<Label*>(node->operand[1].data));
i = new Test (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 67:
i = new Tryout ();
i = new Throw (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 68:
i = new Ushiftright (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
i = new Tryin (reinterpret_cast<Label*>(node->operand[0].data), reinterpret_cast<Label*>(node->operand[1].data));
break;
case 69:
i = new VarXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<double>(node->operand[2].data));
i = new Tryout ();
break;
case 70:
i = new Within (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
i = new Ushiftright (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;
case 71:
i = new Without ();
i = new VarXcr (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), static_cast<double>(node->operand[2].data));
break;
case 72:
i = new Within (TypedRegister(static_cast<Register>(node->operand[0].data), 0));
break;
case 73:
i = new Without ();
break;
case 74:
i = new Xor (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), TypedRegister(static_cast<Register>(node->operand[2].data), 0));
break;

View File

@ -64,81 +64,6 @@ using namespace JSMathClass;
// These classes are private to the JS interpreter.
/**
*
*/
struct Handler: public gc_base {
Handler(Label *catchLabel, Label *finallyLabel)
: catchTarget(catchLabel), finallyTarget(finallyLabel) {}
Label *catchTarget;
Label *finallyTarget;
};
typedef std::vector<Handler *> CatchStack;
/**
* Represents the current function's invocation state.
*/
struct Activation : public gc_base {
JSValues mRegisters;
ICodeModule* mICode;
CatchStack catchStack;
Activation(ICodeModule* iCode, const JSValues& args)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
// copy arg list to initial registers.
JSValues::iterator dest = mRegisters.begin();
for (JSValues::const_iterator src = args.begin(),
end = args.end(); src != end; ++src, ++dest) {
*dest = *src;
}
}
Activation(ICodeModule* iCode, Activation* caller, const JSValue thisArg,
const ArgumentList* list)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
// copy caller's parameter list to initial registers.
JSValues::iterator dest = mRegisters.begin();
*dest++ = thisArg;
const JSValues& params = caller->mRegisters;
for (ArgumentList::const_iterator src = list->begin(),
end = list->end(); src != end; ++src, ++dest) {
Register r = (*src).first.first;
if (r != NotARegister)
*dest = params[r];
else
*dest = JSValue(JSValue::uninitialized_tag);
}
}
// calling a binary operator, no 'this'
Activation(ICodeModule* iCode, const JSValue thisArg, const JSValue arg1, const JSValue arg2)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
mRegisters[0] = thisArg;
mRegisters[1] = arg1;
mRegisters[2] = arg2;
}
// calling a getter function, no arguments
Activation(ICodeModule* iCode, const JSValue thisArg)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
mRegisters[0] = thisArg;
}
// calling a setter function, 1 argument
Activation(ICodeModule* iCode, const JSValue thisArg, const JSValue arg)
: mRegisters(iCode->itsMaxRegister + 1), mICode(iCode)
{
mRegisters[0] = thisArg;
mRegisters[1] = arg;
}
};
/**
* exception-safe class to save off values.
*/
@ -244,7 +169,7 @@ void Context::loadClass(const char *fileName)
}
JSValues& Context::getRegisters() { return mActivation->mRegisters; }
ICodeModule* Context::getICode() { return mActivation->mICode; }
ICodeModule* Context::getICode() { return mICode; }
/**
* Stores saved state from the *previous* activation, the current
@ -256,11 +181,13 @@ struct Linkage : public Context::Frame, public gc_base {
Activation* mActivation; // caller's activation.
JSScope* mScope;
TypedRegister mResult; // the desired target register for the return value
ICodeModule* mICode; // the caller function
JSClosure* mClosure;
Linkage(Linkage* linkage, InstructionIterator returnPC,
Activation* activation, JSScope* scope, TypedRegister result)
Activation* activation, JSScope* scope, TypedRegister result, ICodeModule* iCode, JSClosure *closure)
: mNext(linkage), mReturnPC(returnPC),
mActivation(activation), mScope(scope), mResult(result)
mActivation(activation), mScope(scope), mResult(result), mICode(iCode), mClosure(closure)
{
}
@ -270,7 +197,7 @@ struct Linkage : public Context::Frame, public gc_base {
{
pc = mReturnPC;
registers = &mActivation->mRegisters;
iCode = mActivation->mICode;
iCode = mICode;
}
};
@ -651,12 +578,13 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
// when invoked with empty args, make sure that 'this' is
// going to be the global object.
mActivation = new Activation(iCode, args);
mICode = iCode;
mActivation = new Activation(mICode->itsMaxRegister, args);
JSValues* registers = &mActivation->mRegisters;
if (args.size() == 0) (*registers)[0] = mGlobal;
mPC = mActivation->mICode->its_iCode->begin();
InstructionIterator endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
InstructionIterator endPC = mICode->its_iCode->end();
// stack of all catch/finally handlers available for the current activation
// to implement jsr/rts for finally code
@ -727,7 +655,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (target->isNative()) {
ArgumentList *params = op3(call);
JSValues argv(params->size() + 1);
argv[0] = target->getThis(); //(*registers)[op3(call).first];
argv[0] = target->getThis();
JSValues::size_type i = 1;
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
src != end; ++src, ++i) {
@ -786,9 +714,6 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
else { // shift the index value down by the number of positional parameters
index = (int)d;
index -= icm->itsParameters->mPositionalCount;
// StringFormatter s;
// s << ((int)d - icm->itsParameters->mPositionalCount);
// argName = &mWorld.identifiers[s];
}
TypedRegister argument = (*args)[i].first; // this is the argument whose name didn't match
@ -834,15 +759,41 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
}
}
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, op1(call));
mActivation = new Activation(icm, mActivation, target->getThis()/*(*registers)[op3(call).first]*/, callArgs);
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, op1(call), mICode, mCurrentClosure);
mICode = icm;
mActivation = new Activation(mICode->itsMaxRegister, mActivation, target->getThis(), callArgs);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
JSClosure *cl = dynamic_cast<JSClosure *>(target);
if (cl)
mCurrentClosure = cl;
continue;
}
}
case NEW_CLOSURE:
{
NewClosure* nc = static_cast<NewClosure*>(instruction);
JSClosure* cl = new JSClosure(src1(nc), mActivation, mCurrentClosure);
(*registers)[dst(nc).first] = cl;
}
break;
case GET_CLOSURE:
{
GetClosure* gc = static_cast<GetClosure*>(instruction);
uint32 count = src1(gc);
JSClosure* cl = mCurrentClosure;
while (count-- > 0) {
ASSERT(cl);
cl = cl->getPrevious();
}
(*registers)[dst(gc).first] = cl->getActivation();
}
break;
case DIRECT_CALL:
{
DirectCall* call = static_cast<DirectCall*>(instruction);
@ -862,11 +813,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, op1(call));
mActivation = new Activation(target->getICode(), mActivation, kNullValue, op3(call));
mActivation, mGlobal, op1(call), mICode, mCurrentClosure);
mICode = target->getICode();
mActivation = new Activation(mICode->itsMaxRegister, mActivation, kNullValue, op3(call));
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
}
@ -887,7 +839,9 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (linkage->mResult.first != NotARegister)
(*registers)[linkage->mResult.first] = kUndefinedValue;
mPC = linkage->mReturnPC;
endPC = mActivation->mICode->its_iCode->end();
mICode = linkage->mICode;
mCurrentClosure = linkage->mClosure;
endPC = mICode->its_iCode->end();
}
continue;
@ -911,7 +865,9 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (linkage->mResult.first != NotARegister)
(*registers)[linkage->mResult.first] = result;
mPC = linkage->mReturnPC;
endPC = mActivation->mICode->its_iCode->end();
mICode = linkage->mICode;
mCurrentClosure = linkage->mClosure;
endPC = mICode->its_iCode->end();
}
continue;
case MOVE:
@ -926,11 +882,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSFunction *getter = mGlobal->getter(*src1(ln));
if (getter) {
ASSERT(!getter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, dst(ln));
mActivation = new Activation(getter->getICode(), kNullValue);
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, dst(ln), mICode, mCurrentClosure);
mICode = getter->getICode();
mActivation = new Activation(mICode->itsMaxRegister, kNullValue);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
else
@ -943,11 +900,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSFunction *setter = mGlobal->setter(*dst(sn));
if (setter) {
ASSERT(!setter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, TypedRegister(NotARegister, &Null_Type));
mActivation = new Activation(setter->getICode(), (*registers)[src1(sn).first], kNullValue);
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, TypedRegister(NotARegister, &Null_Type), mICode, mCurrentClosure);
mICode = setter->getICode();
mActivation = new Activation(mICode->itsMaxRegister, (*registers)[src1(sn).first], kNullValue);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
else
@ -1093,21 +1051,33 @@ using JSString throughout.
GetSlot* gs = static_cast<GetSlot*>(instruction);
JSValue& value = (*registers)[src1(gs).first];
if (value.isObject()) {
JSInstance* inst = static_cast<JSInstance *>(value.object);
if (inst->hasGetter(src2(gs))) {
JSFunction* getter = inst->getter(src2(gs));
ASSERT(!getter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, dst(gs));
mActivation = new Activation(getter->getICode(), value);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
JSInstance* inst = dynamic_cast<JSInstance *>(value.object);
if (inst) {
if (inst->hasGetter(src2(gs))) {
JSFunction* getter = inst->getter(src2(gs));
ASSERT(!getter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, dst(gs), mICode, mCurrentClosure);
mICode = getter->getICode();
mActivation = new Activation(mICode->itsMaxRegister, value);
registers = &mActivation->mRegisters;
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
else
(*registers)[dst(gs).first] = (*inst)[src2(gs)];
}
else {
Activation* act = dynamic_cast<Activation *>(value.object);
if (act) {
(*registers)[dst(gs).first] = act->mRegisters[src2(gs)];
}
else
NOT_REACHED("runtime error");
}
else
(*registers)[dst(gs).first] = (*inst)[src2(gs)];
}
// XXX runtime error
else
NOT_REACHED("runtime error");
}
break;
case SET_SLOT:
@ -1115,20 +1085,33 @@ using JSString throughout.
SetSlot* ss = static_cast<SetSlot*>(instruction);
JSValue& value = (*registers)[dst(ss).first];
if (value.isObject()) {
JSInstance* inst = static_cast<JSInstance *>(value.object);
if (inst->hasSetter(src1(ss))) {
JSFunction* setter = inst->setter(src1(ss));
ASSERT(!setter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, TypedRegister(NotARegister, &Null_Type));
mActivation = new Activation(setter->getICode(), value, (*registers)[src2(ss).first]);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
JSInstance* inst = dynamic_cast<JSInstance *>(value.object);
if (inst) {
if (inst->hasSetter(src1(ss))) {
JSFunction* setter = inst->setter(src1(ss));
ASSERT(!setter->isNative());
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, TypedRegister(NotARegister, &Null_Type), mICode, mCurrentClosure);
mICode = setter->getICode();
mActivation = new Activation(mICode->itsMaxRegister, value, (*registers)[src2(ss).first]);
registers = &mActivation->mRegisters;
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
else
(*inst)[src1(ss)] = (*registers)[src2(ss).first];
}
else {
Activation* act = dynamic_cast<Activation *>(value.object);
if (act) {
act->mRegisters[src1(ss)] = (*registers)[src2(ss).first];
}
else
NOT_REACHED("runtime error");
}
else
(*inst)[src1(ss)] = (*registers)[src2(ss).first];
}
else
NOT_REACHED("runtime error");
}
break;
@ -1154,7 +1137,7 @@ using JSString throughout.
{
GenericBranch* bra =
static_cast<GenericBranch*>(instruction);
mPC = mActivation->mICode->its_iCode->begin() + ofs(bra);
mPC = mICode->its_iCode->begin() + ofs(bra);
continue;
}
break;
@ -1164,7 +1147,7 @@ using JSString throughout.
static_cast<GenericBranch*>(instruction);
ASSERT((*registers)[src1(bc).first].isBoolean());
if ((*registers)[src1(bc).first].boolean) {
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
mPC = mICode->its_iCode->begin() + ofs(bc);
continue;
}
}
@ -1175,7 +1158,7 @@ using JSString throughout.
static_cast<GenericBranch*>(instruction);
ASSERT((*registers)[src1(bc).first].isBoolean());
if (!(*registers)[src1(bc).first].boolean) {
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
mPC = mICode->its_iCode->begin() + ofs(bc);
continue;
}
}
@ -1185,7 +1168,7 @@ using JSString throughout.
GenericBranch* bc =
static_cast<GenericBranch*>(instruction);
if ((*registers)[src1(bc).first].isInitialized()) {
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
mPC = mICode->its_iCode->begin() + ofs(bc);
continue;
}
}
@ -1207,11 +1190,12 @@ using JSString throughout.
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, dst(gbo));
mActivation = new Activation(target->getICode(), kNullValue, r1, r2);
mActivation, mGlobal, dst(gbo), mICode, mCurrentClosure);
mICode = target->getICode();
mActivation = new Activation(mICode->itsMaxRegister, kNullValue, r1, r2);
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
mPC = mICode->its_iCode->begin();
endPC = mICode->its_iCode->end();
continue;
}
}
@ -1513,7 +1497,7 @@ using JSString throughout.
subroutineStack.push(++mPC);
Jsr* jsr = static_cast<Jsr*>(instruction);
uint32 offset = ofs(jsr);
mPC = mActivation->mICode->its_iCode->begin() + offset;
mPC = mICode->its_iCode->begin() + offset;
continue;
}
case RTS:
@ -1561,11 +1545,11 @@ using JSString throughout.
Handler *h = mActivation->catchStack.back();
registers = &mActivation->mRegisters;
if (h->catchTarget) {
mPC = mActivation->mICode->its_iCode->begin() + h->catchTarget->mOffset;
mPC = mICode->its_iCode->begin() + h->catchTarget->mOffset;
}
else {
ASSERT(h->finallyTarget);
mPC = mActivation->mICode->its_iCode->begin() + h->finallyTarget->mOffset;
mPC = mICode->its_iCode->begin() + h->finallyTarget->mOffset;
}
mLinkage = pLinkage;
break;
@ -1577,11 +1561,11 @@ using JSString throughout.
else {
Handler *h = mActivation->catchStack.back();
if (h->catchTarget) {
mPC = mActivation->mICode->its_iCode->begin() + h->catchTarget->mOffset;
mPC = mICode->its_iCode->begin() + h->catchTarget->mOffset;
}
else {
ASSERT(h->finallyTarget);
mPC = mActivation->mICode->its_iCode->begin() + h->finallyTarget->mOffset;
mPC = mICode->its_iCode->begin() + h->finallyTarget->mOffset;
}
continue;
}

View File

@ -40,7 +40,7 @@ namespace Interpreter {
void initContext();
public:
explicit Context(World& world, JSScope* aGlobal)
: mWorld(world), mGlobal(aGlobal), mLinkage(0), mActivation(0), mHasOperatorsPackageLoaded(false) { initContext(); }
: mWorld(world), mGlobal(aGlobal), mLinkage(0), mActivation(0), mHasOperatorsPackageLoaded(false), mCurrentClosure(0) { initContext(); }
World& getWorld() { return mWorld; }
JSScope* getGlobalObject() { return mGlobal; }
@ -102,6 +102,8 @@ namespace Interpreter {
typedef ListenerList::iterator ListenerIterator;
ListenerList mListeners;
Activation* mActivation;
ICodeModule* mICode;
JSClosure* mCurrentClosure;
bool mHasOperatorsPackageLoaded;
InstructionIterator mPC;
@ -110,6 +112,80 @@ namespace Interpreter {
}; /* class Context */
/**
*
*/
struct Handler: public gc_base {
Handler(Label *catchLabel, Label *finallyLabel)
: catchTarget(catchLabel), finallyTarget(finallyLabel) {}
Label *catchTarget;
Label *finallyTarget;
};
typedef std::vector<Handler *> CatchStack;
/**
* Represents the current function's invocation state.
*/
struct Activation : public JSObject {
JSValues mRegisters;
CatchStack catchStack;
Activation(uint32 highRegister, const JSValues& args)
: mRegisters(highRegister + 1)
{
// copy arg list to initial registers.
JSValues::iterator dest = mRegisters.begin();
for (JSValues::const_iterator src = args.begin(),
end = args.end(); src != end; ++src, ++dest) {
*dest = *src;
}
}
Activation(uint32 highRegister, Activation* caller, const JSValue thisArg,
const ArgumentList* list)
: mRegisters(highRegister + 1)
{
// copy caller's parameter list to initial registers.
JSValues::iterator dest = mRegisters.begin();
*dest++ = thisArg;
const JSValues& params = caller->mRegisters;
for (ArgumentList::const_iterator src = list->begin(),
end = list->end(); src != end; ++src, ++dest) {
Register r = (*src).first.first;
if (r != NotARegister)
*dest = params[r];
else
*dest = JSValue(JSValue::uninitialized_tag);
}
}
// calling a binary operator, no 'this'
Activation(uint32 highRegister, const JSValue thisArg, const JSValue arg1, const JSValue arg2)
: mRegisters(highRegister + 1)
{
mRegisters[0] = thisArg;
mRegisters[1] = arg1;
mRegisters[2] = arg2;
}
// calling a getter function, no arguments
Activation(uint32 highRegister, const JSValue thisArg)
: mRegisters(highRegister + 1)
{
mRegisters[0] = thisArg;
}
// calling a setter function, 1 argument
Activation(uint32 highRegister, const JSValue thisArg, const JSValue arg)
: mRegisters(highRegister + 1)
{
mRegisters[0] = thisArg;
mRegisters[1] = arg;
}
}; /* struct Activation */
} /* namespace Interpreter */
} /* namespace JavaScript */

View File

@ -347,11 +347,28 @@ namespace JSClasses {
return gc_base::operator new(n);
}
void* operator new(size_t n, uint32 slotCount)
{
if (slotCount > 0) n += sizeof(JSValue) * (slotCount - 1);
return gc_base::operator new(n);
}
#if !defined(XP_MAC)
void operator delete(void* /*ptr*/) {}
void operator delete(void* /*ptr*/, JSClass* /*thisClass*/) {}
void operator delete(void* /*ptr*/, uint32 /*slotCount*/) {}
#endif
JSInstance(uint32 slotCount)
{
mType = NULL;
// initialize extra slots with undefined.
if (slotCount > 0) {
std::uninitialized_fill(&mSlots[1], &mSlots[1] + (slotCount - 1),
JSTypes::kUndefinedValue);
}
}
JSInstance(JSClass* thisClass)
{
mType = thisClass;

View File

@ -49,6 +49,7 @@ namespace ICG {
} /* namespace ICG */
namespace Interpreter {
class Context;
struct Activation;
} /* namespace Interpreter */
} /* namespace JavaScript */
@ -504,7 +505,6 @@ namespace JSTypes {
static JSObject* FunctionPrototypeObject;
ICodeModule* mICode;
typedef JavaScript::gc_traits_finalizable<JSFunction> traits;
typedef gc_allocator<JSFunction, traits> allocator;
@ -519,7 +519,6 @@ namespace JSTypes {
{
setClass(FunctionString);
}
virtual ~JSFunction();
virtual JSValue getThis() { return kNullValue; }
@ -563,6 +562,21 @@ namespace JSTypes {
void* operator new(size_t) { return allocator::allocate(1); }
};
class JSClosure : public JSFunction {
Interpreter::Activation *mActivation;
JSClosure *mPrevious;
typedef JavaScript::gc_traits_finalizable<JSClosure> traits;
typedef gc_allocator<JSClosure, traits> allocator;
public:
JSClosure(ICodeModule* iCode, Interpreter::Activation *activation, JSClosure *previous)
: JSFunction(iCode), mActivation(activation), mPrevious(previous) {}
JSClosure* getPrevious() { return mPrevious; }
Interpreter::Activation* getActivation() { return mActivation; }
void* operator new(size_t) { return allocator::allocate(1); }
};
/**
* Provides a set of nested scopes.
*/

View File

@ -213,7 +213,7 @@ namespace VM {
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
{
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first);
f /* << getRegisterValue(registers, mOp1.first) << ", " */ << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first);
return f;
}
};
@ -229,7 +229,7 @@ namespace VM {
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
{
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first);
f /* << getRegisterValue(registers, mOp1.first) << ", " */ << getRegisterValue(registers, mOp2.first);
return f;
}
};

View File

@ -119,6 +119,14 @@ SOURCE=..\debugger.cpp
# End Source File
# Begin Source File
SOURCE=..\exception.cpp
# End Source File
# Begin Source File
SOURCE=..\exception_msgs.cpp
# End Source File
# Begin Source File
SOURCE=..\hash.cpp
# End Source File
# Begin Source File
@ -147,6 +155,10 @@ SOURCE=..\jstypes.cpp
# End Source File
# Begin Source File
SOURCE=..\lexutils.cpp
# End Source File
# Begin Source File
SOURCE=..\numerics.cpp
# End Source File
# Begin Source File
@ -179,6 +191,10 @@ SOURCE=..\cpucfg.h
# End Source File
# Begin Source File
SOURCE=..\exception.h
# End Source File
# Begin Source File
SOURCE=..\gc_allocator.h
# End Source File
# Begin Source File
@ -219,6 +235,10 @@ SOURCE=..\jstypes.h
# End Source File
# Begin Source File
SOURCE=..\lexutils.h
# End Source File
# Begin Source File
SOURCE=..\nodefactory.h
# End Source File
# Begin Source File

View File

@ -289,6 +289,18 @@ $ops{"SET_ELEMENT"} =
rem => "base, index, value",
params => [ ("TypedRegister", "TypedRegister", "TypedRegister") ]
};
$ops{"NEW_CLOSURE"} =
{
super => "Instruction_2",
rem => "dest, ICodeModule",
params => [ ("TypedRegister", "ICodeModule*") ]
};
$ops{"GET_CLOSURE"} =
{
super => "Instruction_2",
rem => "dest, closure depth",
params => [ ("TypedRegister", "uint32") ]
};
$ops{"ADD"} = $math_op;
$ops{"SUBTRACT"} = $math_op;
$ops{"MULTIPLY"} = $math_op;