Changed ArgumentList to ArgumentList*. Changed ICodeGenerator to take a

Context instead of world & global pair. Connected to ICodeAssembler from
XMLParser.


git-svn-id: svn://10.0.0.236/trunk@81552 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rogerl%netscape.com 2000-10-21 00:30:23 +00:00
parent 8f3b350acd
commit 289f607a92
24 changed files with 462 additions and 320 deletions

View File

@ -153,18 +153,18 @@
/* print() and printOperands() inherited from GenericBranch */
};
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList> {
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList*> {
public:
/* result, target, this, args */
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, ArgumentList aOp4) :
Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList>
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, ArgumentList* aOp4) :
Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList*>
(CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first) << ", " << ArgList(mOp4, registers);
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first);
return f;
}
};
@ -328,18 +328,18 @@
}
};
class DirectCall : public Instruction_3<TypedRegister, JSFunction*, ArgumentList> {
class DirectCall : public Instruction_3<TypedRegister, JSFunction*, ArgumentList*> {
public:
/* result, target, args */
DirectCall (TypedRegister aOp1, JSFunction* aOp2, ArgumentList aOp3) :
Instruction_3<TypedRegister, JSFunction*, ArgumentList>
DirectCall (TypedRegister aOp1, JSFunction* aOp2, ArgumentList* aOp3) :
Instruction_3<TypedRegister, JSFunction*, ArgumentList*>
(DIRECT_CALL, aOp1, aOp2, aOp3) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[DIRECT_CALL] << "\t" << mOp1 << ", " << "JSFunction" << ", " << mOp3;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << getRegisterValue(registers, mOp1.first) << ", " << ArgList(mOp3, registers);
f << getRegisterValue(registers, mOp1.first);
return f;
}
};

View File

@ -31,6 +31,12 @@
* file under either the NPL or the GPL.
*/
#ifdef _WIN32 // Microsoft Visual C++ 6.0 whines about name lengths over 255 getting truncated in the browser database
#pragma warning( disable : 4786)
#endif
#ifndef __icodeasm_h
#define __icodeasm_h

View File

