mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Function invocation & parameter frame instantiation. Labelled statements.
This commit is contained in:
parent
70c0fd6bb0
commit
3098c11277
@ -105,7 +105,7 @@ public:
|
||||
void emitBranch(JS2Op op, LabelID tgt, size_t pos)
|
||||
{ emitOp(op, pos); addFixup(tgt); }
|
||||
|
||||
void adjustStack(JS2Op op) { adjustStack(op, JS2Engine::getStackEffect(op)); }
|
||||
void adjustStack(JS2Op op) { adjustStack(op, getStackEffect(op)); }
|
||||
void adjustStack(JS2Op op, int32 effect);
|
||||
|
||||
void addByte(uint8 v) { mBuffer.push_back(v); }
|
||||
|
@ -241,10 +241,10 @@ JS2Engine::JS2Engine(World &world)
|
||||
float64Table[i] = NULL;
|
||||
|
||||
sp = execStack = new js2val[MAX_EXEC_STACK];
|
||||
|
||||
activationStackTop = activationStack = new ActivationFrame[MAX_ACTIVATION_STACK];
|
||||
}
|
||||
|
||||
int JS2Engine::getStackEffect(JS2Op op)
|
||||
int getStackEffect(JS2Op op)
|
||||
{
|
||||
switch (op) {
|
||||
case eReturn:
|
||||
@ -345,6 +345,28 @@ JS2Object *JS2Engine::defaultConstructor(JS2Engine *engine)
|
||||
return new FixedInstance(c);
|
||||
}
|
||||
|
||||
void JS2Engine::jsr(BytecodeContainer *new_bCon)
|
||||
{
|
||||
ASSERT(activationStackTop < (activationStack + MAX_ACTIVATION_STACK));
|
||||
activationStackTop->bCon = bCon;
|
||||
activationStackTop->pc = pc;
|
||||
activationStackTop++;
|
||||
|
||||
bCon = new_bCon;
|
||||
pc = new_bCon->getCodeStart();
|
||||
|
||||
}
|
||||
|
||||
void JS2Engine::rts()
|
||||
{
|
||||
ASSERT(activationStackTop > activationStack);
|
||||
activationStackTop--;
|
||||
|
||||
bCon = activationStackTop->bCon;
|
||||
pc = activationStackTop->pc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -92,6 +92,8 @@ enum JS2Op {
|
||||
|
||||
};
|
||||
|
||||
int getStackEffect(JS2Op op);
|
||||
|
||||
|
||||
class JS2Object;
|
||||
class JS2Metadata;
|
||||
@ -103,23 +105,11 @@ public:
|
||||
JS2Engine(World &world);
|
||||
|
||||
js2val interpret(JS2Metadata *metadata, Phase execPhase, BytecodeContainer *targetbCon);
|
||||
|
||||
js2val interpreterLoop();
|
||||
|
||||
void *gc_alloc_8();
|
||||
float64 *newDoubleValue(float64 x);
|
||||
|
||||
// Use the pc map in the current bytecode container to get a source offset
|
||||
size_t errorPos();
|
||||
|
||||
js2val allocNumber(float64 x);
|
||||
js2val pushNumber(float64 x) { js2val retval = allocNumber(x); push(retval); return retval; }
|
||||
|
||||
#define MAX_EXEC_STACK (20)
|
||||
|
||||
void push(js2val x) { ASSERT(sp < (execStack + MAX_EXEC_STACK)); *sp++ = x; }
|
||||
js2val pop() { ASSERT(sp > execStack); return *--sp; }
|
||||
js2val top() { return *(sp - 1); }
|
||||
js2val top(int argCount) { return *(sp - (1 + argCount)); }
|
||||
|
||||
String *convertValueToString(js2val x);
|
||||
js2val convertValueToPrimitive(js2val x);
|
||||
@ -134,15 +124,27 @@ public:
|
||||
|
||||
js2val assignmentConversion(js2val val, JS2Class *type) { return val; } // XXX s'more code, please
|
||||
|
||||
|
||||
// Current engine execution state
|
||||
uint8 *pc;
|
||||
BytecodeContainer *bCon;
|
||||
JS2Metadata *meta;
|
||||
Phase phase;
|
||||
World &world;
|
||||
|
||||
|
||||
|
||||
// A cache of f.p. values (XXX experimentally trying to reduce # of double pointers XXX)
|
||||
float64 *nanValue;
|
||||
float64 *float64Table[256];
|
||||
js2val allocNumber(float64 x);
|
||||
js2val pushNumber(float64 x) { js2val retval = allocNumber(x); push(retval); return retval; }
|
||||
void *gc_alloc_8();
|
||||
float64 *newDoubleValue(float64 x);
|
||||
|
||||
|
||||
|
||||
// Cached StringAtoms for handy access
|
||||
StringAtom &true_StringAtom;
|
||||
StringAtom &false_StringAtom;
|
||||
StringAtom &null_StringAtom;
|
||||
@ -151,17 +153,39 @@ public:
|
||||
StringAtom &private_StringAtom;
|
||||
StringAtom &function_StringAtom;
|
||||
StringAtom &object_StringAtom;
|
||||
|
||||
// The activation stack, when it's empty and a return is executed, the
|
||||
// interpreter quits
|
||||
#define MAX_ACTIVATION_STACK (20)
|
||||
struct ActivationFrame {
|
||||
uint8 *pc;
|
||||
BytecodeContainer *bCon;
|
||||
};
|
||||
void jsr(BytecodeContainer *bCon);
|
||||
bool activationStackEmpty() { return (activationStackTop == activationStack); }
|
||||
void rts();
|
||||
ActivationFrame *activationStack;
|
||||
ActivationFrame *activationStackTop;
|
||||
|
||||
|
||||
// The execution stack for expression evaluation, should be empty
|
||||
// between statements.
|
||||
#define MAX_EXEC_STACK (20)
|
||||
|
||||
js2val *execStack;
|
||||
js2val *sp;
|
||||
|
||||
void push(js2val x) { ASSERT(sp < (execStack + MAX_EXEC_STACK)); *sp++ = x; }
|
||||
js2val pop() { ASSERT(sp > execStack); return *--sp; }
|
||||
js2val top() { return *(sp - 1); }
|
||||
js2val top(int argCount) { return *(sp - (1 + argCount)); }
|
||||
|
||||
|
||||
|
||||
|
||||
static JS2Object *defaultConstructor(JS2Engine *engine);
|
||||
|
||||
|
||||
static int getStackEffect(JS2Op op);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -71,15 +71,17 @@ namespace MetaData {
|
||||
* Validate the linked list of statement nodes beginning at 'p'
|
||||
*/
|
||||
void JS2Metadata::ValidateStmtList(StmtNode *p) {
|
||||
LabelSet stmtLbl;
|
||||
JumpTarget jt;
|
||||
while (p) {
|
||||
ValidateStmt(&cxt, &env, p);
|
||||
ValidateStmt(&cxt, &env, p, &stmtLbl, &jt);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
void JS2Metadata::ValidateStmtList(Context *cxt, Environment *env, StmtNode *p) {
|
||||
void JS2Metadata::ValidateStmtList(Context *cxt, Environment *env, StmtNode *p, LabelSet *stmtLbl, JumpTarget *jt) {
|
||||
while (p) {
|
||||
ValidateStmt(cxt, env, p);
|
||||
ValidateStmt(cxt, env, p, stmtLbl, jt);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
@ -89,40 +91,55 @@ namespace MetaData {
|
||||
/*
|
||||
* Validate an individual statement 'p', including it's children
|
||||
*/
|
||||
void JS2Metadata::ValidateStmt(Context *cxt, Environment *env, StmtNode *p) {
|
||||
void JS2Metadata::ValidateStmt(Context *cxt, Environment *env, StmtNode *p, LabelSet *stmtLbl, JumpTarget *jt) {
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::block:
|
||||
case StmtNode::group:
|
||||
{
|
||||
BlockStmtNode *b = checked_cast<BlockStmtNode *>(p);
|
||||
ValidateStmtList(cxt, env, b->statements);
|
||||
b->compileFrame = new BlockFrame();
|
||||
env->addFrame(b->compileFrame);
|
||||
ValidateStmtList(cxt, env, b->statements, stmtLbl, jt);
|
||||
env->removeTopFrame();
|
||||
}
|
||||
break;
|
||||
case StmtNode::label:
|
||||
{
|
||||
LabelStmtNode *l = checked_cast<LabelStmtNode *>(p);
|
||||
ValidateStmt(cxt, env, l->stmt);
|
||||
l->labelID = bCon->getLabel();
|
||||
std::pair<LabelSet::iterator, bool> result = stmtLbl->insert(LabelSet::value_type(&l->name, l->labelID));
|
||||
if (!result.second)
|
||||
reportError(Exception::syntaxError, "Duplicate statement label", p->pos);
|
||||
ValidateStmt(cxt, env, l->stmt, stmtLbl, jt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::If:
|
||||
{
|
||||
UnaryStmtNode *i = checked_cast<UnaryStmtNode *>(p);
|
||||
ValidateExpression(cxt, env, i->expr);
|
||||
ValidateStmt(cxt, env, i->stmt);
|
||||
ValidateStmt(cxt, env, i->stmt, stmtLbl, jt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::IfElse:
|
||||
{
|
||||
BinaryStmtNode *i = checked_cast<BinaryStmtNode *>(p);
|
||||
ValidateExpression(cxt, env, i->expr);
|
||||
ValidateStmt(cxt, env, i->stmt);
|
||||
ValidateStmt(cxt, env, i->stmt2);
|
||||
ValidateStmt(cxt, env, i->stmt, stmtLbl, jt);
|
||||
ValidateStmt(cxt, env, i->stmt2, stmtLbl, jt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::While:
|
||||
{
|
||||
}
|
||||
break;
|
||||
case StmtNode::Return:
|
||||
{
|
||||
ExprStmtNode *e = checked_cast<ExprStmtNode *>(p);
|
||||
if (e->expr) {
|
||||
ValidateExpression(cxt, env, e->expr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::Function:
|
||||
{
|
||||
Attribute *attr = NULL;
|
||||
@ -163,13 +180,16 @@ namespace MetaData {
|
||||
|| (memberMod == Attribute::Virtual)
|
||||
|| (memberMod == Attribute::Final))
|
||||
compileThis = JS2VAL_INACCESSIBLE;
|
||||
ParameterFrame *compileFrame = new ParameterFrame();
|
||||
compileFrame->thisObject = compileThis;
|
||||
compileFrame->prototype = prototype;
|
||||
ParameterFrame *compileFrame = new ParameterFrame(compileThis, prototype);
|
||||
Frame *topFrame = env->getTopFrame();
|
||||
env->addFrame(compileFrame);
|
||||
// ValidateStmt(cxt, env, f->function.parameters);
|
||||
ValidateStmt(cxt, env, f->function.body);
|
||||
VariableBinding *pb = f->function.parameters;
|
||||
while (pb) {
|
||||
// XXX define a static binding for each parameter
|
||||
pb = pb->next;
|
||||
}
|
||||
ValidateStmt(cxt, env, f->function.body, stmtLbl, jt);
|
||||
env->removeTopFrame();
|
||||
if (unchecked
|
||||
&& ((topFrame->kind == GlobalObjectKind)
|
||||
|| (topFrame->kind == ParameterKind))
|
||||
@ -182,16 +202,14 @@ namespace MetaData {
|
||||
case Attribute::Static:
|
||||
{
|
||||
FixedInstance *fInst = new FixedInstance(functionClass);
|
||||
fInst->fWrap = new FunctionWrapper();
|
||||
fInst->fWrap->compileThis = compileThis;
|
||||
fInst->fWrap->unchecked = unchecked;
|
||||
fInst->fWrap = new FunctionWrapper(unchecked, compileFrame);
|
||||
f->fWrap = fInst->fWrap;
|
||||
Variable *v = new Variable(functionClass, OBJECT_TO_JS2VAL(fInst), true);
|
||||
defineStaticMember(env, *f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
env->removeTopFrame();
|
||||
}
|
||||
break;
|
||||
case StmtNode::Var:
|
||||
@ -345,7 +363,7 @@ namespace MetaData {
|
||||
defineStaticMember(env, classStmt->name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos);
|
||||
if (classStmt->body) {
|
||||
env->addFrame(c);
|
||||
ValidateStmtList(cxt, env, classStmt->body->statements);
|
||||
ValidateStmtList(cxt, env, classStmt->body->statements, stmtLbl, jt);
|
||||
ASSERT(env->getTopFrame() == c);
|
||||
env->removeTopFrame();
|
||||
}
|
||||
@ -411,11 +429,16 @@ namespace MetaData {
|
||||
case StmtNode::group:
|
||||
{
|
||||
BlockStmtNode *b = checked_cast<BlockStmtNode *>(p);
|
||||
env->addFrame(b->compileFrame);
|
||||
bCon->emitOp(ePushFrame, p->pos);
|
||||
bCon->addFrame(b->compileFrame);
|
||||
StmtNode *bp = b->statements;
|
||||
while (bp) {
|
||||
EvalStmt(env, phase, bp);
|
||||
bp = bp->next;
|
||||
}
|
||||
bCon->emitOp(ePopFrame, p->pos);
|
||||
env->removeTopFrame();
|
||||
}
|
||||
break;
|
||||
case StmtNode::label:
|
||||
@ -456,13 +479,23 @@ namespace MetaData {
|
||||
{
|
||||
}
|
||||
break;
|
||||
case StmtNode::Return:
|
||||
{
|
||||
ExprStmtNode *e = checked_cast<ExprStmtNode *>(p);
|
||||
if (e->expr) {
|
||||
EvalExprNode(env, phase, e->expr);
|
||||
bCon->emitOp(eReturn, p->pos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::Function:
|
||||
{
|
||||
FunctionStmtNode *f = checked_cast<FunctionStmtNode *>(p);
|
||||
BytecodeContainer *saveBacon = bCon;
|
||||
f->fWrap->bCon = new BytecodeContainer();
|
||||
bCon = f->fWrap->bCon;
|
||||
env->addFrame(f->fWrap->compileFrame);
|
||||
EvalStmt(env, phase, f->function.body);
|
||||
env->removeTopFrame();
|
||||
bCon = saveBacon;
|
||||
}
|
||||
break;
|
||||
@ -1131,7 +1164,7 @@ doBinary:
|
||||
argCount++;
|
||||
args = args->next;
|
||||
}
|
||||
bCon->emitOp(eCall, p->pos);
|
||||
bCon->emitOp(eCall, p->pos, -argCount + 1); // pop argCount args and push a result
|
||||
bCon->addShort(argCount);
|
||||
}
|
||||
break;
|
||||
@ -1147,7 +1180,7 @@ doBinary:
|
||||
argCount++;
|
||||
args = args->next;
|
||||
}
|
||||
bCon->emitOp(eNew, p->pos, -argCount + 1); // pop argCount args and push a result
|
||||
bCon->emitOp(eNew, p->pos, -argCount + 1); // pop argCount args and push a new object
|
||||
bCon->addShort(argCount);
|
||||
}
|
||||
break;
|
||||
@ -1260,6 +1293,42 @@ doBinary:
|
||||
meta->reportError(Exception::referenceError, "{0} is undefined", meta->engine->errorPos(), multiname->name);
|
||||
}
|
||||
|
||||
// Clone the pluralFrame bindings into the singularFrame, instantiating new members for each binding
|
||||
void Environment::instantiateFrame(Frame *pluralFrame, Frame *singularFrame)
|
||||
{
|
||||
StaticBindingIterator sbi, sbend;
|
||||
for (sbi = pluralFrame->staticReadBindings.begin(), sbend = pluralFrame->staticReadBindings.end(); (sbi != sbend); sbi++) {
|
||||
sbi->second->content->cloneContent = NULL;
|
||||
}
|
||||
for (sbi = pluralFrame->staticWriteBindings.begin(), sbend = pluralFrame->staticWriteBindings.end(); (sbi != sbend); sbi++) {
|
||||
sbi->second->content->cloneContent = NULL;
|
||||
}
|
||||
for (sbi = pluralFrame->staticReadBindings.begin(), sbend = pluralFrame->staticReadBindings.end(); (sbi != sbend); sbi++) {
|
||||
StaticBinding *sb;
|
||||
StaticBinding *m = sbi->second;
|
||||
if (m->content->cloneContent == NULL) {
|
||||
m->content->cloneContent = m->content->clone();
|
||||
}
|
||||
sb = new StaticBinding(m->qname, m->content->cloneContent);
|
||||
sb->xplicit = m->xplicit;
|
||||
const StaticBindingMap::value_type e(sbi->first, sb);
|
||||
singularFrame->staticReadBindings.insert(e);
|
||||
}
|
||||
for (sbi = pluralFrame->staticWriteBindings.begin(), sbend = pluralFrame->staticWriteBindings.end(); (sbi != sbend); sbi++) {
|
||||
StaticBinding *sb;
|
||||
StaticBinding *m = sbi->second;
|
||||
if (m->content->cloneContent == NULL) {
|
||||
m->content->cloneContent = new Variable();
|
||||
}
|
||||
sb = new StaticBinding(m->qname, m->content->cloneContent);
|
||||
sb->xplicit = m->xplicit;
|
||||
const StaticBindingMap::value_type e(sbi->first, sb);
|
||||
singularFrame->staticWriteBindings.insert(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
@ -2059,6 +2128,7 @@ readClassProperty:
|
||||
access = WriteAccess;
|
||||
b = container->staticWriteBindings.lower_bound(multiname->name);
|
||||
end = container->staticWriteBindings.upper_bound(multiname->name);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
@ -2160,6 +2230,7 @@ readClassProperty:
|
||||
access = WriteAccess;
|
||||
b = c->instanceWriteBindings.lower_bound(multiname->name);
|
||||
end = c->instanceWriteBindings.upper_bound(multiname->name);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
@ -104,6 +104,7 @@ public:
|
||||
Pond *nextPond;
|
||||
};
|
||||
|
||||
|
||||
class JS2Object {
|
||||
// Every object is either undefined, null, a Boolean,
|
||||
// a number, a string, a namespace, a compound attribute, a class, a method closure,
|
||||
@ -235,6 +236,9 @@ class StaticMember : public Member {
|
||||
public:
|
||||
StaticMember(MemberKind kind) : Member(kind) { }
|
||||
|
||||
StaticMember *cloneContent; // Used during cloning operation
|
||||
|
||||
virtual StaticMember *clone() { ASSERT(false); return NULL; }
|
||||
};
|
||||
|
||||
#define FUTURE_TYPE ((JS2Class *)(-1))
|
||||
@ -244,6 +248,8 @@ public:
|
||||
Variable() : StaticMember(Member::Variable), type(NULL), vb(NULL), value(JS2VAL_VOID), immutable(false) { }
|
||||
Variable(JS2Class *type, js2val value, bool immutable) : StaticMember(StaticMember::Variable), type(type), vb(NULL), value(value), immutable(immutable) { }
|
||||
|
||||
virtual StaticMember *clone() { return new Variable(type, value, immutable); }
|
||||
|
||||
JS2Class *type; // Type of values that may be stored in this variable, NULL if INACCESSIBLE, FUTURE_TYPE if pending
|
||||
VariableBinding *vb; // The variable definition node, to resolve future types
|
||||
js2val value; // This variable's current value; future if the variable has not been declared yet;
|
||||
@ -254,6 +260,7 @@ public:
|
||||
class HoistedVar : public StaticMember {
|
||||
public:
|
||||
HoistedVar() : StaticMember(Member::HoistedVariable), value(JS2VAL_VOID), hasFunctionInitializer(false) { }
|
||||
|
||||
js2val value; // This variable's current value
|
||||
bool hasFunctionInitializer; // true if this variable was created by a function statement
|
||||
};
|
||||
@ -589,6 +596,7 @@ public:
|
||||
// Frames holding bindings for invoked functions
|
||||
class ParameterFrame : public Frame {
|
||||
public:
|
||||
ParameterFrame(js2val thisObject, bool prototype) : Frame(ParameterKind), thisObject(thisObject), prototype(prototype) { }
|
||||
ParameterFrame() : Frame(ParameterKind) { }
|
||||
|
||||
Plurality plurality;
|
||||
@ -637,6 +645,9 @@ public:
|
||||
js2val lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase);
|
||||
void lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing, Phase phase);
|
||||
|
||||
void instantiateFrame(Frame *pluralFrame, Frame *singularFrame);
|
||||
|
||||
|
||||
private:
|
||||
Frame *firstFrame;
|
||||
};
|
||||
@ -644,8 +655,10 @@ private:
|
||||
|
||||
class FunctionWrapper {
|
||||
public:
|
||||
FunctionWrapper(bool unchecked, ParameterFrame *compileFrame)
|
||||
: bCon(new BytecodeContainer), unchecked(unchecked), compileFrame(compileFrame) { }
|
||||
|
||||
BytecodeContainer *bCon;
|
||||
js2val compileThis; // The value of 'this' established at Validate time
|
||||
bool unchecked; // true if the function is untyped, non-method, normal
|
||||
ParameterFrame *compileFrame;
|
||||
};
|
||||
@ -697,6 +710,15 @@ public:
|
||||
bool unused; // true if the unused attribute has been given
|
||||
};
|
||||
|
||||
typedef std::map<const StringAtom *, BytecodeContainer::LabelID> LabelSet;
|
||||
class JumpTarget {
|
||||
public:
|
||||
JumpTarget() : breakTargets(new LabelSet()), continueTargets(new LabelSet()) { }
|
||||
|
||||
LabelSet *breakTargets;
|
||||
LabelSet *continueTargets;
|
||||
};
|
||||
|
||||
struct MemberDescriptor {
|
||||
StaticMember *staticMember;
|
||||
QualifiedName *qname;
|
||||
@ -713,9 +735,9 @@ public:
|
||||
js2val EvalStmtList(Phase phase, StmtNode *p);
|
||||
|
||||
|
||||
void ValidateStmtList(Context *cxt, Environment *env, StmtNode *p);
|
||||
void ValidateStmtList(Context *cxt, Environment *env, StmtNode *p, LabelSet *stmtLbl, JumpTarget *jt);
|
||||
void ValidateTypeExpression(Context *cxt, Environment *env, ExprNode *e) { ValidateExpression(cxt, env, e); }
|
||||
void ValidateStmt(Context *cxt, Environment *env, StmtNode *p);
|
||||
void ValidateStmt(Context *cxt, Environment *env, StmtNode *p, LabelSet *stmtLbl, JumpTarget *jt);
|
||||
void ValidateExpression(Context *cxt, Environment *env, ExprNode *p);
|
||||
void ValidateAttributeExpression(Context *cxt, Environment *env, ExprNode *p);
|
||||
|
||||
|
@ -31,19 +31,6 @@
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
case eReturn:
|
||||
{
|
||||
retval = pop();
|
||||
return retval;
|
||||
}
|
||||
break;
|
||||
|
||||
case eReturnVoid:
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
break;
|
||||
|
||||
case eBranchTrue:
|
||||
{
|
||||
retval = pop();
|
||||
|
@ -87,7 +87,7 @@
|
||||
if (fObj->kind == FixedInstanceKind) {
|
||||
FixedInstance *fInst = checked_cast<FixedInstance *>(fObj);
|
||||
FunctionWrapper *fWrap = fInst->fWrap;
|
||||
js2val compileThis = fWrap->compileThis;
|
||||
js2val compileThis = fWrap->compileFrame->thisObject;
|
||||
js2val runtimeThis;
|
||||
if (JS2VAL_IS_VOID(compileThis))
|
||||
runtimeThis = JS2VAL_VOID;
|
||||
@ -101,37 +101,33 @@
|
||||
}
|
||||
Frame *runtimeFrame = new ParameterFrame();
|
||||
meta->env.addFrame(runtimeFrame);
|
||||
// instantiateFrame(fWrap->compileFrame, runtimeFrame, meta->env);
|
||||
meta->env.instantiateFrame(fWrap->compileFrame, runtimeFrame);
|
||||
// assignArguments(runtimeFrame, fWrap->compileFrame->signature);
|
||||
|
||||
jsr(fWrap->bCon);
|
||||
|
||||
|
||||
/*
|
||||
proc call(this: OBJECT, args: ARGUMENTLIST, runtimeEnv: ENVIRONMENT, phase: PHASE): OBJECT
|
||||
if phase = compile then throw compileExpressionError end if;
|
||||
runtimeThis: OBJECTOPT;
|
||||
case compileThis of
|
||||
{none} do runtimeThis ¨ none;
|
||||
{inaccessible} do
|
||||
runtimeThis ¨ this;
|
||||
g: PACKAGE » GLOBAL ¨ getPackageOrGlobalFrame(runtimeEnv);
|
||||
if prototype and runtimeThis Œ {null, undefined} and g Œ GLOBAL then
|
||||
runtimeThis ¨ g
|
||||
end if
|
||||
end case;
|
||||
runtimeFrame: PARAMETERFRAME ¨ new PARAMETERFRAME··staticReadBindings: {},
|
||||
staticWriteBindings: {}, plurality: singular, this: runtimeThis, prototype: prototype,
|
||||
signature: compileFrame.signatureÒÒ;
|
||||
instantiateFrame(compileFrame, runtimeFrame, [runtimeFrame] ! runtimeEnv);
|
||||
assignArguments(runtimeFrame, compileFrame.signature, unchecked, args);
|
||||
try
|
||||
Eval[Block]([runtimeFrame] ! runtimeEnv, undefined);
|
||||
throw RETURNEDVALUE·value: undefinedÒ
|
||||
catch x: SEMANTICEXCEPTION do
|
||||
if x Œ RETURNEDVALUE then return x.value else throw x end if
|
||||
end try
|
||||
|
||||
*/
|
||||
}
|
||||
else
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case eReturn:
|
||||
{
|
||||
retval = pop();
|
||||
if (activationStackEmpty())
|
||||
return retval;
|
||||
else
|
||||
rts();
|
||||
}
|
||||
break;
|
||||
|
||||
case eReturnVoid:
|
||||
{
|
||||
if (activationStackEmpty())
|
||||
return retval;
|
||||
else
|
||||
rts();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
case eNumber:
|
||||
{
|
||||
push(DOUBLE_TO_JS2VAL(newDoubleValue(BytecodeContainer::getFloat64(pc))));
|
||||
pushNumber(BytecodeContainer::getFloat64(pc));
|
||||
pc += sizeof(float64);
|
||||
}
|
||||
break;
|
||||
|
@ -65,6 +65,8 @@ namespace JavaScript {
|
||||
class OverrideStatus;
|
||||
typedef std::pair<OverrideStatus *, OverrideStatus *> OverrideStatusPair;
|
||||
class FunctionWrapper;
|
||||
class BlockFrame;
|
||||
typedef uint32 LabelID;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -550,6 +552,10 @@ namespace JavaScript {
|
||||
AttributeStmtNode(pos, kind, attributes), statements(statements) {}
|
||||
|
||||
void print(PrettyPrinter &f, bool noSemi) const;
|
||||
|
||||
#ifdef EPIMETHEUS
|
||||
MetaData::BlockFrame *compileFrame; // used by backend
|
||||
#endif
|
||||
};
|
||||
|
||||
struct LabelStmtNode: StmtNode {
|
||||
@ -560,6 +566,9 @@ namespace JavaScript {
|
||||
StmtNode(pos, label), name(name), stmt(stmt) {ASSERT(stmt);}
|
||||
|
||||
void print(PrettyPrinter &f, bool noSemi) const;
|
||||
#ifdef EPIMETHEUS
|
||||
MetaData::LabelID labelID;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct UnaryStmtNode: ExprStmtNode {
|
||||
|
Loading…
Reference in New Issue
Block a user