Added ICodeModule to collect extra info about executable chunks.

This commit is contained in:
rogerl%netscape.com 2000-04-08 01:04:55 +00:00
parent 365dd176a7
commit 4898874939
10 changed files with 210 additions and 102 deletions

View File

@ -37,7 +37,7 @@ namespace JavaScript {
// ICodeGenerator
//
InstructionStream *ICodeGenerator::complete()
ICodeModule *ICodeGenerator::complete()
{
#ifdef DEBUG
ASSERT(stitcher.empty());
@ -62,20 +62,29 @@ namespace JavaScript {
delete t;
}
}
markMaxRegister();
return iCode;
return new ICodeModule(iCode, maxRegister, maxVariable);
}
/***********************************************************************************************/
Register ICodeGenerator::loadVariable(uint32 frameIndex)
{
markMaxVariable(frameIndex);
Register dest = getRegister();
LoadVar *instr = new LoadVar(LOAD_VAR, dest, frameIndex);
iCode->push_back(instr);
return dest;
}
void ICodeGenerator::saveVariable(uint32 frameIndex, Register value)
{
markMaxVariable(frameIndex);
SaveVar *instr = new SaveVar(SAVE_VAR, frameIndex, value);
iCode->push_back(instr);
}
Register ICodeGenerator::loadImmediate(double value)
{
Register dest = getRegister();
@ -120,12 +129,6 @@ namespace JavaScript {
iCode->push_back(instr);
}
void ICodeGenerator::saveVariable(uint32 frameIndex, Register value)
{
SaveVar *instr = new SaveVar(SAVE_VAR, frameIndex, value);
iCode->push_back(instr);
}
Register ICodeGenerator::op(ICodeOp op, Register source)
{
Register dest = getRegister();
@ -585,7 +588,7 @@ namespace JavaScript {
for (InstructionIterator i = iCode->begin(); i != iCode->end(); i++) {
for (LabelList::iterator k = labels.begin(); k != labels.end(); k++)
if ((*k)->itsOffset == (i - iCode->begin())) {
if ((*k)->itsOffset == (ptrdiff_t)(i - iCode->begin())) {
//s << "label #" << (k - labels.begin()) << ":\n";
s << "#" << (i - iCode->begin());
break;
@ -691,7 +694,7 @@ namespace JavaScript {
s << "\n";
}
for (LabelList::iterator k = labels.begin(); k != labels.end(); k++)
if ((*k)->itsOffset == (iCode->end() - iCode->begin())) {
if ((*k)->itsOffset == (ptrdiff_t)(iCode->end() - iCode->begin())) {
// s << "label #" << (k - labels.begin()) << ":\n";
// s << "#" << (i - iCode->begin());
}

View File

@ -31,50 +31,54 @@ namespace JavaScript {
typedef uint32 Register;
typedef std::vector<Register> RegisterList;
enum ICodeOp {
// Operand1 Operand2 Operand3
// Operand1 Operand2 Operand3
NOP,
MOVE_TO, // Destination Register Source Register
MOVE_TO, // Destination Register Source Register
LOAD_VAR, // Destination Register index of frame slot
SAVE_VAR, // index of frame slot Source Register
LOAD_VAR, // Destination Register index of frame slot
SAVE_VAR, // index of frame slot Source Register
LOAD_IMMEDIATE, // Destination Register immediate (double)
LOAD_IMMEDIATE, // Destination Register immediate (double)
LOAD_NAME, // Destination Register StringAtom &
SAVE_NAME, // StringAtom & Source Register
LOAD_NAME, // Destination Register StringAtom &
SAVE_NAME, // StringAtom & Source Register
NEW_OBJECT, // Destination Register
GET_PROP, // Destination Register StringAtom & Base Register
SET_PROP, // StringAtom & Base Register Source Register
GET_PROP, // Destination Register StringAtom & Base Register
SET_PROP, // StringAtom & Base Register Source Register
ADD, // Destination Register Source Register 1 Source Register 2
ADD, // Destination Register Source Register 1 Source Register 2
SUBTRACT,
MULTIPLY,
DIVIDE,
// maintain contiguity
COMPARE_LT, // Destination Register Source Register 1 Source Register 2
COMPARE_LT, // Destination Register Source Register 1 Source Register 2
COMPARE_LE,
COMPARE_EQ,
COMPARE_NE,
COMPARE_GE,
COMPARE_GT,
NOT, // Destination Register Source Register
NOT, // Destination Register Source Register
BRANCH, // Target label
BRANCH_LT, // Target label Condition Register
BRANCH_LT, // Target label Condition Register
BRANCH_LE,
BRANCH_EQ,
BRANCH_NE,
BRANCH_GE,
BRANCH_GT,
RETURN // Source Register
RETURN, // Source Register
CALL, // Destination Register Target Register Arguments
};
class Instruction {
@ -185,6 +189,12 @@ namespace JavaScript {
: Instruction_2<uint32, Register>(op, offset, condition) { }
};
class Call : public Instruction_3<Register, Register, RegisterList> {
public:
Call(Register result, Register target, RegisterList args)
: Instruction_3<Register, Register, RegisterList>(CALL, result, target, args) { }
};
/****************************************************************/
@ -206,6 +216,16 @@ namespace JavaScript {
Label *continueLabel;
};
class ICodeModule {
public:
ICodeModule(InstructionStream *iCode, uint32 maxRegister, uint32 maxVariable)
: its_iCode(iCode), itsMaxRegister(maxRegister), itsMaxVariable(maxVariable) { }
InstructionStream *its_iCode;
uint32 itsMaxRegister;
uint32 itsMaxVariable;
};
/****************************************************************/
// An ICodeGenerator provides the interface between the parser and the interpreter.
@ -220,15 +240,21 @@ namespace JavaScript {
std::vector<ICodeState *> stitcher;
void markMaxRegister() { if (topRegister > maxRegister) maxRegister = topRegister; }
void markMaxVariable(uint32 variableIndex)
{ if (variableIndex > maxVariable) maxVariable = variableIndex; }
Register topRegister;
Register getRegister() { return topRegister++; }
void resetTopRegister() { topRegister = stitcher.empty() ? 0 : stitcher.back()->registerBase; }
void resetTopRegister() { markMaxRegister(); topRegister = stitcher.empty() ? 0 : stitcher.back()->registerBase; }
ICodeOp getBranchOp() { ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); }
public:
Label *getLabel();
private:
uint32 maxRegister;
uint32 maxVariable;
void setLabel(Label *label);
void setLabel(InstructionStream *stream, Label *label);
@ -236,11 +262,12 @@ namespace JavaScript {
void branchConditional(Label *label, Register condition);
public:
ICodeGenerator() : topRegister(0) { iCode = new InstructionStream(); }
ICodeGenerator() : topRegister(0), maxRegister(0), maxVariable(0) { iCode = new InstructionStream(); }
virtual ~ICodeGenerator() { if (iCode) delete iCode; }
void mergeStream(InstructionStream *sideStream);
InstructionStream *complete();
ICodeModule *complete();
std::ostream &print(std::ostream &s);
@ -265,6 +292,8 @@ namespace JavaScript {
Register getRegisterBase() { return topRegister; }
InstructionStream *get_iCode() { return iCode; }
Label *getLabel();
// Rather than have the ICG client maniplate labels and branches, it
// uses the following calls to describe the high level looping constructs

View File

@ -63,15 +63,17 @@ gc_allocator<JSObject> JSObject::alloc;
#define op2(i) (i->itsOperand2)
#define op3(i) (i->itsOperand3)
JSValue interpret(InstructionStream& iCode, const JSValues& args)
JSValue interpret(ICodeModule *iCode, const JSValues& args)
{
JSValue result;
JSValues frame(args);
JSValues registers(32);
JSValues registers(iCode->itsMaxRegister + 1);
static JSObject globals;
InstructionIterator pc = iCode.begin();
while (pc != iCode.end()) {
InstructionIterator begin_pc = iCode->its_iCode->begin();
InstructionIterator end_pc = iCode->its_iCode->end();
InstructionIterator pc = begin_pc;
while (pc != end_pc) {
Instruction* instruction = *pc;
switch (instruction->opcode()) {
case MOVE_TO:
@ -133,7 +135,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
case BRANCH:
{
ResolvedBranch* bra = static_cast<ResolvedBranch*>(instruction);
pc = iCode.begin() + op1(bra);
pc = begin_pc + op1(bra);
continue;
}
break;
@ -141,7 +143,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 < 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -150,7 +152,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 <= 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -159,7 +161,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 == 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -168,7 +170,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 != 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -177,7 +179,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 >= 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -186,7 +188,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 > 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}

View File

@ -55,7 +55,7 @@ namespace JavaScript {
typedef vector<JSValue, gc_allocator<JSValue> > JSValues;
JSValue interpret(InstructionStream& iCode, const JSValues& args);
JSValue interpret(ICodeModule *iCode, const JSValues& args);
}
#endif /* interpreter_h */

View File

@ -342,9 +342,24 @@ static void testICG(World &world)
icg.saveVariable(0, icg.loadImmediate(99));
icg.endForStatement();
InstructionStream *iCode = icg.complete();
ICodeModule *icm = icg.complete();
std::cout << icg;
delete icm;
}
static float64 testFunctionCall(float64 n)
{
uint32 position = 0;
ICodeGenerator icg;
// function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; }
// n is bound to var #0.
icg.beginStatement(position);
icg.loadVariable(0);
}
static float64 testFactorial(float64 n)
@ -384,15 +399,17 @@ static float64 testFactorial(float64 n)
// return result;
icg.returnStatement(icg.loadVariable(1));
InstructionStream *iCode = icg.complete();
// std::cout << icg;
ICodeModule *icm = icg.complete();
std::cout << icg;
// test the iCode interpreter.
JSValues args(32);
args[0] = JSValue(n);
JSValue result = interpret(*iCode, args);
JSValue result = interpret(icm, args);
std::cout << "fact(" << n << ") = " << result.f64 << std::endl;
delete icm;
return result.f64;
}
@ -412,7 +429,7 @@ static float64 testObjects(World &world, int32 n)
initCG.beginStatement(position);
initCG.setProperty(counter, initCG.loadName(global), initCG.loadImmediate(0.0));
InstructionStream* initCode = initCG.complete();
ICodeModule* initCode = initCG.complete();
std::cout << initCG;
@ -428,21 +445,24 @@ static float64 testObjects(World &world, int32 n)
incrCG.setProperty(counter, robject, rvalue);
incrCG.returnStatement(rvalue);
InstructionStream* incrCode = incrCG.complete();
ICodeModule* incrCode = incrCG.complete();
std::cout << incrCG;
// run initialization code.
JSValues args(32);
interpret(*initCode, args);
interpret(initCode, args);
// call the increment function some number of times.
JSValue result;
while (n-- > 0)
result = interpret(*incrCode, args);
result = interpret(incrCode, args);
std::cout << "result = " << result.f64 << std::endl;
delete initCode;
delete incrCode;
return result.f64;
}
@ -452,7 +472,7 @@ int main(int argc, char **argv)
initConsole("\pJavaScript Shell", "Welcome to the js2 shell.\n", argc, argv);
#endif
World world;
#if 0
#if 1
assert(testFactorial(5) == 120);
assert(testObjects(world, 5) == 5);
testICG(world);

View File

@ -37,7 +37,7 @@ namespace JavaScript {
// ICodeGenerator
//
InstructionStream *ICodeGenerator::complete()
ICodeModule *ICodeGenerator::complete()
{
#ifdef DEBUG
ASSERT(stitcher.empty());
@ -62,20 +62,29 @@ namespace JavaScript {
delete t;
}
}
markMaxRegister();
return iCode;
return new ICodeModule(iCode, maxRegister, maxVariable);
}
/***********************************************************************************************/
Register ICodeGenerator::loadVariable(uint32 frameIndex)
{
markMaxVariable(frameIndex);
Register dest = getRegister();
LoadVar *instr = new LoadVar(LOAD_VAR, dest, frameIndex);
iCode->push_back(instr);
return dest;
}
void ICodeGenerator::saveVariable(uint32 frameIndex, Register value)
{
markMaxVariable(frameIndex);
SaveVar *instr = new SaveVar(SAVE_VAR, frameIndex, value);
iCode->push_back(instr);
}
Register ICodeGenerator::loadImmediate(double value)
{
Register dest = getRegister();
@ -120,12 +129,6 @@ namespace JavaScript {
iCode->push_back(instr);
}
void ICodeGenerator::saveVariable(uint32 frameIndex, Register value)
{
SaveVar *instr = new SaveVar(SAVE_VAR, frameIndex, value);
iCode->push_back(instr);
}
Register ICodeGenerator::op(ICodeOp op, Register source)
{
Register dest = getRegister();
@ -585,7 +588,7 @@ namespace JavaScript {
for (InstructionIterator i = iCode->begin(); i != iCode->end(); i++) {
for (LabelList::iterator k = labels.begin(); k != labels.end(); k++)
if ((*k)->itsOffset == (i - iCode->begin())) {
if ((*k)->itsOffset == (ptrdiff_t)(i - iCode->begin())) {
//s << "label #" << (k - labels.begin()) << ":\n";
s << "#" << (i - iCode->begin());
break;
@ -691,7 +694,7 @@ namespace JavaScript {
s << "\n";
}
for (LabelList::iterator k = labels.begin(); k != labels.end(); k++)
if ((*k)->itsOffset == (iCode->end() - iCode->begin())) {
if ((*k)->itsOffset == (ptrdiff_t)(iCode->end() - iCode->begin())) {
// s << "label #" << (k - labels.begin()) << ":\n";
// s << "#" << (i - iCode->begin());
}

View File

@ -31,50 +31,54 @@ namespace JavaScript {
typedef uint32 Register;
typedef std::vector<Register> RegisterList;
enum ICodeOp {
// Operand1 Operand2 Operand3
// Operand1 Operand2 Operand3
NOP,
MOVE_TO, // Destination Register Source Register
MOVE_TO, // Destination Register Source Register
LOAD_VAR, // Destination Register index of frame slot
SAVE_VAR, // index of frame slot Source Register
LOAD_VAR, // Destination Register index of frame slot
SAVE_VAR, // index of frame slot Source Register
LOAD_IMMEDIATE, // Destination Register immediate (double)
LOAD_IMMEDIATE, // Destination Register immediate (double)
LOAD_NAME, // Destination Register StringAtom &
SAVE_NAME, // StringAtom & Source Register
LOAD_NAME, // Destination Register StringAtom &
SAVE_NAME, // StringAtom & Source Register
NEW_OBJECT, // Destination Register
GET_PROP, // Destination Register StringAtom & Base Register
SET_PROP, // StringAtom & Base Register Source Register
GET_PROP, // Destination Register StringAtom & Base Register
SET_PROP, // StringAtom & Base Register Source Register
ADD, // Destination Register Source Register 1 Source Register 2
ADD, // Destination Register Source Register 1 Source Register 2
SUBTRACT,
MULTIPLY,
DIVIDE,
// maintain contiguity
COMPARE_LT, // Destination Register Source Register 1 Source Register 2
COMPARE_LT, // Destination Register Source Register 1 Source Register 2
COMPARE_LE,
COMPARE_EQ,
COMPARE_NE,
COMPARE_GE,
COMPARE_GT,
NOT, // Destination Register Source Register
NOT, // Destination Register Source Register
BRANCH, // Target label
BRANCH_LT, // Target label Condition Register
BRANCH_LT, // Target label Condition Register
BRANCH_LE,
BRANCH_EQ,
BRANCH_NE,
BRANCH_GE,
BRANCH_GT,
RETURN // Source Register
RETURN, // Source Register
CALL, // Destination Register Target Register Arguments
};
class Instruction {
@ -185,6 +189,12 @@ namespace JavaScript {
: Instruction_2<uint32, Register>(op, offset, condition) { }
};
class Call : public Instruction_3<Register, Register, RegisterList> {
public:
Call(Register result, Register target, RegisterList args)
: Instruction_3<Register, Register, RegisterList>(CALL, result, target, args) { }
};
/****************************************************************/
@ -206,6 +216,16 @@ namespace JavaScript {
Label *continueLabel;
};
class ICodeModule {
public:
ICodeModule(InstructionStream *iCode, uint32 maxRegister, uint32 maxVariable)
: its_iCode(iCode), itsMaxRegister(maxRegister), itsMaxVariable(maxVariable) { }
InstructionStream *its_iCode;
uint32 itsMaxRegister;
uint32 itsMaxVariable;
};
/****************************************************************/
// An ICodeGenerator provides the interface between the parser and the interpreter.
@ -220,15 +240,21 @@ namespace JavaScript {
std::vector<ICodeState *> stitcher;
void markMaxRegister() { if (topRegister > maxRegister) maxRegister = topRegister; }
void markMaxVariable(uint32 variableIndex)
{ if (variableIndex > maxVariable) maxVariable = variableIndex; }
Register topRegister;
Register getRegister() { return topRegister++; }
void resetTopRegister() { topRegister = stitcher.empty() ? 0 : stitcher.back()->registerBase; }
void resetTopRegister() { markMaxRegister(); topRegister = stitcher.empty() ? 0 : stitcher.back()->registerBase; }
ICodeOp getBranchOp() { ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); }
public:
Label *getLabel();
private:
uint32 maxRegister;
uint32 maxVariable;
void setLabel(Label *label);
void setLabel(InstructionStream *stream, Label *label);
@ -236,11 +262,12 @@ namespace JavaScript {
void branchConditional(Label *label, Register condition);
public:
ICodeGenerator() : topRegister(0) { iCode = new InstructionStream(); }
ICodeGenerator() : topRegister(0), maxRegister(0), maxVariable(0) { iCode = new InstructionStream(); }
virtual ~ICodeGenerator() { if (iCode) delete iCode; }
void mergeStream(InstructionStream *sideStream);
InstructionStream *complete();
ICodeModule *complete();
std::ostream &print(std::ostream &s);
@ -265,6 +292,8 @@ namespace JavaScript {
Register getRegisterBase() { return topRegister; }
InstructionStream *get_iCode() { return iCode; }
Label *getLabel();
// Rather than have the ICG client maniplate labels and branches, it
// uses the following calls to describe the high level looping constructs

View File

@ -63,15 +63,17 @@ gc_allocator<JSObject> JSObject::alloc;
#define op2(i) (i->itsOperand2)
#define op3(i) (i->itsOperand3)
JSValue interpret(InstructionStream& iCode, const JSValues& args)
JSValue interpret(ICodeModule *iCode, const JSValues& args)
{
JSValue result;
JSValues frame(args);
JSValues registers(32);
JSValues registers(iCode->itsMaxRegister + 1);
static JSObject globals;
InstructionIterator pc = iCode.begin();
while (pc != iCode.end()) {
InstructionIterator begin_pc = iCode->its_iCode->begin();
InstructionIterator end_pc = iCode->its_iCode->end();
InstructionIterator pc = begin_pc;
while (pc != end_pc) {
Instruction* instruction = *pc;
switch (instruction->opcode()) {
case MOVE_TO:
@ -133,7 +135,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
case BRANCH:
{
ResolvedBranch* bra = static_cast<ResolvedBranch*>(instruction);
pc = iCode.begin() + op1(bra);
pc = begin_pc + op1(bra);
continue;
}
break;
@ -141,7 +143,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 < 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -150,7 +152,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 <= 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -159,7 +161,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 == 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -168,7 +170,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 != 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -177,7 +179,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 >= 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}
@ -186,7 +188,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
{
ResolvedBranchCond* bc = static_cast<ResolvedBranchCond*>(instruction);
if (registers[op2(bc)].i32 > 0) {
pc = iCode.begin() + op1(bc);
pc = begin_pc + op1(bc);
continue;
}
}

View File

@ -55,7 +55,7 @@ namespace JavaScript {
typedef vector<JSValue, gc_allocator<JSValue> > JSValues;
JSValue interpret(InstructionStream& iCode, const JSValues& args);
JSValue interpret(ICodeModule *iCode, const JSValues& args);
}
#endif /* interpreter_h */

View File

@ -342,9 +342,24 @@ static void testICG(World &world)
icg.saveVariable(0, icg.loadImmediate(99));
icg.endForStatement();
InstructionStream *iCode = icg.complete();
ICodeModule *icm = icg.complete();
std::cout << icg;
delete icm;
}
static float64 testFunctionCall(float64 n)
{
uint32 position = 0;
ICodeGenerator icg;
// function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; }
// n is bound to var #0.
icg.beginStatement(position);
icg.loadVariable(0);
}
static float64 testFactorial(float64 n)
@ -384,15 +399,17 @@ static float64 testFactorial(float64 n)
// return result;
icg.returnStatement(icg.loadVariable(1));
InstructionStream *iCode = icg.complete();
// std::cout << icg;
ICodeModule *icm = icg.complete();
std::cout << icg;
// test the iCode interpreter.
JSValues args(32);
args[0] = JSValue(n);
JSValue result = interpret(*iCode, args);
JSValue result = interpret(icm, args);
std::cout << "fact(" << n << ") = " << result.f64 << std::endl;
delete icm;
return result.f64;
}
@ -412,7 +429,7 @@ static float64 testObjects(World &world, int32 n)
initCG.beginStatement(position);
initCG.setProperty(counter, initCG.loadName(global), initCG.loadImmediate(0.0));
InstructionStream* initCode = initCG.complete();
ICodeModule* initCode = initCG.complete();
std::cout << initCG;
@ -428,21 +445,24 @@ static float64 testObjects(World &world, int32 n)
incrCG.setProperty(counter, robject, rvalue);
incrCG.returnStatement(rvalue);
InstructionStream* incrCode = incrCG.complete();
ICodeModule* incrCode = incrCG.complete();
std::cout << incrCG;
// run initialization code.
JSValues args(32);
interpret(*initCode, args);
interpret(initCode, args);
// call the increment function some number of times.
JSValue result;
while (n-- > 0)
result = interpret(*incrCode, args);
result = interpret(incrCode, args);
std::cout << "result = " << result.f64 << std::endl;
delete initCode;
delete incrCode;
return result.f64;
}
@ -452,7 +472,7 @@ int main(int argc, char **argv)
initConsole("\pJavaScript Shell", "Welcome to the js2 shell.\n", argc, argv);
#endif
World world;
#if 0
#if 1
assert(testFactorial(5) == 120);
assert(testObjects(world, 5) == 5);
testICG(world);