@ -73,20 +73,19 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
//
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags)
ICodeGenerator::ICodeGenerator(Context *cx, JSClass *aClass, ICodeGeneratorFlags flags)
: mTopRegister(0),
mParameterCount(0),
mExceptionRegister(TypedRegister(NotARegister, &None_Type)),
variableList(new VariableList()),
mWorld(world),
mGlobal(global),
mContext(cx),
mInstructionMap(new InstructionMap()),
mClass(aClass),
mFlags(flags),
pLabels(NULL),
mHasRestParameter(false),
mHasNamedRestParameter(false),
mInitName(world->identifiers["__init__"])
mInitName(cx->getWorld().identifiers["__init__"])
{
iCode = new InstructionStream();
iCodeOwner = true;
@ -94,12 +93,22 @@ ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, I
JSType *ICodeGenerator::findType(const StringAtom& typeName)
{
const JSValue& type = mGlobal->getVariable(typeName);
const JSValue& type = mContext->getGlobalObject()->getVariable(typeName);
if (type.isType())
return type.type;
return &Any_Type;
}
/*
-Called to allocate parameter and variable registers, aka 'permanent' registers.
-mTopRegister is the current high-water mark.
-mPermanentRegister marks those registers given to variables/parameters.
-Theoretically, mPermanentRegister[n] can be become false when a scope ends and
the registers allocated to contained variables are then available for re-use.
-Mostly the need is to handle overlapping allocation of temps & permanents as the
variables declarations are encountered. This wouldn't be necessary if a function
presented a list of all variables, or a pre-pass executed to discover same.
*/
TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *type)
{
Register r = mTopRegister;
@ -121,25 +130,16 @@ TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *t
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, findType(typeName));
}
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, &Any_Type);
}
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, JSType *type)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, type);
}
@ -493,7 +493,7 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1,
TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg, ArgumentList *args)
{
TypedRegister dest(getTempRegister(), &Any_Type);
Call *instr = new Call(dest, target, thisArg, *args);
Call *instr = new Call(dest, target, thisArg, args);
iCode->push_back(instr);
return dest;
}
@ -501,7 +501,7 @@ TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg,
TypedRegister ICodeGenerator::directCall(JSFunction *target, ArgumentList *args)
{
TypedRegister dest(getTempRegister(), &Any_Type);
DirectCall *instr = new DirectCall(dest, target, *args);
DirectCall *instr = new DirectCall(dest, target, args);
iCode->push_back(instr);
return dest;
}
@ -757,7 +757,7 @@ ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &n
return (isConstructor) ? Constructor : Static;
}
}
v.second = mGlobal->getType(name);
v.second = mContext->getGlobalObject()->getType(name);
return Name;
}
}
@ -946,7 +946,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
// handle <class name>.<static field>
//
if (base.second == &Type_Type) {
const JSValue &v = mGlobal->getVariable(baseName);
const JSValue &v = mContext->getGlobalObject()->getVariable(baseName);
bool isConstructor;
ASSERT(v.isType()); // there's no other way that base.second could be &Type_Type, right?
clazz = dynamic_cast<JSClass*>(v.type);
@ -1154,23 +1154,23 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::New:
{
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
ArgumentList args;
ArgumentList *args = new ArgumentList();
ExprPairList *p = i->pairs;
while (p) {
if (p->field && (p->field->getKind() == ExprNode::identifier))
args.push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
args->push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
else
args.push_back(Argument(genExpr(p->value), NULL ));
args->push_back(Argument(genExpr(p->value), NULL ));
p = p->next;
}
if (i->op->getKind() == ExprNode::identifier) {
const StringAtom &className = static_cast<IdentifierExprNode *>(i->op)->name;
const JSValue& value = mGlobal->getVariable(className);
const JSValue& value = mContext->getGlobalObject()->getVariable(className);
if (value.isType()) {
JSClass* clazz = dynamic_cast<JSClass*>(value.type);
if (clazz) {
ret = newClass(clazz);
ret = call(getStatic(clazz, className), ret, &args);
ret = call(getStatic(clazz, className), ret, args);
}
else {
//
@ -1178,7 +1178,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
//
JSFunction *f = value.type->getConstructor();
if (f)
ret = directCall(f, &args);
ret = directCall(f, args);
else
NOT_REACHED("new <name>, where <name> is not a new-able type (whatever that means)"); // XXX Runtime error.
}
@ -1187,7 +1187,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
if (value.isFunction()) {
TypedRegister f = loadName(className, value.type);
ret = newObject(f);
ret = call(f, ret, &args);
ret = call(f, ret, args);
}
else
NOT_REACHED("new <name>, where <name> is not a function"); // XXX Runtime error.
@ -1207,23 +1207,23 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::call :
{
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
ArgumentList args;
ArgumentList *args = new ArgumentList();
ExprPairList *p = i->pairs;
uint32 count = 0;
StringFormatter s;
while (p) {
if (p->field && (p->field->getKind() == ExprNode::identifier))
args.push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
args->push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
else
if (p->field && (p->field->getKind() == ExprNode::string))
args.push_back(Argument(genExpr(p->value), &mWorld->identifiers[(static_cast<StringExprNode *>(p->field))->str]));
args->push_back(Argument(genExpr(p->value), &mContext->getWorld().identifiers[(static_cast<StringExprNode *>(p->field))->str]));
else {
/* do this for new argument style to provide default 'positional' name
s << count;
args.push_back(Argument(genExpr(p->value), &mWorld->identifiers[s] ));
args->push_back(Argument(genExpr(p->value), &mContext->getWorld().identifiers[s] ));
s.clear();
*/
args.push_back(Argument(genExpr(p->value), NULL ));
args->push_back(Argument(genExpr(p->value), NULL ));
}
count++;
p = p->next;
@ -1231,17 +1231,17 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
if (i->op->getKind() == ExprNode::dot) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
ret = handleDot(b, ExprNode::call, xcrementOp, ret, &args, false);
ret = handleDot(b, ExprNode::call, xcrementOp, ret, args, false);
}
else
if (i->op->getKind() == ExprNode::identifier) {
ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, ret, &args, false);
ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, ret, args, false);
}
else
if (i->op->getKind() == ExprNode::index) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
TypedRegister base = genExpr(b->op1);
ret = call(getElement(base, genExpr(b->op2)), base, &args);
ret = call(getElement(base, genExpr(b->op2)), base, args);
}
else
ASSERT("WAH!");
@ -1279,7 +1279,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
ret = loadImmediate((static_cast<NumberExprNode *>(p))->value);
break;
case ExprNode::string :
ret = loadString(mWorld->identifiers[(static_cast<StringExprNode *>(p))->str]);
ret = loadString(mContext->getWorld().identifiers[(static_cast<StringExprNode *>(p))->str]);
break;
case ExprNode::preDecrement:
xcrementOp = SUBTRACT;
@ -1564,8 +1564,8 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::functionLiteral:
{
FunctionExprNode *f = static_cast<FunctionExprNode *>(p);
ICodeGenerator icg(mWorld, mGlobal);
icg.allocateParameter(mWorld->identifiers["this"]); // always parameter #0
ICodeGenerator icg(mContext);
icg.allocateParameter(mContext->getWorld().identifiers["this"]); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
@ -1590,7 +1590,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
const StringAtom &name = (static_cast<IdentifierExprNode *>(b->op2))->name;
/*LValueKind lvk = resolveIdentifier(name, t, slotIndex);*/
ASSERT(t.second == &Type_Type);
const JSValue &v = mGlobal->getVariable(name);
const JSValue &v = mContext->getGlobalObject()->getVariable(name);
ASSERT(v.isType());
JSClass *clazz = dynamic_cast<JSClass*>(v.type);
if (clazz)
@ -1648,8 +1648,8 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator icg(mWorld, mGlobal, mClass, flags);
icg.allocateParameter(mWorld->identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
ICodeGenerator icg(mContext, mClass, flags);
icg.allocateParameter(mContext->getWorld().identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
@ -1703,7 +1703,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
superclass constructor ourselves.
*/
TypedRegister thisValue = TypedRegister(0, mClass);
ArgumentList args;
ArgumentList *args = new ArgumentList();
if (superclass) {
bool foundSuperCall = false;
BlockStmtNode *b = f->function.body;
@ -1724,11 +1724,11 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
}
}
if (!foundSuperCall) { // invoke the default superclass constructor
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
}
}
if (mClass->hasStatic(mInitName))
icg.call(icg.getStatic(mClass, mInitName), thisValue, &args); // ok, so it's mis-named
icg.call(icg.getStatic(mClass, mInitName), thisValue, args); // ok, so it's mis-named
}
if (f->function.body)
@ -1745,9 +1745,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
TypedRegister ret(NotARegister, &None_Type);
startStatement(p->pos);
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
switch (p->getKind()) {
case StmtNode::Class:
@ -1760,14 +1757,14 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (classStmt->superclass) {
ASSERT(classStmt->superclass->getKind() == ExprNode::identifier);
IdentifierExprNode* superclassExpr = static_cast<IdentifierExprNode*>(classStmt->superclass);
const JSValue& superclassValue = mGlobal->getVariable(superclassExpr->name);
const JSValue& superclassValue = mContext->getGlobalObject()->getVariable(superclassExpr->name);
ASSERT(superclassValue.isObject() && !superclassValue.isNull());
superclass = static_cast<JSClass*>(superclassValue.object);
}
JSClass* thisClass = new JSClass(mGlobal, nameExpr->name, superclass);
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), nameExpr->name, superclass);
// is it ok for a partially defined class to appear in global scope? this is needed
// to handle recursive types, such as linked list nodes.
mGlobal->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
mContext->getGlobalObject()->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
/*
@ -1849,14 +1846,15 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (classStmt->body) {
JSScope* thisScope = thisClass->getScope();
ICodeGenerator *ccg = NULL;
Context *classContext = new Context(mContext->getWorld(), thisScope);
if (needsInstanceInitializer) {
// constructor code generator. Slot variable
// initializers get added to this function.
ccg = new ICodeGenerator(mWorld, thisScope, thisClass, kNoFlags);
ccg->allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
ccg = new ICodeGenerator(classContext, thisClass, kNoFlags);
ccg->allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
}
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod); // static initializer code generator.
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod); // static initializer code generator.
// static field inits, plus code to initialize
// static method slots.
StmtNode* s = classStmt->body->statements;
@ -1895,7 +1893,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
bool isConstructor = (s->getKind() == StmtNode::Constructor);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator mcg(mWorld, thisScope, thisClass, flags); // method code generator.
ICodeGenerator mcg(classContext, thisClass, flags); // method code generator.
ICodeModule *icm = mcg.genFunction(f, isConstructor, superclass);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
@ -1939,13 +1937,13 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
// initializer and the superclass default constructor
if (!hasDefaultConstructor) {
TypedRegister thisValue = TypedRegister(0, thisClass);
ArgumentList args;
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
icg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
ArgumentList *args = new ArgumentList();
ICodeGenerator icg(classContext, thisClass, kIsStaticMethod);
icg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
if (superclass)
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
if (thisClass->hasStatic(mInitName))
icg.call(icg.getStatic(thisClass, mInitName), thisValue, &args);
icg.call(icg.getStatic(thisClass, mInitName), thisValue, args);
icg.returnStmt(thisValue);
thisClass->defineConstructor(nameExpr->name);
scg.setStatic(thisClass, nameExpr->name, scg.newFunction(icg.complete(&Void_Type)));
@ -1956,11 +1954,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
// REVISIT: using the scope of the class to store both methods and statics.
if (scg.getICode()->size()) {
Interpreter::Context cx(*mWorld, thisScope);
ICodeModule* clinit = scg.complete(&Void_Type);
cx.interpret(clinit, JSValues());
classContext->interpret(clinit, JSValues());
delete clinit;
}
delete classContext;
}
}
break;
@ -1974,8 +1972,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
switch (f->function.prefix) {
case FunctionName::Get:
if (isTopLevel()) {
mGlobal->defineVariable(name, resultType);
mGlobal->setGetter(name, new JSFunction(icm));
mContext->getGlobalObject()->defineVariable(name, resultType);
mContext->getGlobalObject()->setGetter(name, new JSFunction(icm));
}
else {
// is this legal - a nested getter?
@ -1985,8 +1983,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
break;
case FunctionName::Set:
if (isTopLevel()) {
mGlobal->defineVariable(name, resultType);
mGlobal->setSetter(name, new JSFunction(icm));
mContext->getGlobalObject()->defineVariable(name, resultType);
mContext->getGlobalObject()->setSetter(name, new JSFunction(icm));
}
else {
// is this legal - a nested setter?
@ -1995,7 +1993,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
}
break;
case FunctionName::normal:
mGlobal->defineFunction(name, icm);
mContext->getGlobalObject()->defineFunction(name, icm);
break;
}
}
@ -2010,8 +2008,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
std::transform(fileName->begin(), fileName->end(), str.begin(), narrow);
FILE* f = fopen(str.c_str(), "r");
if (f) {
Context cx(*mWorld, mGlobal);
(void)cx.readEvalFile(f, *fileName);
(void)mContext->readEvalFile(f, *fileName);
fclose(f);
}
}
@ -2025,7 +2022,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
JSType *type = extractType(v->type);
if (isTopLevel())
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
mContext->getGlobalObject()->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
if (v->initializer) {
@ -2326,6 +2323,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
CatchClause *c = t->catches;
while (c) {
// Bind the incoming exception ...
if (mExceptionRegister.first == NotABanana)
mExceptionRegister = allocateRegister(mContext->getWorld().identifiers["__exceptionObject__"], &Any_Type);
variableList->setRegisterForVariable(c->name, mExceptionRegister);
genStmt(c->stmt);
@ -2412,17 +2411,18 @@ void ICodeGenerator::readICode(const char *fileName)
node->getValue(widenCString("name"), className);
if (node->getValue(widenCString("super"), superName)) {
const JSValue& superclassValue = mGlobal->getVariable(superName);
const JSValue& superclassValue = mContext->getGlobalObject()->getVariable(superName);
superclass = static_cast<JSClass*>(superclassValue.object);
}
JSClass* thisClass = new JSClass(mGlobal, className, superclass);
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), className, superclass);
JSScope* thisScope = thisClass->getScope();
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod);
ICodeGenerator ccg(mWorld, thisScope, thisClass, kNoFlags);
ccg.allocateParameter(mWorld->identifiers["this"], thisClass);
Context *classContext = new Context(mContext->getWorld(), thisScope);
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod);
ICodeGenerator ccg(classContext, thisClass, kNoFlags);
ccg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass);
thisClass->defineStatic(mInitName, &Function_Type);
mGlobal->defineVariable(className, &Type_Type, JSValue(thisClass));
mContext->getGlobalObject()->defineVariable(className, &Type_Type, JSValue(thisClass));
bool hasDefaultConstructor = false;
XMLNodeList &elements = node->children();
@ -2432,31 +2432,44 @@ void ICodeGenerator::readICode(const char *fileName)
if (element->name().compare(widenCString("method")) == 0) {
String methodName, resultTypeName;
element->getValue(widenCString("name"), methodName);
element->getValue(widenCString("result"), resultTypeName);
#ifdef ROB_DONE
JSType *resultType = findType(mWorld->identifiers[resultTypeName]);
element->getValue(widenCString("type"), resultTypeName);
VariableList *theVariableList = new VariableList();
theVariableList->add(mContext->getWorld().identifiers["this"], TypedRegister(0, thisClass));
uint32 pCount = 1;
XMLNodeList &parameters = element->children();
for (XMLNodeList::const_iterator k = parameters.begin(); k != parameters.end(); k++) {
XMLNode *parameter = *k;
if (parameter->name().compare(widenCString("parameter")) == 0) {
String parameterName;
String parameterTypeName;
element->getValue(widenCString("name"), parameterName);
element->getValue(widenCString("type"), parameterTypeName);
JSType *parameterType = findType(mContext->getWorld().identifiers[parameterTypeName]);
theVariableList->add(mContext->getWorld().identifiers[parameterName], TypedRegister(pCount++, parameterType));
}
}
JSType *resultType = findType(mContext->getWorld().identifiers[resultTypeName]);
String &body = element->body();
if (body.length()) {
std::string str(body.length(), char());
std::transform(body.begin(), body.end(), str.begin(), narrow);
ICodeParser icp;
ICodeParser icp(mContext);
stdOut << "Calling ICodeParser with :\n" << str << "\n";
icp.ParseSourceFromString(str);
ICodeModule *icm = new ICodeModule(icp.instructionStream(),
NULL, /* VariableList *variables */
icp.maxRegister,
1, /* uint32 maxParameter, */
NULL, /* InstructionMap *instructionMap */
false, /* bool hasRestParameter, */
false, /* bool hasNamedRestParameter */
ICodeModule *icm = new ICodeModule(icp.mInstructions,
theVariableList, /* VariableList *variables */
icp.mMaxRegister,
pCount, /* uint32 maxParameter, */
NULL, /* InstructionMap *instructionMap */
false, /* bool hasRestParameter, */
false, /* bool hasNamedRestParameter */
resultType);
thisClass->defineMethod(methodName, new JSFunction(icm));
}
#endif
}
else {
if (element->name().compare(widenCString("field")) == 0) {
@ -2465,7 +2478,7 @@ void ICodeGenerator::readICode(const char *fileName)
element->getValue(widenCString("name"), fieldName);
element->getValue(widenCString("type"), fieldType);
JSType *type = findType(mWorld->identifiers[fieldType]);
JSType *type = findType(mContext->getWorld().identifiers[fieldType]);
if (element->hasAttribute(widenCString("static")))
thisClass->defineStatic(fieldName, type);
@ -2478,28 +2491,39 @@ void ICodeGenerator::readICode(const char *fileName)
if (!hasDefaultConstructor) {
TypedRegister thisValue = TypedRegister(0, thisClass);
ArgumentList args;
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
icg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
ArgumentList *args = new ArgumentList(0);
ICodeGenerator icg(mContext, thisClass, kIsStaticMethod);
icg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
if (superclass)
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
if (thisClass->hasStatic(mInitName))
icg.call(icg.getStatic(thisClass, mInitName), thisValue, &args);
icg.call(icg.getStatic(thisClass, mInitName), thisValue, args);
icg.returnStmt(thisValue);
thisClass->defineConstructor(className);
scg.setStatic(thisClass, mWorld->identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
scg.setStatic(thisClass, mContext->getWorld().identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
}
thisClass->complete();
if (scg.getICode()->size()) {
Interpreter::Context cx(*mWorld, thisScope);
ICodeModule* clinit = scg.complete(&Void_Type);
cx.interpret(clinit, JSValues());
classContext->interpret(clinit, JSValues());
delete clinit;
}
delete classContext;
}
else {
if (node->name().compare(widenCString("script")) == 0) {
// build an icode module and execute it
}
else {
if (node->name().compare(widenCString("instance")) == 0) {
// find the appropriate class and initialize the fields
}
else {
if (node->name().compare(widenCString("object")) == 0) {
// an object literal
}
}
}
}

View File

@ -171,14 +171,13 @@ namespace ICG {
bool iCodeOwner;
LabelList labels;
Register mTopRegister; // highest (currently) alloacated register
Register mTopRegister; // highest (currently) allocated register
uint32 mParameterCount; // number of parameters declared for the function
// these must come before any variables declared.
TypedRegister mExceptionRegister; // reserved to carry the exception object.
VariableList *variableList; // name|register pair for each variable
World *mWorld; // used to register strings
JSScope *mGlobal; // the scope for compiling within
Context *mContext; // the world and global object
LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct
// maps source position to instruction index
InstructionMap *mInstructionMap;
@ -254,7 +253,7 @@ namespace ICG {
public:
ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
ICodeGenerator(Context *cx, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
~ICodeGenerator()
{

View File

@ -155,7 +155,7 @@ namespace ICodeASM {
i = new BranchTrue (reinterpret_cast<Label*>(node->operand[0].data), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 7:
i = new Call (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), *(reinterpret_cast<ArgumentList *>(node->operand[3].data)));
i = new Call (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), reinterpret_cast<ArgumentList*>(node->operand[3].data));
break;
case 8:
i = new Cast (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<JSType*>(node->operand[2].data));
@ -188,7 +188,7 @@ namespace ICodeASM {
i = new DeleteProp (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 18:
i = new DirectCall (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSFunction*>(node->operand[1].data), *(reinterpret_cast<ArgumentList *>(node->operand[2].data)));
i = new DirectCall (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSFunction*>(node->operand[1].data), reinterpret_cast<ArgumentList*>(node->operand[2].data));
break;
case 19:
i = new Divide (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));

View File

@ -96,15 +96,15 @@ struct Activation : public gc_base {
}
Activation(ICodeModule* iCode, Activation* caller, const JSValue thisArg,
const ArgumentList& list)
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) {
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];
@ -157,7 +157,7 @@ ICodeModule* Context::compileFunction(const String &source)
String filename = widenCString("Some source source");
Parser p(getWorld(), a, source, filename);
ExprNode* e = p.parseExpression(false);
ICodeGenerator icg(&getWorld(), getGlobalObject());
ICodeGenerator icg(this);
ASSERT(e->getKind() == ExprNode::functionLiteral);
FunctionExprNode* f = static_cast<FunctionExprNode*>(e);
icg.allocateParameter(getWorld().identifiers["this"]); // always parameter #0
@ -232,7 +232,7 @@ JSValue Context::readEvalFile(FILE* in, const String& fileName)
ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
{
ICodeGenerator icg(&getWorld(), getGlobalObject());
ICodeGenerator icg(this);
TypedRegister ret(NotARegister, &None_Type);
while (p) {
@ -248,7 +248,7 @@ ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
void Context::loadClass(const char *fileName)
{
ICodeGenerator icg(&getWorld(), getGlobalObject());
ICodeGenerator icg(this);
icg.readICode(fileName); // loads it into the global object
}
@ -702,11 +702,11 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (!target)
throw new JSException("Call to non callable object");
if (target->isNative()) {
ArgumentList &params = op4(call);
JSValues argv(params.size() + 1);
ArgumentList *params = op4(call);
JSValues argv(params->size() + 1);
argv[0] = (*registers)[op3(call).first];
JSValues::size_type i = 1;
for (ArgumentList::const_iterator src = params.begin(), end = params.end();
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first.first];
}
@ -717,12 +717,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
}
else {
ICodeModule *icm = target->getICode();
ArgumentList &args = op4(call);
ArgumentList *args = op4(call);
// mParameterCount includes 'this' and also 1 for a named rest parameter
//
uint32 pCount = icm->mParameterCount - 1;
ArgumentList callArgs(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
ArgumentList *callArgs = new ArgumentList(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
if (icm->mHasNamedRestParameter) pCount--;
/*
@ -740,19 +740,19 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSArray *restArg = NULL;
uint32 restIndex = 0;
uint32 i;
for (i = 0; i < args.size(); i++) {
if (args[i].second) { // a named argument
TypedRegister r = icm->itsVariables->findVariable(*(args[i].second));
for (i = 0; i < args->size(); i++) {
if ((*args)[i].second) { // a named argument
TypedRegister r = icm->itsVariables->findVariable(*((*args)[i].second));
bool isParameter = false;
if (r.first != NotABanana) { // we found the name in the target's list of variables
if (r.first < icm->mParameterCount) { // make sure we didn't match a local var
ASSERT(r.first <= callArgs.size());
ASSERT(r.first <= callArgs->size());
// the named argument is arriving in slot i, but needs to be r instead
// r.first is the intended target register, we subtract 1 since the callArgs array doesn't include 'this'
// here's where we could detect over-writing a positional arg with a named one if that is illegal
// if (callArgs[r.first - 1].first.first != NotARegister)...
(*registers)[args[i].first.first] = (*registers)[args[i].first.first].convert(r.second);
callArgs[r.first - 1] = Argument(args[i].first, NULL); // no need to copy the name through?
(*registers)[(*args)[i].first.first] = (*registers)[(*args)[i].first.first].convert(r.second);
(*callArgs)[r.first - 1] = Argument((*args)[i].first, NULL); // no need to copy the name through?
isParameter = true;
}
}
@ -761,12 +761,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (icm->mHasNamedRestParameter) {
if (restArg == NULL) {
restArg = new JSArray();
restArg->setProperty(*args[i].second, (*registers)[args[i].first.first]);
(*registers)[args[i].first.first] = restArg;
callArgs[pCount] = Argument(TypedRegister(args[i].first.first, &Array_Type), NULL);
restArg->setProperty(*(*args)[i].second, (*registers)[(*args)[i].first.first]);
(*registers)[(*args)[i].first.first] = restArg;
(*callArgs)[pCount] = Argument(TypedRegister((*args)[i].first.first, &Array_Type), NULL);
}
else
restArg->setProperty(*args[i].second, (*registers)[args[i].first.first]);
restArg->setProperty(*(*args)[i].second, (*registers)[(*args)[i].first.first]);
}
// else just throw it away
@ -782,12 +782,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (icm->mHasNamedRestParameter) {
if (restArg == NULL) {
restArg = new JSArray();
(*restArg)[restIndex++] = (*registers)[args[i].first.first];
(*registers)[args[i].first.first] = restArg;
callArgs[pCount] = Argument(TypedRegister(args[i].first.first, &Array_Type), NULL);
(*restArg)[restIndex++] = (*registers)[(*args)[i].first.first];
(*registers)[(*args)[i].first.first] = restArg;
(*callArgs)[pCount] = Argument(TypedRegister((*args)[i].first.first, &Array_Type), NULL);
}
else
(*restArg)[restIndex++] = (*registers)[args[i].first.first];
(*restArg)[restIndex++] = (*registers)[(*args)[i].first.first];
}
// else just throw it away
}
@ -796,14 +796,14 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
}
else {
TypedRegister r = icm->itsVariables->getRegister(i + 1); // the variable list includes 'this'
(*registers)[args[i].first.first] = (*registers)[args[i].first.first].convert(r.second);
callArgs[i] = args[i]; // it's a positional, just slap it in place
(*registers)[(*args)[i].first.first] = (*registers)[(*args)[i].first.first].convert(r.second);
(*callArgs)[i] = (*args)[i]; // it's a positional, just slap it in place
}
}
}
uint32 contiguousArgs = 0;
for (i = 0; i < args.size(); i++) {
Argument &arg = args[i];
for (i = 0; i < args->size(); i++) {
Argument &arg = (*args)[i];
if (arg.first.first == NotARegister) break;
contiguousArgs++;
}
@ -824,10 +824,10 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
DirectCall* call = static_cast<DirectCall*>(instruction);
JSFunction *target = op2(call);
if (target->isNative()) {
ArgumentList &params = op3(call);
JSValues argv(params.size() + 1);
ArgumentList *params = op3(call);
JSValues argv(params->size() + 1);
JSValues::size_type i = 1;
for (ArgumentList::const_iterator src = params.begin(), end = params.end();
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first.first];
}

View File

@ -213,6 +213,7 @@ class Tracer : public Context::Listener {
};
//#define HAVE_GEORGE_TRACE_IT
//#define TEST_XML_LOADER
static void readEvalPrint(FILE *in, World &world)
{
@ -302,7 +303,7 @@ static void readEvalPrint(FILE *in, World &world)
stdOut << '\n';
}
//#define HAVE_GEORGE_TRACE_IT
char * tests[] = {
"function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" ,
@ -327,7 +328,7 @@ static void testCompile()
Arena a;
Parser p(world, a, testScript, widenCString("testCompile"));
StmtNode *parsedStatements = p.parseProgram();
ICodeGenerator icg(&world, &glob);
ICodeGenerator icg(&cx);
StmtNode *s = parsedStatements;
while (s) {
icg.genStmt(s);

View File

@ -31,6 +31,7 @@
* file under either the NPL or the GPL.
*/
#ifndef jsclasses_h
#define jsclasses_h

View File

@ -47,12 +47,12 @@ Formatter& operator<< (Formatter& f, Instruction& i)
return i.print(f);
}
Formatter& operator<< (Formatter& f, ArgumentList& rl)
Formatter& operator<< (Formatter& f, ArgumentList* rl)
{
Argument* e = rl.end();
Argument* e = rl->end();
f << "(";
for (ArgumentList::iterator r = rl.begin(); r != e; r++) {
for (ArgumentList::iterator r = rl->begin(); r != e; r++) {
f << "R" << r->first.first;
if ((r + 1) != e)
f << ", ";
@ -64,10 +64,10 @@ Formatter& operator<< (Formatter& f, ArgumentList& rl)
Formatter& operator<< (Formatter& f, const ArgList& al)
{
const ArgumentList& rl = al.mList;
const ArgumentList* rl = al.mList;
const JSValues& registers = al.mRegisters;
f << "(";
ArgumentList::const_iterator i = rl.begin(), e = rl.end();
ArgumentList::const_iterator i = rl->begin(), e = rl->end();
if (i != e) {
Argument r = *i++;
f << getRegisterValue(registers, r.first.first);

View File

@ -97,16 +97,16 @@ namespace VM {
* Helper to print Call operands.
*/
struct ArgList {
const ArgumentList& mList;
const ArgumentList* mList;
const JSValues& mRegisters;
ArgList(const ArgumentList& rl, const JSValues& registers)
ArgList(const ArgumentList* rl, const JSValues& registers)
: mList(rl), mRegisters(registers) {}
};
/********************************************************************/
Formatter& operator<< (Formatter& f, Instruction& i);
Formatter& operator<< (Formatter& f, ArgumentList& rl);
Formatter& operator<< (Formatter& f, ArgumentList* rl);
Formatter& operator<< (Formatter& f, const ArgList& al);
Formatter& operator<< (Formatter& f, InstructionStream& is);
Formatter& operator<< (Formatter& f, TypedRegister& r);

View File

@ -124,12 +124,32 @@ void XMLParser::parseAttrValue(String &val)
}
}
void XMLParser::parseStringLiteral(String &val)
{
char quotech = mReader.get();
if ((quotech != '\"') || (quotech != '\''))
syntaxError("\" or \' expected");
else {
mReader.beginRecording(val);
while (true) {
char ch = mReader.get();
if (mReader.getEof())
syntaxError("Unterminated string literal");
if (ch == quotech)
break;
mReader.recordChar(ch);
}
mReader.endRecording();
}
}
XMLTag *XMLParser::parseTag()
{
XMLTag *tag = new XMLTag();
char ch = mReader.peek();
if (ch == '/') {
tag->setEndTag();
tag->setTag(EndTag);
mReader.skip(1);
}
else {
@ -137,7 +157,7 @@ XMLTag *XMLParser::parseTag()
mReader.skip(1);
if (mReader.match("--", 2)) {
mReader.skip(2);
tag->setComment();
tag->setTag(CommentTag);
while (true) {
ch = mReader.get();
if (mReader.getEof())
@ -154,6 +174,25 @@ XMLTag *XMLParser::parseTag()
if (mReader.isLineBreak(ch))
mReader.beginLine();
}
} else {
if (mReader.match("[CDATA[", 7)) {
mReader.skip(7);
tag->setTag(CDataTag);
while (true) {
ch = mReader.get();
if (mReader.getEof())
syntaxError("Unterminated CDATA tag");
if (ch == ']') {
if (mReader.match("]>", 2)) {
mReader.skip(2);
return tag;
}
}
else
if (mReader.isLineBreak(ch))
mReader.beginLine();
}
}
}
}
}
@ -174,7 +213,7 @@ XMLTag *XMLParser::parseTag()
if (mReader.getEof())
syntaxError("Unterminated tag");
if (ch == '/') {
tag->setEmpty();
tag->setTag(EmptyTag);
ch = mReader.get();
}
if (ch != '>')
@ -197,7 +236,7 @@ void XMLParser::parseTagBody(XMLNode *parent, XMLTag *startTag)
break;
else {
XMLNode *child = new XMLNode(parent, tag);
if (!tag->isEmpty())
if (tag->hasContent())
parseTagBody(child, tag);
}
}

View File

@ -10,7 +10,7 @@
namespace JavaScript {
typedef enum {Tag, EmptyTag, EndTag, CommentTag, DocTypeTag, ProcessInstructionTag } TagFlag;
typedef enum {Tag, EmptyTag, EndTag, CommentTag, DocTypeTag, ProcessInstructionTag, CDataTag } TagFlag;
class XMLLexer
@ -68,14 +68,14 @@ public:
String &name() { return mName; }
void setEmpty() { mFlag = EmptyTag; }
void setComment() { mFlag = EmptyTag; }
void setEndTag() { mFlag = EndTag; }
void setTag(TagFlag f) { mFlag = f; }
bool isEmpty() const { return mFlag == EmptyTag; }
bool isEndTag() const { return mFlag == EndTag; }
bool isComment() const { return mFlag == CommentTag; }
bool hasContent() const { return mFlag == Tag; }
String mName;
TagFlag mFlag;
AttributeList mAttributeList;
@ -152,6 +152,7 @@ public:
XMLParser(const char *fileName) : mReader(fileName) { }
void parseStringLiteral(String &val);
void parseName(String &id);
void parseWhiteSpace();

View File

@ -153,18 +153,18 @@
/* print() and printOperands() inherited from GenericBranch */
};
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList> {
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList*> {
public:
/* result, target, this, args */
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, ArgumentList aOp4) :
Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList>
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, ArgumentList* aOp4) :
Instruction_4<TypedRegister, TypedRegister, TypedRegister, ArgumentList*>
(CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first) << ", " << ArgList(mOp4, registers);
f << getRegisterValue(registers, mOp1.first) << ", " << getRegisterValue(registers, mOp2.first) << ", " << getRegisterValue(registers, mOp3.first);
return f;
}
};
@ -328,18 +328,18 @@
}
};
class DirectCall : public Instruction_3<TypedRegister, JSFunction*, ArgumentList> {
class DirectCall : public Instruction_3<TypedRegister, JSFunction*, ArgumentList*> {
public:
/* result, target, args */
DirectCall (TypedRegister aOp1, JSFunction* aOp2, ArgumentList aOp3) :
Instruction_3<TypedRegister, JSFunction*, ArgumentList>
DirectCall (TypedRegister aOp1, JSFunction* aOp2, ArgumentList* aOp3) :
Instruction_3<TypedRegister, JSFunction*, ArgumentList*>
(DIRECT_CALL, aOp1, aOp2, aOp3) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[DIRECT_CALL] << "\t" << mOp1 << ", " << "JSFunction" << ", " << mOp3;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << getRegisterValue(registers, mOp1.first) << ", " << ArgList(mOp3, registers);
f << getRegisterValue(registers, mOp1.first);
return f;
}
};

View File

@ -31,6 +31,12 @@
* file under either the NPL or the GPL.
*/
#ifdef _WIN32 // Microsoft Visual C++ 6.0 whines about name lengths over 255 getting truncated in the browser database
#pragma warning( disable : 4786)
#endif
#ifndef __icodeasm_h
#define __icodeasm_h

View File

@ -73,20 +73,19 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
//
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags)
ICodeGenerator::ICodeGenerator(Context *cx, JSClass *aClass, ICodeGeneratorFlags flags)
: mTopRegister(0),
mParameterCount(0),
mExceptionRegister(TypedRegister(NotARegister, &None_Type)),
variableList(new VariableList()),
mWorld(world),
mGlobal(global),
mContext(cx),
mInstructionMap(new InstructionMap()),
mClass(aClass),
mFlags(flags),
pLabels(NULL),
mHasRestParameter(false),
mHasNamedRestParameter(false),
mInitName(world->identifiers["__init__"])
mInitName(cx->getWorld().identifiers["__init__"])
{
iCode = new InstructionStream();
iCodeOwner = true;
@ -94,12 +93,22 @@ ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, I
JSType *ICodeGenerator::findType(const StringAtom& typeName)
{
const JSValue& type = mGlobal->getVariable(typeName);
const JSValue& type = mContext->getGlobalObject()->getVariable(typeName);
if (type.isType())
return type.type;
return &Any_Type;
}
/*
-Called to allocate parameter and variable registers, aka 'permanent' registers.
-mTopRegister is the current high-water mark.
-mPermanentRegister marks those registers given to variables/parameters.
-Theoretically, mPermanentRegister[n] can be become false when a scope ends and
the registers allocated to contained variables are then available for re-use.
-Mostly the need is to handle overlapping allocation of temps & permanents as the
variables declarations are encountered. This wouldn't be necessary if a function
presented a list of all variables, or a pre-pass executed to discover same.
*/
TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *type)
{
Register r = mTopRegister;
@ -121,25 +130,16 @@ TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *t
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, findType(typeName));
}
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, &Any_Type);
}
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, JSType *type)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, type);
}
@ -493,7 +493,7 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1,
TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg, ArgumentList *args)
{
TypedRegister dest(getTempRegister(), &Any_Type);
Call *instr = new Call(dest, target, thisArg, *args);
Call *instr = new Call(dest, target, thisArg, args);
iCode->push_back(instr);
return dest;
}
@ -501,7 +501,7 @@ TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg,
TypedRegister ICodeGenerator::directCall(JSFunction *target, ArgumentList *args)
{
TypedRegister dest(getTempRegister(), &Any_Type);
DirectCall *instr = new DirectCall(dest, target, *args);
DirectCall *instr = new DirectCall(dest, target, args);
iCode->push_back(instr);
return dest;
}
@ -757,7 +757,7 @@ ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &n
return (isConstructor) ? Constructor : Static;
}
}
v.second = mGlobal->getType(name);
v.second = mContext->getGlobalObject()->getType(name);
return Name;
}
}
@ -946,7 +946,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
// handle <class name>.<static field>
//
if (base.second == &Type_Type) {
const JSValue &v = mGlobal->getVariable(baseName);
const JSValue &v = mContext->getGlobalObject()->getVariable(baseName);
bool isConstructor;
ASSERT(v.isType()); // there's no other way that base.second could be &Type_Type, right?
clazz = dynamic_cast<JSClass*>(v.type);
@ -1154,23 +1154,23 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::New:
{
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
ArgumentList args;
ArgumentList *args = new ArgumentList();
ExprPairList *p = i->pairs;
while (p) {
if (p->field && (p->field->getKind() == ExprNode::identifier))
args.push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
args->push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
else
args.push_back(Argument(genExpr(p->value), NULL ));
args->push_back(Argument(genExpr(p->value), NULL ));
p = p->next;
}
if (i->op->getKind() == ExprNode::identifier) {
const StringAtom &className = static_cast<IdentifierExprNode *>(i->op)->name;
const JSValue& value = mGlobal->getVariable(className);
const JSValue& value = mContext->getGlobalObject()->getVariable(className);
if (value.isType()) {
JSClass* clazz = dynamic_cast<JSClass*>(value.type);
if (clazz) {
ret = newClass(clazz);
ret = call(getStatic(clazz, className), ret, &args);
ret = call(getStatic(clazz, className), ret, args);
}
else {
//
@ -1178,7 +1178,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
//
JSFunction *f = value.type->getConstructor();
if (f)
ret = directCall(f, &args);
ret = directCall(f, args);
else
NOT_REACHED("new <name>, where <name> is not a new-able type (whatever that means)"); // XXX Runtime error.
}
@ -1187,7 +1187,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
if (value.isFunction()) {
TypedRegister f = loadName(className, value.type);
ret = newObject(f);
ret = call(f, ret, &args);
ret = call(f, ret, args);
}
else
NOT_REACHED("new <name>, where <name> is not a function"); // XXX Runtime error.
@ -1207,23 +1207,23 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::call :
{
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
ArgumentList args;
ArgumentList *args = new ArgumentList();
ExprPairList *p = i->pairs;
uint32 count = 0;
StringFormatter s;
while (p) {
if (p->field && (p->field->getKind() == ExprNode::identifier))
args.push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
args->push_back(Argument(genExpr(p->value), &(static_cast<IdentifierExprNode *>(p->field))->name));
else
if (p->field && (p->field->getKind() == ExprNode::string))
args.push_back(Argument(genExpr(p->value), &mWorld->identifiers[(static_cast<StringExprNode *>(p->field))->str]));
args->push_back(Argument(genExpr(p->value), &mContext->getWorld().identifiers[(static_cast<StringExprNode *>(p->field))->str]));
else {
/* do this for new argument style to provide default 'positional' name
s << count;
args.push_back(Argument(genExpr(p->value), &mWorld->identifiers[s] ));
args->push_back(Argument(genExpr(p->value), &mContext->getWorld().identifiers[s] ));
s.clear();
*/
args.push_back(Argument(genExpr(p->value), NULL ));
args->push_back(Argument(genExpr(p->value), NULL ));
}
count++;
p = p->next;
@ -1231,17 +1231,17 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
if (i->op->getKind() == ExprNode::dot) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
ret = handleDot(b, ExprNode::call, xcrementOp, ret, &args, false);
ret = handleDot(b, ExprNode::call, xcrementOp, ret, args, false);
}
else
if (i->op->getKind() == ExprNode::identifier) {
ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, ret, &args, false);
ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, ret, args, false);
}
else
if (i->op->getKind() == ExprNode::index) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
TypedRegister base = genExpr(b->op1);
ret = call(getElement(base, genExpr(b->op2)), base, &args);
ret = call(getElement(base, genExpr(b->op2)), base, args);
}
else
ASSERT("WAH!");
@ -1279,7 +1279,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
ret = loadImmediate((static_cast<NumberExprNode *>(p))->value);
break;
case ExprNode::string :
ret = loadString(mWorld->identifiers[(static_cast<StringExprNode *>(p))->str]);
ret = loadString(mContext->getWorld().identifiers[(static_cast<StringExprNode *>(p))->str]);
break;
case ExprNode::preDecrement:
xcrementOp = SUBTRACT;
@ -1564,8 +1564,8 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::functionLiteral:
{
FunctionExprNode *f = static_cast<FunctionExprNode *>(p);
ICodeGenerator icg(mWorld, mGlobal);
icg.allocateParameter(mWorld->identifiers["this"]); // always parameter #0
ICodeGenerator icg(mContext);
icg.allocateParameter(mContext->getWorld().identifiers["this"]); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
@ -1590,7 +1590,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
const StringAtom &name = (static_cast<IdentifierExprNode *>(b->op2))->name;
/*LValueKind lvk = resolveIdentifier(name, t, slotIndex);*/
ASSERT(t.second == &Type_Type);
const JSValue &v = mGlobal->getVariable(name);
const JSValue &v = mContext->getGlobalObject()->getVariable(name);
ASSERT(v.isType());
JSClass *clazz = dynamic_cast<JSClass*>(v.type);
if (clazz)
@ -1648,8 +1648,8 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator icg(mWorld, mGlobal, mClass, flags);
icg.allocateParameter(mWorld->identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
ICodeGenerator icg(mContext, mClass, flags);
icg.allocateParameter(mContext->getWorld().identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
@ -1703,7 +1703,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
superclass constructor ourselves.
*/
TypedRegister thisValue = TypedRegister(0, mClass);
ArgumentList args;
ArgumentList *args = new ArgumentList();
if (superclass) {
bool foundSuperCall = false;
BlockStmtNode *b = f->function.body;
@ -1724,11 +1724,11 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
}
}
if (!foundSuperCall) { // invoke the default superclass constructor
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
}
}
if (mClass->hasStatic(mInitName))
icg.call(icg.getStatic(mClass, mInitName), thisValue, &args); // ok, so it's mis-named
icg.call(icg.getStatic(mClass, mInitName), thisValue, args); // ok, so it's mis-named
}
if (f->function.body)
@ -1745,9 +1745,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
TypedRegister ret(NotARegister, &None_Type);
startStatement(p->pos);
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
switch (p->getKind()) {
case StmtNode::Class:
@ -1760,14 +1757,14 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (classStmt->superclass) {
ASSERT(classStmt->superclass->getKind() == ExprNode::identifier);
IdentifierExprNode* superclassExpr = static_cast<IdentifierExprNode*>(classStmt->superclass);
const JSValue& superclassValue = mGlobal->getVariable(superclassExpr->name);
const JSValue& superclassValue = mContext->getGlobalObject()->getVariable(superclassExpr->name);
ASSERT(superclassValue.isObject() && !superclassValue.isNull());
superclass = static_cast<JSClass*>(superclassValue.object);
}
JSClass* thisClass = new JSClass(mGlobal, nameExpr->name, superclass);
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), nameExpr->name, superclass);
// is it ok for a partially defined class to appear in global scope? this is needed
// to handle recursive types, such as linked list nodes.
mGlobal->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
mContext->getGlobalObject()->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
/*
@ -1849,14 +1846,15 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (classStmt->body) {
JSScope* thisScope = thisClass->getScope();
ICodeGenerator *ccg = NULL;
Context *classContext = new Context(mContext->getWorld(), thisScope);
if (needsInstanceInitializer) {
// constructor code generator. Slot variable
// initializers get added to this function.
ccg = new ICodeGenerator(mWorld, thisScope, thisClass, kNoFlags);
ccg->allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
ccg = new ICodeGenerator(classContext, thisClass, kNoFlags);
ccg->allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
}
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod); // static initializer code generator.
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod); // static initializer code generator.
// static field inits, plus code to initialize
// static method slots.
StmtNode* s = classStmt->body->statements;
@ -1895,7 +1893,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
bool isConstructor = (s->getKind() == StmtNode::Constructor);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator mcg(mWorld, thisScope, thisClass, flags); // method code generator.
ICodeGenerator mcg(classContext, thisClass, flags); // method code generator.
ICodeModule *icm = mcg.genFunction(f, isConstructor, superclass);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
@ -1939,13 +1937,13 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
// initializer and the superclass default constructor
if (!hasDefaultConstructor) {
TypedRegister thisValue = TypedRegister(0, thisClass);
ArgumentList args;
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
icg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
ArgumentList *args = new ArgumentList();
ICodeGenerator icg(classContext, thisClass, kIsStaticMethod);
icg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
if (superclass)
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
if (thisClass->hasStatic(mInitName))
icg.call(icg.getStatic(thisClass, mInitName), thisValue, &args);
icg.call(icg.getStatic(thisClass, mInitName), thisValue, args);
icg.returnStmt(thisValue);
thisClass->defineConstructor(nameExpr->name);
scg.setStatic(thisClass, nameExpr->name, scg.newFunction(icg.complete(&Void_Type)));
@ -1956,11 +1954,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
// REVISIT: using the scope of the class to store both methods and statics.
if (scg.getICode()->size()) {
Interpreter::Context cx(*mWorld, thisScope);
ICodeModule* clinit = scg.complete(&Void_Type);
cx.interpret(clinit, JSValues());
classContext->interpret(clinit, JSValues());
delete clinit;
}
delete classContext;
}
}
break;
@ -1974,8 +1972,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
switch (f->function.prefix) {
case FunctionName::Get:
if (isTopLevel()) {
mGlobal->defineVariable(name, resultType);
mGlobal->setGetter(name, new JSFunction(icm));
mContext->getGlobalObject()->defineVariable(name, resultType);
mContext->getGlobalObject()->setGetter(name, new JSFunction(icm));
}
else {
// is this legal - a nested getter?
@ -1985,8 +1983,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
break;
case FunctionName::Set:
if (isTopLevel()) {
mGlobal->defineVariable(name, resultType);
mGlobal->setSetter(name, new JSFunction(icm));
mContext->getGlobalObject()->defineVariable(name, resultType);
mContext->getGlobalObject()->setSetter(name, new JSFunction(icm));
}
else {
// is this legal - a nested setter?
@ -1995,7 +1993,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
}
break;
case FunctionName::normal:
mGlobal->defineFunction(name, icm);
mContext->getGlobalObject()->defineFunction(name, icm);
break;
}
}
@ -2010,8 +2008,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
std::transform(fileName->begin(), fileName->end(), str.begin(), narrow);
FILE* f = fopen(str.c_str(), "r");
if (f) {
Context cx(*mWorld, mGlobal);
(void)cx.readEvalFile(f, *fileName);
(void)mContext->readEvalFile(f, *fileName);
fclose(f);
}
}
@ -2025,7 +2022,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
if (v->name && (v->name->getKind() == ExprNode::identifier)) {
JSType *type = extractType(v->type);
if (isTopLevel())
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
mContext->getGlobalObject()->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name, type);
if (v->initializer) {
@ -2326,6 +2323,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
CatchClause *c = t->catches;
while (c) {
// Bind the incoming exception ...
if (mExceptionRegister.first == NotABanana)
mExceptionRegister = allocateRegister(mContext->getWorld().identifiers["__exceptionObject__"], &Any_Type);
variableList->setRegisterForVariable(c->name, mExceptionRegister);
genStmt(c->stmt);
@ -2412,17 +2411,18 @@ void ICodeGenerator::readICode(const char *fileName)
node->getValue(widenCString("name"), className);
if (node->getValue(widenCString("super"), superName)) {
const JSValue& superclassValue = mGlobal->getVariable(superName);
const JSValue& superclassValue = mContext->getGlobalObject()->getVariable(superName);
superclass = static_cast<JSClass*>(superclassValue.object);
}
JSClass* thisClass = new JSClass(mGlobal, className, superclass);
JSClass* thisClass = new JSClass(mContext->getGlobalObject(), className, superclass);
JSScope* thisScope = thisClass->getScope();
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod);
ICodeGenerator ccg(mWorld, thisScope, thisClass, kNoFlags);
ccg.allocateParameter(mWorld->identifiers["this"], thisClass);
Context *classContext = new Context(mContext->getWorld(), thisScope);
ICodeGenerator scg(classContext, thisClass, kIsStaticMethod);
ICodeGenerator ccg(classContext, thisClass, kNoFlags);
ccg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass);
thisClass->defineStatic(mInitName, &Function_Type);
mGlobal->defineVariable(className, &Type_Type, JSValue(thisClass));
mContext->getGlobalObject()->defineVariable(className, &Type_Type, JSValue(thisClass));
bool hasDefaultConstructor = false;
XMLNodeList &elements = node->children();
@ -2432,31 +2432,44 @@ void ICodeGenerator::readICode(const char *fileName)
if (element->name().compare(widenCString("method")) == 0) {
String methodName, resultTypeName;
element->getValue(widenCString("name"), methodName);
element->getValue(widenCString("result"), resultTypeName);
#ifdef ROB_DONE
JSType *resultType = findType(mWorld->identifiers[resultTypeName]);
element->getValue(widenCString("type"), resultTypeName);
VariableList *theVariableList = new VariableList();
theVariableList->add(mContext->getWorld().identifiers["this"], TypedRegister(0, thisClass));
uint32 pCount = 1;
XMLNodeList &parameters = element->children();
for (XMLNodeList::const_iterator k = parameters.begin(); k != parameters.end(); k++) {
XMLNode *parameter = *k;
if (parameter->name().compare(widenCString("parameter")) == 0) {
String parameterName;
String parameterTypeName;
element->getValue(widenCString("name"), parameterName);
element->getValue(widenCString("type"), parameterTypeName);
JSType *parameterType = findType(mContext->getWorld().identifiers[parameterTypeName]);
theVariableList->add(mContext->getWorld().identifiers[parameterName], TypedRegister(pCount++, parameterType));
}
}
JSType *resultType = findType(mContext->getWorld().identifiers[resultTypeName]);
String &body = element->body();
if (body.length()) {
std::string str(body.length(), char());
std::transform(body.begin(), body.end(), str.begin(), narrow);
ICodeParser icp;
ICodeParser icp(mContext);
stdOut << "Calling ICodeParser with :\n" << str << "\n";
icp.ParseSourceFromString(str);
ICodeModule *icm = new ICodeModule(icp.instructionStream(),
NULL, /* VariableList *variables */
icp.maxRegister,
1, /* uint32 maxParameter, */
NULL, /* InstructionMap *instructionMap */
false, /* bool hasRestParameter, */
false, /* bool hasNamedRestParameter */
ICodeModule *icm = new ICodeModule(icp.mInstructions,
theVariableList, /* VariableList *variables */
icp.mMaxRegister,
pCount, /* uint32 maxParameter, */
NULL, /* InstructionMap *instructionMap */
false, /* bool hasRestParameter, */
false, /* bool hasNamedRestParameter */
resultType);
thisClass->defineMethod(methodName, new JSFunction(icm));
}
#endif
}
else {
if (element->name().compare(widenCString("field")) == 0) {
@ -2465,7 +2478,7 @@ void ICodeGenerator::readICode(const char *fileName)
element->getValue(widenCString("name"), fieldName);
element->getValue(widenCString("type"), fieldType);
JSType *type = findType(mWorld->identifiers[fieldType]);
JSType *type = findType(mContext->getWorld().identifiers[fieldType]);
if (element->hasAttribute(widenCString("static")))
thisClass->defineStatic(fieldName, type);
@ -2478,28 +2491,39 @@ void ICodeGenerator::readICode(const char *fileName)
if (!hasDefaultConstructor) {
TypedRegister thisValue = TypedRegister(0, thisClass);
ArgumentList args;
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
icg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
ArgumentList *args = new ArgumentList(0);
ICodeGenerator icg(mContext, thisClass, kIsStaticMethod);
icg.allocateParameter(mContext->getWorld().identifiers["this"], thisClass); // always parameter #0
if (superclass)
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, args);
if (thisClass->hasStatic(mInitName))
icg.call(icg.getStatic(thisClass, mInitName), thisValue, &args);
icg.call(icg.getStatic(thisClass, mInitName), thisValue, args);
icg.returnStmt(thisValue);
thisClass->defineConstructor(className);
scg.setStatic(thisClass, mWorld->identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
scg.setStatic(thisClass, mContext->getWorld().identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
}
thisClass->complete();
if (scg.getICode()->size()) {
Interpreter::Context cx(*mWorld, thisScope);
ICodeModule* clinit = scg.complete(&Void_Type);
cx.interpret(clinit, JSValues());
classContext->interpret(clinit, JSValues());
delete clinit;
}
delete classContext;
}
else {
if (node->name().compare(widenCString("script")) == 0) {
// build an icode module and execute it
}
else {
if (node->name().compare(widenCString("instance")) == 0) {
// find the appropriate class and initialize the fields
}
else {
if (node->name().compare(widenCString("object")) == 0) {
// an object literal
}
}
}
}

View File

@ -171,14 +171,13 @@ namespace ICG {
bool iCodeOwner;
LabelList labels;
Register mTopRegister; // highest (currently) alloacated register
Register mTopRegister; // highest (currently) allocated register
uint32 mParameterCount; // number of parameters declared for the function
// these must come before any variables declared.
TypedRegister mExceptionRegister; // reserved to carry the exception object.
VariableList *variableList; // name|register pair for each variable
World *mWorld; // used to register strings
JSScope *mGlobal; // the scope for compiling within
Context *mContext; // the world and global object
LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct
// maps source position to instruction index
InstructionMap *mInstructionMap;
@ -254,7 +253,7 @@ namespace ICG {
public:
ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
ICodeGenerator(Context *cx, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
~ICodeGenerator()
{

View File

@ -155,7 +155,7 @@ namespace ICodeASM {
i = new BranchTrue (reinterpret_cast<Label*>(node->operand[0].data), TypedRegister(static_cast<Register>(node->operand[1].data), 0));
break;
case 7:
i = new Call (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), *(reinterpret_cast<ArgumentList *>(node->operand[3].data)));
i = new Call (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), reinterpret_cast<ArgumentList*>(node->operand[3].data));
break;
case 8:
i = new Cast (TypedRegister(static_cast<Register>(node->operand[0].data), 0), TypedRegister(static_cast<Register>(node->operand[1].data), 0), reinterpret_cast<JSType*>(node->operand[2].data));
@ -188,7 +188,7 @@ namespace ICodeASM {
i = new DeleteProp (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 18:
i = new DirectCall (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSFunction*>(node->operand[1].data), *(reinterpret_cast<ArgumentList *>(node->operand[2].data)));
i = new DirectCall (TypedRegister(static_cast<Register>(node->operand[0].data), 0), reinterpret_cast<JSFunction*>(node->operand[1].data), reinterpret_cast<ArgumentList*>(node->operand[2].data));
break;
case 19:
i = new Divide (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));

View File

@ -96,15 +96,15 @@ struct Activation : public gc_base {
}
Activation(ICodeModule* iCode, Activation* caller, const JSValue thisArg,
const ArgumentList& list)
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) {
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];
@ -157,7 +157,7 @@ ICodeModule* Context::compileFunction(const String &source)
String filename = widenCString("Some source source");
Parser p(getWorld(), a, source, filename);
ExprNode* e = p.parseExpression(false);
ICodeGenerator icg(&getWorld(), getGlobalObject());
ICodeGenerator icg(this);
ASSERT(e->getKind() == ExprNode::functionLiteral);
FunctionExprNode* f = static_cast<FunctionExprNode*>(e);
icg.allocateParameter(getWorld().identifiers["this"]); // always parameter #0
@ -232,7 +232,7 @@ JSValue Context::readEvalFile(FILE* in, const String& fileName)
ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
{
ICodeGenerator icg(&getWorld(), getGlobalObject());
ICodeGenerator icg(this);
TypedRegister ret(NotARegister, &None_Type);
while (p) {
@ -248,7 +248,7 @@ ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
void Context::loadClass(const char *fileName)
{
ICodeGenerator icg(&getWorld(), getGlobalObject());
ICodeGenerator icg(this);
icg.readICode(fileName); // loads it into the global object
}
@ -702,11 +702,11 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (!target)
throw new JSException("Call to non callable object");
if (target->isNative()) {
ArgumentList &params = op4(call);
JSValues argv(params.size() + 1);
ArgumentList *params = op4(call);
JSValues argv(params->size() + 1);
argv[0] = (*registers)[op3(call).first];
JSValues::size_type i = 1;
for (ArgumentList::const_iterator src = params.begin(), end = params.end();
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first.first];
}
@ -717,12 +717,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
}
else {
ICodeModule *icm = target->getICode();
ArgumentList &args = op4(call);
ArgumentList *args = op4(call);
// mParameterCount includes 'this' and also 1 for a named rest parameter
//
uint32 pCount = icm->mParameterCount - 1;
ArgumentList callArgs(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
ArgumentList *callArgs = new ArgumentList(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
if (icm->mHasNamedRestParameter) pCount--;
/*
@ -740,19 +740,19 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSArray *restArg = NULL;
uint32 restIndex = 0;
uint32 i;
for (i = 0; i < args.size(); i++) {
if (args[i].second) { // a named argument
TypedRegister r = icm->itsVariables->findVariable(*(args[i].second));
for (i = 0; i < args->size(); i++) {
if ((*args)[i].second) { // a named argument
TypedRegister r = icm->itsVariables->findVariable(*((*args)[i].second));
bool isParameter = false;
if (r.first != NotABanana) { // we found the name in the target's list of variables
if (r.first < icm->mParameterCount) { // make sure we didn't match a local var
ASSERT(r.first <= callArgs.size());
ASSERT(r.first <= callArgs->size());
// the named argument is arriving in slot i, but needs to be r instead
// r.first is the intended target register, we subtract 1 since the callArgs array doesn't include 'this'
// here's where we could detect over-writing a positional arg with a named one if that is illegal
// if (callArgs[r.first - 1].first.first != NotARegister)...
(*registers)[args[i].first.first] = (*registers)[args[i].first.first].convert(r.second);
callArgs[r.first - 1] = Argument(args[i].first, NULL); // no need to copy the name through?
(*registers)[(*args)[i].first.first] = (*registers)[(*args)[i].first.first].convert(r.second);
(*callArgs)[r.first - 1] = Argument((*args)[i].first, NULL); // no need to copy the name through?
isParameter = true;
}
}
@ -761,12 +761,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (icm->mHasNamedRestParameter) {
if (restArg == NULL) {
restArg = new JSArray();
restArg->setProperty(*args[i].second, (*registers)[args[i].first.first]);
(*registers)[args[i].first.first] = restArg;
callArgs[pCount] = Argument(TypedRegister(args[i].first.first, &Array_Type), NULL);
restArg->setProperty(*(*args)[i].second, (*registers)[(*args)[i].first.first]);
(*registers)[(*args)[i].first.first] = restArg;
(*callArgs)[pCount] = Argument(TypedRegister((*args)[i].first.first, &Array_Type), NULL);
}
else
restArg->setProperty(*args[i].second, (*registers)[args[i].first.first]);
restArg->setProperty(*(*args)[i].second, (*registers)[(*args)[i].first.first]);
}
// else just throw it away
@ -782,12 +782,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
if (icm->mHasNamedRestParameter) {
if (restArg == NULL) {
restArg = new JSArray();
(*restArg)[restIndex++] = (*registers)[args[i].first.first];
(*registers)[args[i].first.first] = restArg;
callArgs[pCount] = Argument(TypedRegister(args[i].first.first, &Array_Type), NULL);
(*restArg)[restIndex++] = (*registers)[(*args)[i].first.first];
(*registers)[(*args)[i].first.first] = restArg;
(*callArgs)[pCount] = Argument(TypedRegister((*args)[i].first.first, &Array_Type), NULL);
}
else
(*restArg)[restIndex++] = (*registers)[args[i].first.first];
(*restArg)[restIndex++] = (*registers)[(*args)[i].first.first];
}
// else just throw it away
}
@ -796,14 +796,14 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
}
else {
TypedRegister r = icm->itsVariables->getRegister(i + 1); // the variable list includes 'this'
(*registers)[args[i].first.first] = (*registers)[args[i].first.first].convert(r.second);
callArgs[i] = args[i]; // it's a positional, just slap it in place
(*registers)[(*args)[i].first.first] = (*registers)[(*args)[i].first.first].convert(r.second);
(*callArgs)[i] = (*args)[i]; // it's a positional, just slap it in place
}
}
}
uint32 contiguousArgs = 0;
for (i = 0; i < args.size(); i++) {
Argument &arg = args[i];
for (i = 0; i < args->size(); i++) {
Argument &arg = (*args)[i];
if (arg.first.first == NotARegister) break;
contiguousArgs++;
}
@ -824,10 +824,10 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
DirectCall* call = static_cast<DirectCall*>(instruction);
JSFunction *target = op2(call);
if (target->isNative()) {
ArgumentList &params = op3(call);
JSValues argv(params.size() + 1);
ArgumentList *params = op3(call);
JSValues argv(params->size() + 1);
JSValues::size_type i = 1;
for (ArgumentList::const_iterator src = params.begin(), end = params.end();
for (ArgumentList::const_iterator src = params->begin(), end = params->end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first.first];
}

View File

@ -31,6 +31,7 @@
* file under either the NPL or the GPL.
*/
#ifndef jsclasses_h
#define jsclasses_h

View File

@ -47,12 +47,12 @@ Formatter& operator<< (Formatter& f, Instruction& i)
return i.print(f);
}
Formatter& operator<< (Formatter& f, ArgumentList& rl)
Formatter& operator<< (Formatter& f, ArgumentList* rl)
{
Argument* e = rl.end();
Argument* e = rl->end();
f << "(";
for (ArgumentList::iterator r = rl.begin(); r != e; r++) {
for (ArgumentList::iterator r = rl->begin(); r != e; r++) {
f << "R" << r->first.first;
if ((r + 1) != e)
f << ", ";
@ -64,10 +64,10 @@ Formatter& operator<< (Formatter& f, ArgumentList& rl)
Formatter& operator<< (Formatter& f, const ArgList& al)
{
const ArgumentList& rl = al.mList;
const ArgumentList* rl = al.mList;
const JSValues& registers = al.mRegisters;
f << "(";
ArgumentList::const_iterator i = rl.begin(), e = rl.end();
ArgumentList::const_iterator i = rl->begin(), e = rl->end();
if (i != e) {
Argument r = *i++;
f << getRegisterValue(registers, r.first.first);

View File

@ -97,16 +97,16 @@ namespace VM {
* Helper to print Call operands.
*/
struct ArgList {
const ArgumentList& mList;
const ArgumentList* mList;
const JSValues& mRegisters;
ArgList(const ArgumentList& rl, const JSValues& registers)
ArgList(const ArgumentList* rl, const JSValues& registers)
: mList(rl), mRegisters(registers) {}
};
/********************************************************************/
Formatter& operator<< (Formatter& f, Instruction& i);
Formatter& operator<< (Formatter& f, ArgumentList& rl);
Formatter& operator<< (Formatter& f, ArgumentList* rl);
Formatter& operator<< (Formatter& f, const ArgList& al);
Formatter& operator<< (Formatter& f, InstructionStream& is);
Formatter& operator<< (Formatter& f, TypedRegister& r);

View File

@ -124,12 +124,32 @@ void XMLParser::parseAttrValue(String &val)
}
}
void XMLParser::parseStringLiteral(String &val)
{
char quotech = mReader.get();
if ((quotech != '\"') || (quotech != '\''))
syntaxError("\" or \' expected");
else {
mReader.beginRecording(val);
while (true) {
char ch = mReader.get();
if (mReader.getEof())
syntaxError("Unterminated string literal");
if (ch == quotech)
break;
mReader.recordChar(ch);
}
mReader.endRecording();
}
}
XMLTag *XMLParser::parseTag()
{
XMLTag *tag = new XMLTag();
char ch = mReader.peek();
if (ch == '/') {
tag->setEndTag();
tag->setTag(EndTag);
mReader.skip(1);
}
else {
@ -137,7 +157,7 @@ XMLTag *XMLParser::parseTag()
mReader.skip(1);
if (mReader.match("--", 2)) {
mReader.skip(2);
tag->setComment();
tag->setTag(CommentTag);
while (true) {
ch = mReader.get();
if (mReader.getEof())
@ -154,6 +174,25 @@ XMLTag *XMLParser::parseTag()
if (mReader.isLineBreak(ch))
mReader.beginLine();
}
} else {
if (mReader.match("[CDATA[", 7)) {
mReader.skip(7);
tag->setTag(CDataTag);
while (true) {
ch = mReader.get();
if (mReader.getEof())
syntaxError("Unterminated CDATA tag");
if (ch == ']') {
if (mReader.match("]>", 2)) {
mReader.skip(2);
return tag;
}
}
else
if (mReader.isLineBreak(ch))
mReader.beginLine();
}
}
}
}
}
@ -174,7 +213,7 @@ XMLTag *XMLParser::parseTag()
if (mReader.getEof())
syntaxError("Unterminated tag");
if (ch == '/') {
tag->setEmpty();
tag->setTag(EmptyTag);
ch = mReader.get();
}
if (ch != '>')
@ -197,7 +236,7 @@ void XMLParser::parseTagBody(XMLNode *parent, XMLTag *startTag)
break;
else {
XMLNode *child = new XMLNode(parent, tag);
if (!tag->isEmpty())
if (tag->hasContent())
parseTagBody(child, tag);
}
}

View File

@ -10,7 +10,7 @@
namespace JavaScript {
typedef enum {Tag, EmptyTag, EndTag, CommentTag, DocTypeTag, ProcessInstructionTag } TagFlag;
typedef enum {Tag, EmptyTag, EndTag, CommentTag, DocTypeTag, ProcessInstructionTag, CDataTag } TagFlag;
class XMLLexer
@ -68,14 +68,14 @@ public:
String &name() { return mName; }
void setEmpty() { mFlag = EmptyTag; }
void setComment() { mFlag = EmptyTag; }
void setEndTag() { mFlag = EndTag; }
void setTag(TagFlag f) { mFlag = f; }
bool isEmpty() const { return mFlag == EmptyTag; }
bool isEndTag() const { return mFlag == EndTag; }
bool isComment() const { return mFlag == CommentTag; }
bool hasContent() const { return mFlag == Tag; }
String mName;
TagFlag mFlag;
AttributeList mAttributeList;
@ -152,6 +152,7 @@ public:
XMLParser(const char *fileName) : mReader(fileName) { }
void parseStringLiteral(String &val);
void parseName(String &id);
void parseWhiteSpace();

View File

@ -213,6 +213,7 @@ class Tracer : public Context::Listener {
};
//#define HAVE_GEORGE_TRACE_IT
//#define TEST_XML_LOADER
static void readEvalPrint(FILE *in, World &world)
{
@ -302,7 +303,7 @@ static void readEvalPrint(FILE *in, World &world)
stdOut << '\n';
}
//#define HAVE_GEORGE_TRACE_IT
char * tests[] = {
"function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" ,
@ -327,7 +328,7 @@ static void testCompile()
Arena a;
Parser p(world, a, testScript, widenCString("testCompile"));
StmtNode *parsedStatements = p.parseProgram();
ICodeGenerator icg(&world, &glob);
ICodeGenerator icg(&cx);
StmtNode *s = parsedStatements;
while (s) {
icg.genStmt(s);