ref: a4cc139e1cb81fc53b88b72fe8d15b9ac43d2ef4
dir: /jsrun.c/
#include "js.h"
#include "jsvalue.h"
#include "jsobject.h"
#include "jscompile.h"
#include "jsrun.h"
#include "jsstate.h"
static js_Value stack[256];
static int top = 0;
static inline int i32(double d)
{
double two32 = 4294967296.0;
double two31 = 2147483648.0;
if (!isfinite(d) || d == 0)
return 0;
d = fmod(d, two32);
d = d >= 0 ? floor(d) : ceil(d) + two32;
if (d >= two31)
return d - two32;
else
return d;
}
static inline unsigned int u32(double d)
{
return i32(d);
}
static inline void push(js_State *J, js_Value v)
{
stack[top++] = v;
}
static inline js_Value pop(js_State *J)
{
return stack[--top];
}
static inline js_Value peek(js_State *J)
{
return stack[top-1];
}
static inline void pushnumber(js_State *J, double number)
{
js_Value v;
v.type = JS_TNUMBER;
v.u.number = number;
push(J, v);
}
static inline double popnumber(js_State *J)
{
js_Value v = pop(J);
if (v.type == JS_TNUMBER)
return v.u.number;
if (v.type == JS_TSTRING)
return strtod(v.u.string, 0);
return 0;
}
static inline void pushundefined(js_State *J)
{
js_Value v;
v.type = JS_TUNDEFINED;
push(J, v);
}
static inline void pushnull(js_State *J)
{
js_Value v;
v.type = JS_TNULL;
push(J, v);
}
static inline void pushboolean(js_State *J, int boolean)
{
js_Value v;
v.type = JS_TBOOLEAN;
v.u.boolean = boolean;
push(J, v);
}
static inline int popboolean(js_State *J)
{
js_Value v = pop(J);
if (v.type == JS_TBOOLEAN)
return v.u.boolean;
if (v.type == JS_TNUMBER)
return v.u.number != 0;
return 0;
}
static inline void pushreference(js_State *J, js_Property *reference)
{
js_Value v;
v.type = JS_TREFERENCE;
v.u.reference = reference;
push(J, v);
}
static inline js_Property *popreference(js_State *J)
{
js_Value v = pop(J);
if (v.type == JS_TREFERENCE)
return v.u.reference;
return 0;
}
static inline js_Property *peekreference(js_State *J)
{
js_Value v = peek(J);
if (v.type == JS_TREFERENCE)
return v.u.reference;
return 0;
}
#define UNARY(X) a = popnumber(J); pushnumber(J, X)
#define BINARY(X) b = popnumber(J); a = popnumber(J); pushnumber(J, X)
static void runfun(js_State *J, js_Function *F, js_Object *E)
{
short *pc = F->code;
int opcode, addr;
js_Property *p;
js_Value v;
double a, b;
const char *s;
while (1) {
opcode = *pc++;
switch (opcode) {
case OP_NUMBER:
pushnumber(J, F->numlist[*pc++]);
break;
case OP_LOADVAR:
s = F->strlist[*pc++];
p = js_getproperty(J, E, s);
if (p)
push(J, p->value);
else
pushundefined(J);
break;
case OP_AVAR:
s = F->strlist[*pc++];
p = js_setproperty(J, E, s);
pushreference(J, p);
break;
case OP_LOAD:
p = peekreference(J);
if (p)
push(J, p->value);
else
pushundefined(J);
break;
case OP_STORE:
v = pop(J);
p = popreference(J);
if (p)
p->value = v;
push(J, v);
break;
case OP_UNDEF: pushundefined(J); break;
case OP_NULL: pushnull(J); break;
case OP_TRUE: pushboolean(J, 1); break;
case OP_FALSE: pushboolean(J, 0); break;
case OP_POS: UNARY(a); break;
case OP_NEG: UNARY(-a); break;
case OP_BITNOT: UNARY(~i32(a)); break;
case OP_LOGNOT: UNARY(!a); break;
case OP_ADD: BINARY(a + b); break;
case OP_SUB: BINARY(a - b); break;
case OP_MUL: BINARY(a * b); break;
case OP_DIV: BINARY(a / b); break;
case OP_MOD: BINARY(fmod(a, b)); break;
case OP_SHL: BINARY(i32(a) << (u32(b) & 0x1F)); break;
case OP_SHR: BINARY(i32(a) >> (u32(b) & 0x1F)); break;
case OP_USHR: BINARY(u32(a) >> (u32(b) & 0x1F)); break;
case OP_BITAND: BINARY(i32(a) & i32(b)); break;
case OP_BITXOR: BINARY(i32(a) ^ i32(b)); break;
case OP_BITOR: BINARY(i32(a) | i32(b)); break;
case OP_LT: BINARY(a < b); break;
case OP_GT: BINARY(a > b); break;
case OP_LE: BINARY(a <= b); break;
case OP_GE: BINARY(a >= b); break;
case OP_EQ: BINARY(a == b); break;
case OP_NE: BINARY(a != b); break;
case OP_JFALSE:
addr = *pc++;
if (!popboolean(J))
pc = F->code + addr;
break;
case OP_JTRUE:
addr = *pc++;
if (popboolean(J))
pc = F->code + addr;
break;
case OP_JUMP:
pc = F->code + *pc;
break;
case OP_POP: pop(J); break;
case OP_RETURN: return;
default:
fprintf(stderr, "illegal instruction: %d (pc=%d)\n", opcode, (int)(pc - F->code - 1));
return;
}
}
}
void jsR_runfunction(js_State *J, js_Function *F)
{
js_Object *varenv = js_newobject(J);
runfun(J, F, varenv);
js_dumpobject(J, varenv);
}