зеркало из https://github.com/mozilla/gecko-dev.git
Exec milestone.
This commit is contained in:
Родитель
37ba77fecf
Коммит
6cfbc1ea9d
|
@ -42,10 +42,6 @@
|
|||
#ifndef bytecodecontainer_h___
|
||||
#define bytecodecontainer_h___
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include "js2value.h"
|
||||
|
||||
|
||||
namespace JavaScript {
|
||||
|
@ -60,7 +56,7 @@ public:
|
|||
BytecodeContainer::~BytecodeContainer() ;
|
||||
|
||||
|
||||
JS2Op *getCodeStart() { return (JS2Op *)(mBuffer->begin()); }
|
||||
uint8 *getCodeStart() { return mBuffer->begin(); }
|
||||
|
||||
|
||||
void emitOp(JS2Op op) { adjustStack(op); addByte((uint8)op); }
|
||||
|
@ -71,10 +67,13 @@ public:
|
|||
void addPointer(void *v) { ASSERT(sizeof(void *) == sizeof(uint32)); addLong((uint32)(v)); }
|
||||
|
||||
void addFloat64(float64 v) { mBuffer->insert(mBuffer->end(), (uint8 *)&v, (uint8 *)(&v) + sizeof(float64)); }
|
||||
static float64 getFloat64(void *pc) { return *((float64 *)pc); }
|
||||
|
||||
void addLong(uint32 v) { mBuffer->insert(mBuffer->end(), (uint8 *)&v, (uint8 *)(&v) + sizeof(uint32)); }
|
||||
static uint32 getLong(void *pc) { return *((uint32 *)pc); }
|
||||
|
||||
void addMultiname(Multiname *mn) { mMultinameList.push_back(mn); addPointer(mn); }
|
||||
|
||||
static Multiname *getMultiname(void *pc){ return (Multiname *)getLong(pc); }
|
||||
|
||||
typedef std::vector<uint8> CodeBuffer;
|
||||
|
||||
|
|
|
@ -31,11 +31,18 @@
|
|||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
#include "js2metadata.h"
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
#include "js2value.h"
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include "reader.h"
|
||||
#include "parser.h"
|
||||
#include "js2engine.h"
|
||||
#include "bytecodecontainer.h"
|
||||
#include "js2metadata.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "tracer.h"
|
||||
|
@ -140,7 +147,7 @@ static int readEvalPrint(FILE *in)
|
|||
metadata->setCurrentParser(&p); // for error reporting
|
||||
|
||||
metadata->ValidateStmtList(parsedStatements);
|
||||
js2val rval = metadata->EvalStmtList(MetaData::RunPhase, parsedStatements);
|
||||
js2val rval = metadata->EvalStmtList(RunPhase, parsedStatements);
|
||||
if (!JS2VAL_IS_VOID(rval))
|
||||
stdOut << *metadata->engine->toString(rval) << '\n';
|
||||
}
|
||||
|
|
|
@ -41,26 +41,44 @@
|
|||
#pragma warning(disable: 4710)
|
||||
#endif
|
||||
|
||||
#include "numerics.h"
|
||||
#include "js2metadata.h"
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
#include "js2value.h"
|
||||
#include "numerics.h"
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include "reader.h"
|
||||
#include "parser.h"
|
||||
#include "js2engine.h"
|
||||
#include "bytecodecontainer.h"
|
||||
#include "js2metadata.h"
|
||||
|
||||
namespace JavaScript {
|
||||
namespace MetaData {
|
||||
|
||||
js2val JS2Engine::interpret(JS2Op *start)
|
||||
js2val JS2Engine::interpret(JS2Metadata *metadata, Phase execPhase, uint8 *start)
|
||||
{
|
||||
pc = start;
|
||||
meta = metadata;
|
||||
phase = execPhase;
|
||||
return interpreterLoop();
|
||||
}
|
||||
|
||||
js2val JS2Engine::interpreterLoop()
|
||||
{
|
||||
js2val retval;
|
||||
js2val retval = JS2VAL_VOID;
|
||||
while (true) {
|
||||
switch (*pc) {
|
||||
JS2Op op = (JS2Op)*pc++;
|
||||
switch (op) {
|
||||
#include "js2op_arithmetic.cpp"
|
||||
#include "js2op_invocation.cpp"
|
||||
#include "js2op_access.cpp"
|
||||
#include "js2op_literal.cpp"
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
|
@ -69,7 +87,7 @@ js2val JS2Engine::interpreterLoop()
|
|||
// return a pointer to an 8 byte chunk in the gc heap
|
||||
void *JS2Engine::gc_alloc_8()
|
||||
{
|
||||
return NULL;
|
||||
return STD::malloc(8);
|
||||
}
|
||||
|
||||
// See if the double value is in the hash table, return it's pointer if so
|
||||
|
@ -202,6 +220,7 @@ int JS2Engine::getStackEffect(JS2Op op)
|
|||
return -1;
|
||||
case eTrue:
|
||||
case eFalse:
|
||||
case eNumber:
|
||||
return 1;
|
||||
|
||||
case eLexicalRead:
|
||||
|
@ -209,6 +228,9 @@ int JS2Engine::getStackEffect(JS2Op op)
|
|||
case eLexicalWrite:
|
||||
return -1;
|
||||
|
||||
case eReturnVoid:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
|
|
|
@ -52,19 +52,23 @@ enum JS2Op {
|
|||
ePlus,
|
||||
eTrue,
|
||||
eFalse,
|
||||
eNumber,
|
||||
eLexicalRead, // <multiname index>
|
||||
eLexicalWrite, // <multiname index>
|
||||
eReturn
|
||||
eReturn,
|
||||
eReturnVoid
|
||||
};
|
||||
|
||||
|
||||
class JS2Metadata;
|
||||
|
||||
|
||||
class JS2Engine {
|
||||
public:
|
||||
|
||||
JS2Engine(World &world);
|
||||
|
||||
js2val interpret(JS2Op *start);
|
||||
js2val interpret(JS2Metadata *metadata, Phase execPhase, uint8 *start);
|
||||
|
||||
js2val interpreterLoop();
|
||||
|
||||
|
@ -86,7 +90,9 @@ public:
|
|||
js2val toPrimitive(js2val x) { if (JS2VAL_IS_PRIMITIVE(x)) return x; else return convertValueToPrimitive(x); }
|
||||
float64 toNumber(js2val x) { if (JS2VAL_IS_INT(x)) return JS2VAL_TO_INT(x); else if (JS2VAL_IS_DOUBLE(x)) return *JS2VAL_TO_DOUBLE(x); else return convertValueToDouble(x); }
|
||||
|
||||
JS2Op *pc;
|
||||
uint8 *pc;
|
||||
JS2Metadata *meta;
|
||||
Phase phase;
|
||||
|
||||
float64 *nanValue;
|
||||
float64 *float64Table[256];
|
||||
|
|
|
@ -40,9 +40,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
#include "js2metadata.h"
|
||||
|
||||
|
||||
namespace JavaScript {
|
||||
namespace MetaData {
|
||||
|
||||
|
|
|
@ -41,8 +41,19 @@
|
|||
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
#include "js2value.h"
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include "reader.h"
|
||||
#include "parser.h"
|
||||
#include "js2engine.h"
|
||||
#include "bytecodecontainer.h"
|
||||
#include "js2metadata.h"
|
||||
|
||||
|
||||
|
@ -150,15 +161,14 @@ namespace MetaData {
|
|||
* Evaluate the linked list of statement nodes beginning at 'p' (generate bytecode)
|
||||
* and then execute that bytecode
|
||||
*/
|
||||
js2val JS2Metadata::EvalStmtList(Phase phase, StmtNode *p) {
|
||||
js2val retval = JS2VAL_VOID;
|
||||
js2val JS2Metadata::EvalStmtList(Phase phase, StmtNode *p)
|
||||
{
|
||||
while (p) {
|
||||
retval = EvalStmt(&env, phase, p);
|
||||
EvalStmt(&env, phase, p);
|
||||
p = p->next;
|
||||
}
|
||||
bCon->emitOp(eReturn);
|
||||
engine->interpret(bCon->getCodeStart());
|
||||
return retval;
|
||||
bCon->emitOp(eReturnVoid);
|
||||
return engine->interpret(this, phase, bCon->getCodeStart());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -166,21 +176,24 @@ namespace MetaData {
|
|||
* - this generates bytecode for each statement, but doesn't actually
|
||||
* execute it.
|
||||
*/
|
||||
js2val JS2Metadata::EvalStmt(Environment *env, Phase phase, StmtNode *p)
|
||||
void JS2Metadata::EvalStmt(Environment *env, Phase phase, StmtNode *p)
|
||||
{
|
||||
js2val retval = JS2VAL_VOID;
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::block:
|
||||
case StmtNode::group:
|
||||
{
|
||||
BlockStmtNode *b = checked_cast<BlockStmtNode *>(p);
|
||||
retval = EvalStmtList(phase, b->statements);
|
||||
StmtNode *bp = b->statements;
|
||||
while (bp) {
|
||||
EvalStmt(env, phase, bp);
|
||||
bp = bp->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::label:
|
||||
{
|
||||
LabelStmtNode *l = checked_cast<LabelStmtNode *>(p);
|
||||
retval = EvalStmt(env, phase, l->stmt);
|
||||
EvalStmt(env, phase, l->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Var:
|
||||
|
@ -198,17 +211,13 @@ namespace MetaData {
|
|||
case StmtNode::expression:
|
||||
{
|
||||
ExprStmtNode *e = checked_cast<ExprStmtNode *>(p);
|
||||
retval = EvalExpression(env, phase, e->expr);
|
||||
if (JS2VAL_IS_OBJECT(retval)) {
|
||||
JS2Object *obj = JS2VAL_TO_OBJECT(retval);
|
||||
}
|
||||
|
||||
Reference *r = EvalExprNode(env, phase, e->expr);
|
||||
if (r) r->emitReadBytecode(bCon);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NOT_REACHED("Not Yet Implemented");
|
||||
} // switch (p->getKind())
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
@ -468,23 +477,18 @@ namespace MetaData {
|
|||
|
||||
|
||||
/*
|
||||
* Evaluate the expression rooted at p.
|
||||
* Works by generating a JS string that represents the expression and then using
|
||||
* the JS interpreter to execute that string against the current environment. The
|
||||
* result is the value of this expression.
|
||||
*
|
||||
* Evaluate an expression 'p' and execute the assocaited bytecode
|
||||
*/
|
||||
js2val JS2Metadata::EvalExpression(Environment *env, Phase phase, ExprNode *p)
|
||||
{
|
||||
Reference *rVal = EvalExprNode(env, phase, p);
|
||||
try {
|
||||
}
|
||||
catch (const char *err) {
|
||||
reportError(Exception::internalError, err, p->pos);
|
||||
return JS2VAL_VOID;
|
||||
}
|
||||
EvalExprNode(env, phase, p);
|
||||
bCon->emitOp(eReturnVoid);
|
||||
return engine->interpret(this, phase, bCon->getCodeStart());
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate the expression rooted at p.
|
||||
*/
|
||||
Reference *JS2Metadata::EvalExprNode(Environment *env, Phase phase, ExprNode *p)
|
||||
{
|
||||
Reference *returnRef = NULL;
|
||||
|
@ -499,11 +503,11 @@ namespace MetaData {
|
|||
{
|
||||
if (phase == CompilePhase) reportError(Exception::compileExpressionError, "Inappropriate compile time expression", p->pos);
|
||||
BinaryExprNode *b = checked_cast<BinaryExprNode *>(p);
|
||||
Reference *lVal = EvalExprNode(env, phase, b->op1);
|
||||
if (lVal) {
|
||||
returnRef = EvalExprNode(env, phase, b->op1);
|
||||
if (returnRef) {
|
||||
Reference *rVal = EvalExprNode(env, phase, b->op2);
|
||||
if (rVal) rVal->emitReadBytecode(bCon);
|
||||
lVal->emitWriteBytecode(bCon);
|
||||
returnRef->emitWriteBytecode(bCon);
|
||||
}
|
||||
else
|
||||
reportError(Exception::semanticError, "Assignment needs an lValue", p->pos);
|
||||
|
@ -531,6 +535,8 @@ namespace MetaData {
|
|||
|
||||
case ExprNode::number:
|
||||
{
|
||||
bCon->emitOp(eNumber);
|
||||
bCon->addFloat64(checked_cast<NumberExprNode *>(p)->value);
|
||||
}
|
||||
break;
|
||||
case ExprNode::identifier:
|
||||
|
|
|
@ -36,18 +36,6 @@
|
|||
#define js2metadata_h___
|
||||
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
#include "js2value.h"
|
||||
#include "js2engine.h"
|
||||
#include "bytecodecontainer.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace JavaScript {
|
||||
namespace MetaData {
|
||||
|
||||
|
@ -60,14 +48,13 @@ class StaticBinding;
|
|||
class Environment;
|
||||
class Context;
|
||||
class CompoundAttribute;
|
||||
class BytecodeContainer;
|
||||
|
||||
typedef void (Invokable)();
|
||||
typedef Invokable Callor;
|
||||
typedef JS2Object *(Constructor)();
|
||||
|
||||
|
||||
enum Phase { CompilePhase, RunPhase };
|
||||
enum Access { ReadAccess, WriteAccess, ReadWriteAccess };
|
||||
|
||||
class JS2Object {
|
||||
// Every object is either undefined, null, a Boolean,
|
||||
|
@ -554,7 +541,7 @@ public:
|
|||
js2val EvalExpression(Environment *env, Phase phase, ExprNode *p);
|
||||
Reference *EvalExprNode(Environment *env, Phase phase, ExprNode *p);
|
||||
Attribute *EvalAttributeExpression(Environment *env, Phase phase, ExprNode *p);
|
||||
js2val EvalStmt(Environment *env, Phase phase, StmtNode *p);
|
||||
void EvalStmt(Environment *env, Phase phase, StmtNode *p);
|
||||
|
||||
|
||||
JS2Class *objectType(js2val obj);
|
||||
|
|
|
@ -136,6 +136,8 @@
|
|||
#define JS2VAL_UNDEFINED JS2VAL_VOID
|
||||
|
||||
typedef uint32 js2val;
|
||||
enum Phase { CompilePhase, RunPhase };
|
||||
enum Access { ReadAccess, WriteAccess, ReadWriteAccess };
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,7 +42,7 @@ RSC=rc.exe
|
|||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "../../../src" /D "NDEBUG" /D "XP_" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "XP_PC" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "../../../src" /D "NDEBUG" /D "XP_" /D "_CONSOLE" /D "XP_PC" /D "WIN32" /D "_MBCS" /D "DIKDIK" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
|
@ -66,7 +66,7 @@ LINK32=link.exe
|
|||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I "../../../src" /I "../../../src/regexp" /D "_DEBUG" /D "XP_PC" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "DEBUG" /FR /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I "../../../src" /I "../../../src/regexp" /D "_DEBUG" /D "_CONSOLE" /D "DEBUG" /D "XP_PC" /D "WIN32" /D "_MBCS" /D "DIKDIK" /FR /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
|
|
Загрузка…
Ссылка в новой задаче