FreeWRL
view release on metacpan or search on metacpan
JS/js/jsinterp.c view on Meta::CPAN
/* Try to hit the property cache, FindVariable primes it. */
CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval));
if (!ok)
goto out;
/* Push the right-hand side as our result. */
PUSH_OPND(rval);
break;
case JSOP_BINDNAME:
atom = GET_ATOM(cx, script, pc);
SAVE_SP(fp);
ok = js_FindVariable(cx, (jsid)atom, &obj, &obj2, &prop);
if (!ok)
goto out;
OBJ_DROP_PROPERTY(cx, obj2, prop);
PUSH_OPND(OBJECT_TO_JSVAL(obj));
break;
case JSOP_SETNAME2:
atom = GET_ATOM(cx, script, pc);
id = (jsid)atom;
rval = POP();
lval = POP();
PR_ASSERT(!JSVAL_IS_PRIMITIVE(lval));
obj = JSVAL_TO_OBJECT(lval);
CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval));
if (!ok)
goto out;
PUSH_OPND(rval);
break;
#define INTEGER_OP(OP, EXTRA_CODE) { \
SAVE_SP(fp); \
ok = PopInt(cx, &j) && PopInt(cx, &i); \
RESTORE_SP(fp); \
if (!ok) \
goto out; \
EXTRA_CODE \
i = i OP j; \
PUSH_NUMBER(cx, i); \
}
#define BITWISE_OP(OP) INTEGER_OP(OP, (void) 0;)
#define SIGNED_SHIFT_OP(OP) INTEGER_OP(OP, j &= 31;)
case JSOP_BITOR:
BITWISE_OP(|);
break;
case JSOP_BITXOR:
BITWISE_OP(^);
break;
case JSOP_BITAND:
BITWISE_OP(&);
break;
#ifdef XP_PC
#define COMPARE_DOUBLES(LVAL, OP, RVAL, IFNAN) \
((JSDOUBLE_IS_NaN(LVAL) || JSDOUBLE_IS_NaN(RVAL)) \
? (IFNAN) \
: (LVAL) OP (RVAL))
#else
#define COMPARE_DOUBLES(LVAL, OP, RVAL, IFNAN) ((LVAL) OP (RVAL))
#endif
#define RELATIONAL_OP(OP) { \
rval = POP(); \
lval = POP(); \
/* Optimize for two int-tagged operands (typical loop control). */ \
if ((lval & rval) & JSVAL_INT) { \
ltmp = lval ^ JSVAL_VOID; \
rtmp = rval ^ JSVAL_VOID; \
if (ltmp && rtmp) { \
cond = JSVAL_TO_INT(lval) OP JSVAL_TO_INT(rval); \
} else { \
d = ltmp ? JSVAL_TO_INT(lval) : *rt->jsNaN; \
d2 = rtmp ? JSVAL_TO_INT(rval) : *rt->jsNaN; \
cond = COMPARE_DOUBLES(d, OP, d2, JS_FALSE); \
} \
} else { \
VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_NUMBER, &lval); \
/* Need lval for strcmp or ToNumber later, so root it via sp[0]. */ \
sp[0] = lval; \
VALUE_TO_PRIMITIVE(cx, rval, JSTYPE_NUMBER, &rval); \
if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) { \
str = JSVAL_TO_STRING(lval); \
str2 = JSVAL_TO_STRING(rval); \
cond = js_CompareStrings(str, str2) OP 0; \
} else { \
/* Need rval after ToNumber(lval), so root it via sp[1]. */ \
sp[1] = rval; \
VALUE_TO_NUMBER(cx, lval, d); \
VALUE_TO_NUMBER(cx, rval, d2); \
cond = COMPARE_DOUBLES(d, OP, d2, JS_FALSE); \
} \
} \
PUSH_OPND(BOOLEAN_TO_JSVAL(cond)); \
}
#define EQUALITY_OP(OP, IFNAN) { \
rval = POP(); \
lval = POP(); \
ltmp = JSVAL_TAG(lval); \
rtmp = JSVAL_TAG(rval); \
if (ltmp == rtmp) { \
if (ltmp == JSVAL_STRING) { \
str = JSVAL_TO_STRING(lval); \
str2 = JSVAL_TO_STRING(rval); \
cond = js_CompareStrings(str, str2) OP 0; \
} else if (ltmp == JSVAL_DOUBLE) { \
d = *JSVAL_TO_DOUBLE(lval); \
d2 = *JSVAL_TO_DOUBLE(rval); \
cond = COMPARE_DOUBLES(d, OP, d2, IFNAN); \
} else { \
/* Handle all undefined (=>NaN) and int combinations. */ \
cond = lval OP rval; \
} \
} else { \
if (JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval)) { \
cond = (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) OP 1; \
} else if (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) { \
cond = 1 OP 0; \
} else { \
if (ltmp == JSVAL_OBJECT) { \
VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_VOID, &lval); \
ltmp = JSVAL_TAG(lval); \
} else if (rtmp == JSVAL_OBJECT) { \
VALUE_TO_PRIMITIVE(cx, rval, JSTYPE_VOID, &rval); \
rtmp = JSVAL_TAG(rval); \
} \
if (ltmp == JSVAL_STRING && rtmp == JSVAL_STRING) { \
str = JSVAL_TO_STRING(lval); \
str2 = JSVAL_TO_STRING(rval); \
cond = js_CompareStrings(str, str2) OP 0; \
} else { \
/* Need rval after ToNumber(lval), so root it via sp[1]. */ \
sp[1] = rval; \
VALUE_TO_NUMBER(cx, lval, d); \
VALUE_TO_NUMBER(cx, rval, d2); \
cond = COMPARE_DOUBLES(d, OP, d2, IFNAN); \
} \
} \
} \
PUSH_OPND(BOOLEAN_TO_JSVAL(cond)); \
}
case JSOP_EQ:
EQUALITY_OP(==, JS_FALSE);
break;
case JSOP_NE:
EQUALITY_OP(!=, JS_TRUE);
break;
#if !JS_BUG_FALLIBLE_EQOPS
#define NEW_EQUALITY_OP(OP, IFNAN) { \
rval = POP(); \
lval = POP(); \
ltmp = JSVAL_TAG(lval); \
rtmp = JSVAL_TAG(rval); \
if (ltmp == rtmp) { \
if (ltmp == JSVAL_STRING) { \
str = JSVAL_TO_STRING(lval); \
str2 = JSVAL_TO_STRING(rval); \
cond = js_CompareStrings(str, str2) OP 0; \
} else if (ltmp == JSVAL_DOUBLE) { \
d = *JSVAL_TO_DOUBLE(lval); \
d2 = *JSVAL_TO_DOUBLE(rval); \
cond = COMPARE_DOUBLES(d, OP, d2, IFNAN); \
} else { \
cond = lval OP rval; \
} \
} else { \
if (ltmp == JSVAL_DOUBLE && JSVAL_IS_INT(rval)) { \
d = *JSVAL_TO_DOUBLE(lval); \
JS/js/jsinterp.c view on Meta::CPAN
* Keep rval on the stack so it isn't GC'd during the next
* js_ValueToString.
*/
sp[1] = rval;
str2 = JSVAL_TO_STRING(rval);
SAVE_SP(fp);
ok = (str = js_ValueToString(cx, lval)) != NULL;
}
if (!ok)
goto out;
if ((length = str->length) == 0) {
str3 = str2;
} else if ((length2 = str2->length) == 0) {
str3 = str;
} else {
length3 = length + length2;
chars = JS_malloc(cx, (length3 + 1) * sizeof(jschar));
if (!chars) {
ok = JS_FALSE;
goto out;
}
js_strncpy(chars, str->chars, length);
js_strncpy(chars + length, str2->chars, length2);
chars[length3] = 0;
str3 = js_NewString(cx, chars, length3, 0);
if (!str3) {
JS_free(cx, chars);
ok = JS_FALSE;
goto out;
}
}
PUSH_OPND(STRING_TO_JSVAL(str3));
} else {
VALUE_TO_NUMBER(cx, ltmp, d);
VALUE_TO_NUMBER(cx, rtmp, d2);
d += d2;
PUSH_NUMBER(cx, d);
}
break;
#define BINARY_OP(OP) { \
POP_NUMBER(cx, d2); \
POP_NUMBER(cx, d); \
d = d OP d2; \
PUSH_NUMBER(cx, d); \
}
case JSOP_SUB:
BINARY_OP(-);
break;
case JSOP_MUL:
BINARY_OP(*);
break;
case JSOP_DIV:
POP_NUMBER(cx, d2);
POP_NUMBER(cx, d);
if (d2 == 0) {
#ifdef XP_PC
/* XXX MSVC miscompiles such that (NaN == 0) */
if (JSDOUBLE_IS_NaN(d2))
rval = DOUBLE_TO_JSVAL(rt->jsNaN);
else
#endif
if (d == 0 || JSDOUBLE_IS_NaN(d))
rval = DOUBLE_TO_JSVAL(rt->jsNaN);
else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
rval = DOUBLE_TO_JSVAL(rt->jsNegativeInfinity);
else
rval = DOUBLE_TO_JSVAL(rt->jsPositiveInfinity);
PUSH_OPND(rval);
} else {
d /= d2;
PUSH_NUMBER(cx, d);
}
break;
case JSOP_MOD:
POP_NUMBER(cx, d2);
POP_NUMBER(cx, d);
if (d2 == 0) {
PUSH_OPND(DOUBLE_TO_JSVAL(rt->jsNaN));
} else {
#ifdef XP_PC
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))
#endif
d = fmod(d, d2);
PUSH_NUMBER(cx, d);
}
break;
case JSOP_NOT:
POP_BOOLEAN(cx, rval, cond);
PUSH_OPND(BOOLEAN_TO_JSVAL(!cond));
break;
case JSOP_BITNOT:
SAVE_SP(fp);
ok = PopInt(cx, &i);
RESTORE_SP(fp);
if (!ok)
goto out;
i = ~i;
PUSH_NUMBER(cx, i);
break;
case JSOP_NEG:
POP_NUMBER(cx, d);
d = -d;
PUSH_NUMBER(cx, d);
break;
case JSOP_POS:
POP_NUMBER(cx, d);
PUSH_NUMBER(cx, d);
break;
case JSOP_NEW:
/* Get immediate argc and find the constructor function. */
argc = GET_ARGC(pc);
do_new:
vp = sp - (2 + argc);
PR_ASSERT(vp >= newsp);
lval = *vp;
if (!JSVAL_IS_OBJECT(lval) ||
(obj2 = JSVAL_TO_OBJECT(lval)) == NULL ||
!obj2->map->ops->construct) {
fun = js_ValueToFunction(cx, vp, JS_TRUE);
if (!fun) {
ok = JS_FALSE;
goto out;
}
obj2 = fun->object;
}
if (!obj2) {
proto = parent = NULL;
fun = NULL;
} else {
/* Get the constructor prototype object for this function. */
ok = OBJ_GET_PROPERTY(cx, obj2,
(jsid)rt->atomState.classPrototypeAtom,
( run in 0.568 second using v1.01-cache-2.11-cpan-39bf76dae61 )