mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-02 12:07:52 +00:00
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:
parent
9bf885bd61
commit
d11b23802a
@ -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 ",
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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 ",
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user