mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge.
This commit is contained in:
commit
e91eb4bc47
@ -69,9 +69,6 @@
|
||||
#include "jsxml.h"
|
||||
#endif
|
||||
|
||||
#define JSSLOT_ITER_STATE (JSSLOT_PRIVATE)
|
||||
#define JSSLOT_ITER_FLAGS (JSSLOT_PRIVATE + 1)
|
||||
|
||||
#if JSSLOT_ITER_FLAGS >= JS_INITIAL_NSLOTS
|
||||
#error JS_INITIAL_NSLOTS must be greater than JSSLOT_ITER_FLAGS.
|
||||
#endif
|
||||
@ -225,11 +222,11 @@ IteratorNextImpl(JSContext *cx, JSObject *obj, jsval *rval)
|
||||
|
||||
iterable = OBJ_GET_PARENT(cx, obj);
|
||||
JS_ASSERT(iterable);
|
||||
state = OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_STATE);
|
||||
state = STOBJ_GET_SLOT(obj, JSSLOT_ITER_STATE);
|
||||
if (JSVAL_IS_NULL(state))
|
||||
goto stop;
|
||||
|
||||
flags = JSVAL_TO_INT(OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_FLAGS));
|
||||
flags = JSVAL_TO_INT(STOBJ_GET_SLOT(obj, JSSLOT_ITER_FLAGS));
|
||||
JS_ASSERT(!(flags & JSITER_ENUMERATE));
|
||||
foreach = (flags & JSITER_FOREACH) != 0;
|
||||
ok =
|
||||
@ -263,7 +260,7 @@ IteratorNextImpl(JSContext *cx, JSObject *obj, jsval *rval)
|
||||
return JS_TRUE;
|
||||
|
||||
stop:
|
||||
JS_ASSERT(OBJ_GET_SLOT(cx, obj, JSSLOT_ITER_STATE) == JSVAL_NULL);
|
||||
JS_ASSERT(STOBJ_GET_SLOT(obj, JSSLOT_ITER_STATE) == JSVAL_NULL);
|
||||
*rval = JSVAL_HOLE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -319,7 +316,7 @@ js_GetNativeIteratorFlags(JSContext *cx, JSObject *iterobj)
|
||||
{
|
||||
if (OBJ_GET_CLASS(cx, iterobj) != &js_IteratorClass)
|
||||
return 0;
|
||||
return JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_FLAGS));
|
||||
return JSVAL_TO_INT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_FLAGS));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -598,7 +595,7 @@ js_CallIteratorNext(JSContext *cx, JSObject *iterobj, jsval *rval)
|
||||
|
||||
/* Fast path for native iterators */
|
||||
if (OBJ_GET_CLASS(cx, iterobj) == &js_IteratorClass) {
|
||||
flags = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_FLAGS));
|
||||
flags = JSVAL_TO_INT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_FLAGS));
|
||||
if (flags & JSITER_ENUMERATE)
|
||||
return CallEnumeratorNext(cx, iterobj, flags, rval);
|
||||
|
||||
|
@ -57,6 +57,12 @@ JS_BEGIN_EXTERN_C
|
||||
#define JSITER_FOREACH 0x2 /* return [key, value] pair rather than key */
|
||||
#define JSITER_KEYVALUE 0x4 /* destructuring for-in wants [key, value] */
|
||||
|
||||
/*
|
||||
* Native iterator object slots, shared between jsiter.cpp and jstracer.cpp.
|
||||
*/
|
||||
#define JSSLOT_ITER_STATE (JSSLOT_PRIVATE)
|
||||
#define JSSLOT_ITER_FLAGS (JSSLOT_PRIVATE + 1)
|
||||
|
||||
/*
|
||||
* Convert the value stored in *vp to its iteration object. The flags should
|
||||
* contain JSITER_ENUMERATE if js_ValueToIterator is called when enumerating
|
||||
|
@ -4129,20 +4129,6 @@ out:
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private type used to enumerate properties of a native JS object. It is not
|
||||
* allocated when there are no enumerable properties in the object. Instead
|
||||
* for empty enumerators the code uses JSVAL_ZERO as the enumeration state.
|
||||
*/
|
||||
struct JSNativeEnumerator {
|
||||
uint32 cursor; /* index into ids array, runs from
|
||||
length down to 0 */
|
||||
uint32 length; /* length of ids array */
|
||||
JSNativeEnumerator *next; /* double-linked list support */
|
||||
JSNativeEnumerator **prevp;
|
||||
jsid ids[1]; /* enumeration id array */
|
||||
};
|
||||
|
||||
/*
|
||||
* This function is used to enumerate the properties of native JSObjects
|
||||
* and those host objects that do not define a JSNewEnumerateOp-style iterator
|
||||
|
@ -609,6 +609,22 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval);
|
||||
extern JSBool
|
||||
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
|
||||
|
||||
/*
|
||||
* Private type used to enumerate properties of a native JS object. It is not
|
||||
* allocated when there are no enumerable properties in the object. Instead for
|
||||
* empty enumerators js_Enumerate uses JSVAL_ZERO as the enumeration state.
|
||||
*
|
||||
* Shared between jsobj.cpp and jstracer.cpp.
|
||||
*/
|
||||
struct JSNativeEnumerator {
|
||||
uint32 cursor; /* index into ids array, runs from
|
||||
length down to 0 */
|
||||
uint32 length; /* length of ids array */
|
||||
JSNativeEnumerator *next; /* double-linked list support */
|
||||
JSNativeEnumerator **prevp;
|
||||
jsid ids[1]; /* enumeration id array */
|
||||
};
|
||||
|
||||
extern JSBool
|
||||
js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp);
|
||||
|
@ -410,6 +410,10 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
i = (jsint)GET_UINT24(pc);
|
||||
goto print_int;
|
||||
|
||||
case JOF_UINT8:
|
||||
i = pc[1];
|
||||
goto print_int;
|
||||
|
||||
case JOF_INT8:
|
||||
i = GET_INT8(pc);
|
||||
goto print_int;
|
||||
|
@ -76,7 +76,7 @@ typedef enum JSOp {
|
||||
#define JOF_TABLESWITCHX 10 /* extended (32-bit offset) table switch */
|
||||
#define JOF_LOOKUPSWITCHX 11 /* extended (32-bit offset) lookup switch */
|
||||
#define JOF_UINT24 12 /* extended unsigned 24-bit literal (index) */
|
||||
#define JOF_2BYTE 13 /* 2-byte opcode, e.g., upper 8 bits of 24-bit
|
||||
#define JOF_UINT8 13 /* uint8 immediate, e.g. top 8 bits of 24-bit
|
||||
atom index */
|
||||
#define JOF_LOCAL 14 /* block-local operand stack variable */
|
||||
#define JOF_OBJECT 15 /* unsigned 16-bit object pool index */
|
||||
|
@ -237,7 +237,7 @@ OPDEF(JSOP_VARDEC, 102,"vardec", NULL, 3, 0, 1, 15, JOF_QVAR |
|
||||
* Initialize for-in iterator using the JSITER_* flag bits in this op's uint8
|
||||
* immediate operand. See also JSOP_ENDITER.
|
||||
*/
|
||||
OPDEF(JSOP_ITER, 103,"iter", NULL, 2, 1, 1, 0, JOF_2BYTE)
|
||||
OPDEF(JSOP_ITER, 103,"iter", NULL, 2, 1, 1, 0, JOF_UINT8)
|
||||
|
||||
/* ECMA-compliant for/in ops. */
|
||||
OPDEF(JSOP_FORNAME, 104,"forname", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_FOR)
|
||||
@ -425,7 +425,7 @@ OPDEF(JSOP_UINT24, 188,"uint24", NULL, 4, 0, 1, 16, JOF_UINT24
|
||||
* JSOP_INDEXBASE and JSOP_RESETBASE to provide the upper bits of the index.
|
||||
* See jsemit.c, EmitIndexOp.
|
||||
*/
|
||||
OPDEF(JSOP_INDEXBASE, 189,"atombase", NULL, 2, 0, 0, 0, JOF_2BYTE|JOF_INDEXBASE)
|
||||
OPDEF(JSOP_INDEXBASE, 189,"atombase", NULL, 2, 0, 0, 0, JOF_UINT8|JOF_INDEXBASE)
|
||||
OPDEF(JSOP_RESETBASE, 190,"resetbase", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_RESETBASE0, 191,"resetbase0", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "jscntxt.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jsiter.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsopcode.h"
|
||||
#include "jsscript.h"
|
||||
@ -1079,13 +1080,13 @@ TraceRecorder::verifyTypeStability()
|
||||
uint16* gslots = treeInfo->globalSlots.data();
|
||||
uint8* m = treeInfo->globalTypeMap.data();
|
||||
JS_ASSERT(treeInfo->globalTypeMap.length() == ngslots);
|
||||
FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
|
||||
FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
|
||||
if (!checkType(*vp, *m))
|
||||
return false;
|
||||
++m
|
||||
);
|
||||
m = treeInfo->stackTypeMap.data();
|
||||
FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
|
||||
FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
|
||||
if (!checkType(*vp, *m))
|
||||
return false;
|
||||
++m
|
||||
@ -1192,11 +1193,11 @@ js_DeleteRecorder(JSContext* cx)
|
||||
}
|
||||
|
||||
static bool
|
||||
js_StartRecorder(JSContext* cx, GuardRecord* anchor, Fragment* f,
|
||||
js_StartRecorder(JSContext* cx, GuardRecord* anchor, Fragment* f,
|
||||
unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap)
|
||||
{
|
||||
/* start recording if no exception during construction */
|
||||
JS_TRACE_MONITOR(cx).recorder = new (&gc) TraceRecorder(cx, anchor, f,
|
||||
JS_TRACE_MONITOR(cx).recorder = new (&gc) TraceRecorder(cx, anchor, f,
|
||||
ngslots, globalTypeMap, stackTypeMap);
|
||||
if (cx->throwing) {
|
||||
js_AbortRecording(cx, NULL, "setting up recorder failed");
|
||||
@ -1394,7 +1395,7 @@ js_LoopEdge(JSContext* cx, jsbytecode* oldpc)
|
||||
JS_ASSERT(ti->entryStackDepth == unsigned(cx->fp->regs->sp - StackBase(cx->fp)));
|
||||
|
||||
/* recording primary trace */
|
||||
return js_StartRecorder(cx, NULL, f, ti->globalSlots.length(),
|
||||
return js_StartRecorder(cx, NULL, f, ti->globalSlots.length(),
|
||||
ti->globalTypeMap.data(), ti->stackTypeMap.data());
|
||||
}
|
||||
return false;
|
||||
@ -1414,7 +1415,7 @@ js_LoopEdge(JSContext* cx, jsbytecode* oldpc)
|
||||
return false;
|
||||
default:
|
||||
JS_ASSERT(lr->exit->exitType == DONT_GROW);
|
||||
/* We ran out of heap, or an unsupported instruction. Exit for now and re-enter once the
|
||||
/* We ran out of heap, or an unsupported instruction. Exit for now and re-enter once the
|
||||
GC ran. */
|
||||
return false;
|
||||
}
|
||||
@ -1714,15 +1715,15 @@ TraceRecorder::binary(LOpcode op)
|
||||
}
|
||||
|
||||
bool
|
||||
TraceRecorder::map_is_native(JSObjectMap* map, LIns* map_ins)
|
||||
TraceRecorder::map_is_native(JSObjectMap* map, LIns* map_ins, LIns*& ops_ins)
|
||||
{
|
||||
LIns* ops = addName(lir->insLoadi(map_ins, offsetof(JSObjectMap, ops)), "ops");
|
||||
ops_ins = addName(lir->insLoadi(map_ins, offsetof(JSObjectMap, ops)), "ops");
|
||||
if (map->ops == &js_ObjectOps) {
|
||||
guard(true, addName(lir->ins2(LIR_eq, ops, lir->insImmPtr(&js_ObjectOps)),
|
||||
guard(true, addName(lir->ins2(LIR_eq, ops_ins, lir->insImmPtr(&js_ObjectOps)),
|
||||
"guard(native-ops)"));
|
||||
return true;
|
||||
}
|
||||
LIns* n = lir->insLoadi(ops, offsetof(JSObjectOps, newObjectMap));
|
||||
LIns* n = lir->insLoadi(ops_ins, offsetof(JSObjectOps, newObjectMap));
|
||||
if (map->ops->newObjectMap == js_ObjectOps.newObjectMap) {
|
||||
guard(true, addName(lir->ins2(LIR_eq, n, lir->insImmPtr((void*)js_ObjectOps.newObjectMap)),
|
||||
"guard(native-map)"));
|
||||
@ -1735,7 +1736,8 @@ bool
|
||||
TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2, jsuword& pcval)
|
||||
{
|
||||
LIns* map_ins = lir->insLoadi(obj_ins, offsetof(JSObject, map));
|
||||
if (!map_is_native(obj->map, map_ins))
|
||||
LIns* ops_ins;
|
||||
if (!map_is_native(obj->map, map_ins, ops_ins))
|
||||
return false;
|
||||
|
||||
JSAtom* atom;
|
||||
@ -1775,9 +1777,10 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2
|
||||
if (PCVCAP_TAG(entry->vcap) == 1) {
|
||||
JS_ASSERT(OBJ_SCOPE(obj2)->shape == PCVCAP_SHAPE(entry->vcap));
|
||||
|
||||
LIns* obj2_ins = get(&STOBJ_GET_SLOT(obj, JSSLOT_PROTO));
|
||||
LIns* obj2_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
|
||||
map_ins = lir->insLoadi(obj2_ins, offsetof(JSObject, map));
|
||||
if (!map_is_native(obj2->map, map_ins))
|
||||
LIns* ops_ins;
|
||||
if (!map_is_native(obj2->map, map_ins, ops_ins))
|
||||
return false;
|
||||
|
||||
shape_ins = addName(lir->insLoadi(map_ins, offsetof(JSScope, shape)), "shape");
|
||||
@ -1869,13 +1872,18 @@ TraceRecorder::stobj_set_slot(LIns* obj_ins, unsigned slot, LIns*& dslots_ins, L
|
||||
}
|
||||
}
|
||||
|
||||
LIns*
|
||||
TraceRecorder::stobj_get_fslot(LIns* obj_ins, unsigned slot)
|
||||
{
|
||||
JS_ASSERT(slot < JS_INITIAL_NSLOTS);
|
||||
return lir->insLoadi(obj_ins, offsetof(JSObject, fslots) + slot * sizeof(jsval));
|
||||
}
|
||||
|
||||
LIns*
|
||||
TraceRecorder::stobj_get_slot(LIns* obj_ins, unsigned slot, LIns*& dslots_ins)
|
||||
{
|
||||
if (slot < JS_INITIAL_NSLOTS) {
|
||||
return lir->insLoadi(obj_ins,
|
||||
offsetof(JSObject, fslots) + slot * sizeof(jsval));
|
||||
}
|
||||
if (slot < JS_INITIAL_NSLOTS)
|
||||
return stobj_get_fslot(obj_ins, slot);
|
||||
|
||||
if (!dslots_ins)
|
||||
dslots_ins = lir->insLoadi(obj_ins, offsetof(JSObject, dslots));
|
||||
@ -1984,35 +1992,40 @@ TraceRecorder::getThis(LIns*& this_ins)
|
||||
}
|
||||
|
||||
bool
|
||||
TraceRecorder::guardThatObjectHasClass(JSObject* obj, LIns* obj_ins,
|
||||
JSClass* cls, LIns*& dslots_ins)
|
||||
TraceRecorder::guardClass(JSObject* obj, LIns* obj_ins, JSClass* clasp)
|
||||
{
|
||||
if (STOBJ_GET_CLASS(obj) != cls)
|
||||
if (STOBJ_GET_CLASS(obj) != clasp)
|
||||
return false;
|
||||
LIns* class_ins = stobj_get_slot(obj_ins, JSSLOT_CLASS, dslots_ins);
|
||||
|
||||
LIns* class_ins = stobj_get_fslot(obj_ins, JSSLOT_CLASS);
|
||||
class_ins = lir->ins2(LIR_and, class_ins, lir->insImmPtr((void*)~3));
|
||||
guard(true, lir->ins2(LIR_eq, class_ins, lir->insImmPtr(cls)));
|
||||
|
||||
char namebuf[32];
|
||||
JS_snprintf(namebuf, sizeof namebuf, "guard(class is %s)", clasp->name);
|
||||
guard(true, addName(lir->ins2(LIR_eq, class_ins, lir->insImmPtr(clasp)), namebuf));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::guardThatObjectIsDenseArray(JSObject* obj, LIns* obj_ins, LIns*& dslots_ins)
|
||||
bool TraceRecorder::guardDenseArray(JSObject* obj, LIns* obj_ins)
|
||||
{
|
||||
return guardThatObjectHasClass(obj, obj_ins, &js_ArrayClass, dslots_ins);
|
||||
return guardClass(obj, obj_ins, &js_ArrayClass);
|
||||
}
|
||||
|
||||
bool TraceRecorder::guardDenseArrayIndexWithinBounds(JSObject* obj, jsint idx,
|
||||
LIns* obj_ins, LIns*& dslots_ins, LIns* idx_ins)
|
||||
bool TraceRecorder::guardDenseArrayIndex(JSObject* obj, jsint idx, LIns* obj_ins,
|
||||
LIns* dslots_ins, LIns* idx_ins)
|
||||
{
|
||||
jsuint length = ARRAY_DENSE_LENGTH(obj);
|
||||
if (!((jsuint)idx < length && idx < obj->fslots[JSSLOT_ARRAY_LENGTH]))
|
||||
return false;
|
||||
if (!dslots_ins)
|
||||
dslots_ins = lir->insLoadi(obj_ins, offsetof(JSObject, dslots));
|
||||
LIns* length_ins = stobj_get_slot(obj_ins, JSSLOT_ARRAY_LENGTH, dslots_ins);
|
||||
|
||||
LIns* length_ins = stobj_get_fslot(obj_ins, JSSLOT_ARRAY_LENGTH);
|
||||
|
||||
// guard(index >= 0)
|
||||
guard(true, lir->ins2i(LIR_ge, idx_ins, 0));
|
||||
|
||||
// guard(index < length)
|
||||
guard(true, lir->ins2(LIR_lt, idx_ins, length_ins));
|
||||
|
||||
// guard(index < capacity)
|
||||
guard(false, lir->ins_eq0(dslots_ins));
|
||||
guard(true, lir->ins2(LIR_lt, idx_ins,
|
||||
@ -2103,14 +2116,7 @@ bool TraceRecorder::record_JSOP_ARGUMENTS()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool TraceRecorder::record_JSOP_FORARG()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool TraceRecorder::record_JSOP_FORVAR()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_DUP()
|
||||
{
|
||||
stack(0, get(&stackval(-1)));
|
||||
@ -2342,7 +2348,8 @@ bool TraceRecorder::record_JSOP_SETPROP()
|
||||
ABORT_TRACE("cache miss");
|
||||
|
||||
LIns* map_ins = lir->insLoadi(obj_ins, offsetof(JSObject, map));
|
||||
if (!map_is_native(obj->map, map_ins))
|
||||
LIns* ops_ins;
|
||||
if (!map_is_native(obj->map, map_ins, ops_ins))
|
||||
return false;
|
||||
|
||||
if (obj != globalObj) { // global object's shape is guarded at trace entry
|
||||
@ -2404,8 +2411,7 @@ bool TraceRecorder::record_JSOP_SETELEM()
|
||||
LIns* obj_ins = get(&l);
|
||||
|
||||
/* make sure the object is actually a dense array */
|
||||
LIns* dslots_ins = lir->insLoadi(obj_ins, offsetof(JSObject, dslots));
|
||||
if (!guardThatObjectIsDenseArray(obj, obj_ins, dslots_ins))
|
||||
if (!guardDenseArray(obj, obj_ins))
|
||||
ABORT_TRACE("not a dense array");
|
||||
|
||||
/* check that the index is within bounds */
|
||||
@ -2448,7 +2454,7 @@ bool TraceRecorder::record_JSOP_CALLNAME()
|
||||
}
|
||||
|
||||
JSInlineFrame*
|
||||
TraceRecorder::synthesizeFrame(JSObject* callee, JSObject *thisp, jsbytecode* pc)
|
||||
TraceRecorder::synthesizeFrame(JSObject* callee, JSObject* thisp, jsbytecode* pc)
|
||||
{
|
||||
JS_ASSERT(HAS_FUNCTION_CLASS(callee));
|
||||
|
||||
@ -2549,7 +2555,7 @@ bool TraceRecorder::record_JSOP_CALL()
|
||||
ABORT_TRACE("can't trace function calls with arity mismatch");
|
||||
unsigned callDepth = getCallDepth();
|
||||
lir->insStorei(lir->insImmPtr(JSVAL_TO_OBJECT(fval)),
|
||||
lirbuf->rp, callDepth * sizeof(JSObject*));
|
||||
lirbuf->rp, callDepth * sizeof(JSObject*));
|
||||
if (callDepth+1 > treeInfo->maxCallDepth)
|
||||
treeInfo->maxCallDepth = callDepth+1;
|
||||
atoms = fun->u.i.script->atomMap.vector;
|
||||
@ -2711,8 +2717,7 @@ TraceRecorder::elem(jsval& l, jsval& r, jsval*& vp, LIns*& v_ins, LIns*& addr_in
|
||||
guard(false, lir->ins2(LIR_eq, obj_ins, lir->insImmPtr((void*)globalObj)));
|
||||
|
||||
/* make sure the object is actually a dense array */
|
||||
LIns* dslots_ins = lir->insLoadi(obj_ins, offsetof(JSObject, dslots));
|
||||
if (!guardThatObjectIsDenseArray(obj, obj_ins, dslots_ins))
|
||||
if (!guardDenseArray(obj, obj_ins))
|
||||
return false;
|
||||
|
||||
/* check that the index is within bounds */
|
||||
@ -2722,12 +2727,15 @@ TraceRecorder::elem(jsval& l, jsval& r, jsval*& vp, LIns*& v_ins, LIns*& addr_in
|
||||
/* we have to check that its really an integer, but this check will to go away
|
||||
once we peel the loop type down to integer for this slot */
|
||||
guard(true, lir->ins2(LIR_feq, get(&r), lir->ins1(LIR_i2f, idx_ins)));
|
||||
if (!guardDenseArrayIndexWithinBounds(obj, idx, obj_ins, dslots_ins, idx_ins))
|
||||
|
||||
LIns* dslots_ins = lir->insLoadi(obj_ins, offsetof(JSObject, dslots));
|
||||
if (!guardDenseArrayIndex(obj, idx, obj_ins, dslots_ins, idx_ins))
|
||||
return false;
|
||||
vp = &obj->dslots[idx];
|
||||
|
||||
addr_ins = lir->ins2(LIR_add, dslots_ins,
|
||||
lir->ins2i(LIR_lsh, idx_ins, sizeof(jsval) == 4 ? 2 : 3));
|
||||
lir->ins2i(LIR_lsh, idx_ins, (sizeof(jsval) == 4) ? 2 : 3));
|
||||
|
||||
/* load the value, check the type (need to check JSVAL_HOLE only for booleans) */
|
||||
v_ins = lir->insLoad(LIR_ld, addr_ins, 0);
|
||||
return unbox_jsval(*vp, v_ins);
|
||||
@ -2878,38 +2886,47 @@ bool TraceRecorder::record_JSOP_OBJECT()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_POP()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_POS()
|
||||
{
|
||||
return false;
|
||||
jsval& r = stackval(-1);
|
||||
return isNumber(r);
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_TRAP()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_GETARG()
|
||||
{
|
||||
stack(0, arg(GET_ARGNO(cx->fp->regs->pc)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_SETARG()
|
||||
{
|
||||
arg(GET_ARGNO(cx->fp->regs->pc), stack(-1));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_GETVAR()
|
||||
{
|
||||
stack(0, var(GET_SLOTNO(cx->fp->regs->pc)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_SETVAR()
|
||||
{
|
||||
var(GET_SLOTNO(cx->fp->regs->pc), stack(-1));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_UINT16()
|
||||
{
|
||||
jsdpun u;
|
||||
@ -2917,82 +2934,190 @@ bool TraceRecorder::record_JSOP_UINT16()
|
||||
stack(0, lir->insImmq(u.u64));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_NEWINIT()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_ENDINIT()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_INITPROP()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_INITELEM()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_DEFSHARP()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_USESHARP()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_INCARG()
|
||||
{
|
||||
return inc(argval(GET_ARGNO(cx->fp->regs->pc)), 1);
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_INCVAR()
|
||||
{
|
||||
return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), 1);
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_DECARG()
|
||||
{
|
||||
return inc(argval(GET_ARGNO(cx->fp->regs->pc)), -1);
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_DECVAR()
|
||||
{
|
||||
return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), -1);
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_ARGINC()
|
||||
{
|
||||
return inc(argval(GET_ARGNO(cx->fp->regs->pc)), 1, false);
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_VARINC()
|
||||
{
|
||||
return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), 1, false);
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_ARGDEC()
|
||||
{
|
||||
return inc(argval(GET_ARGNO(cx->fp->regs->pc)), -1, false);
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_VARDEC()
|
||||
{
|
||||
return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), -1, false);
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_ITER()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::forInProlog(LIns*& iterobj_ins)
|
||||
{
|
||||
jsval& iterval = stackval(-1);
|
||||
JS_ASSERT(!JSVAL_IS_PRIMITIVE(iterval));
|
||||
JSObject* iterobj = JSVAL_TO_OBJECT(iterval);
|
||||
|
||||
iterobj_ins = get(&iterval);
|
||||
if (guardClass(iterobj, iterobj_ins, &js_IteratorClass)) {
|
||||
uintN flags = JSVAL_TO_INT(iterobj->fslots[JSSLOT_ITER_FLAGS]);
|
||||
if (flags & ~JSITER_ENUMERATE)
|
||||
ABORT_TRACE("for-each-in or destructuring JSOP_ITER not traced");
|
||||
|
||||
guard(true,
|
||||
addName(lir->ins_eq0(lir->ins2(LIR_and,
|
||||
lir->insLoadi(iterobj_ins,
|
||||
offsetof(JSObject, fslots) +
|
||||
JSSLOT_ITER_FLAGS * sizeof(jsval)),
|
||||
lir->insImm(~JSITER_ENUMERATE))),
|
||||
"guard(iter flags is JSITER_ENUMERATE)"));
|
||||
|
||||
JSObject* obj = STOBJ_GET_PARENT(iterobj);
|
||||
LIns* obj_ins = stobj_get_fslot(iterobj_ins, JSSLOT_PARENT);
|
||||
LIns* map_ins = lir->insLoadi(obj_ins, offsetof(JSObject, map));
|
||||
LIns* ops_ins;
|
||||
if (!map_is_native(obj->map, map_ins, ops_ins))
|
||||
return false;
|
||||
|
||||
LIns* n = lir->insLoadi(ops_ins, offsetof(JSObjectOps, enumerate));
|
||||
if (obj->map->ops->enumerate == js_ObjectOps.enumerate) {
|
||||
guard(true, addName(lir->ins2(LIR_eq, n, lir->insImmPtr((void*)js_ObjectOps.enumerate)),
|
||||
"guard(native-enumerate)"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_ENDITER()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_FORNAME()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_FORPROP()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_FORELEM()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_FORARG()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_FORVAR()
|
||||
{
|
||||
LIns* iterobj_ins;
|
||||
if (!forInProlog(iterobj_ins))
|
||||
return false;
|
||||
|
||||
LIns* stateval_ins = stobj_get_fslot(iterobj_ins, JSSLOT_ITER_STATE);
|
||||
|
||||
guard(false,
|
||||
addName(lir->ins2(LIR_eq, stateval_ins, lir->insImmPtr((void*) JSVAL_ZERO)),
|
||||
"guard(non-empty iter state)"));
|
||||
|
||||
LIns* state_ins = lir->ins2(LIR_and, stateval_ins, lir->insImmPtr((void*) ~3));
|
||||
LIns* cursor_ins = lir->insLoadi(state_ins, offsetof(JSNativeEnumerator, cursor));
|
||||
guard(false, addName(lir->ins_eq0(cursor_ins), "guard(ne->cursor != 0)"));
|
||||
|
||||
cursor_ins = lir->ins2i(LIR_sub, cursor_ins, 1);
|
||||
lir->insStorei(cursor_ins, state_ins, offsetof(JSNativeEnumerator, cursor));
|
||||
|
||||
LIns* ids_ins = lir->ins2i(LIR_add, state_ins, offsetof(JSNativeEnumerator, ids));
|
||||
LIns* id_addr_ins = lir->ins2(LIR_add, ids_ins,
|
||||
lir->ins2i(LIR_lsh, cursor_ins, (sizeof(jsid) == 4) ? 2 : 3));
|
||||
|
||||
LIns* id_ins = lir->insLoadi(id_addr_ins, 0);
|
||||
var(GET_SLOTNO(cx->fp->regs->pc), id_ins);
|
||||
|
||||
// Stack an unboxed true to make JSOP_IFEQ loop.
|
||||
stack(0, lir->insImm(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_FORLOCAL()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_FORCONST()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_POPN()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_BINDNAME()
|
||||
{
|
||||
JSObject* obj = cx->fp->scopeChain;
|
||||
@ -3241,6 +3366,7 @@ bool TraceRecorder::record_JSOP_RETRVAL()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_GETGVAR()
|
||||
{
|
||||
jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
|
||||
@ -3251,7 +3377,7 @@ bool TraceRecorder::record_JSOP_GETGVAR()
|
||||
|
||||
if (!lazilyImportGlobalSlot(slot))
|
||||
ABORT_TRACE("lazy import of global slot failed");
|
||||
|
||||
|
||||
stack(0, get(&STOBJ_GET_SLOT(cx->fp->scopeChain, slot)));
|
||||
return true;
|
||||
}
|
||||
@ -3266,7 +3392,7 @@ bool TraceRecorder::record_JSOP_SETGVAR()
|
||||
|
||||
if (!lazilyImportGlobalSlot(slot))
|
||||
ABORT_TRACE("lazy import of global slot failed");
|
||||
|
||||
|
||||
set(&STOBJ_GET_SLOT(cx->fp->scopeChain, slot), stack(-1));
|
||||
return true;
|
||||
}
|
||||
@ -3278,10 +3404,10 @@ bool TraceRecorder::record_JSOP_INCGVAR()
|
||||
return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
|
||||
|
||||
uint32 slot = JSVAL_TO_INT(slotval);
|
||||
|
||||
|
||||
if (!lazilyImportGlobalSlot(slot))
|
||||
ABORT_TRACE("lazy import of global slot failed");
|
||||
|
||||
|
||||
return inc(STOBJ_GET_SLOT(cx->fp->scopeChain, slot), 1);
|
||||
}
|
||||
|
||||
@ -3292,10 +3418,10 @@ bool TraceRecorder::record_JSOP_DECGVAR()
|
||||
return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
|
||||
|
||||
uint32 slot = JSVAL_TO_INT(slotval);
|
||||
|
||||
|
||||
if (!lazilyImportGlobalSlot(slot))
|
||||
ABORT_TRACE("lazy import of global slot failed");
|
||||
|
||||
|
||||
return inc(STOBJ_GET_SLOT(cx->fp->scopeChain, slot), -1);
|
||||
}
|
||||
|
||||
@ -3309,7 +3435,7 @@ bool TraceRecorder::record_JSOP_GVARINC()
|
||||
|
||||
if (!lazilyImportGlobalSlot(slot))
|
||||
ABORT_TRACE("lazy import of global slot failed");
|
||||
|
||||
|
||||
return inc(STOBJ_GET_SLOT(cx->fp->scopeChain, slot), 1, false);
|
||||
}
|
||||
|
||||
@ -3323,7 +3449,7 @@ bool TraceRecorder::record_JSOP_GVARDEC()
|
||||
|
||||
if (!lazilyImportGlobalSlot(slot))
|
||||
ABORT_TRACE("lazy import of global slot failed");
|
||||
|
||||
|
||||
return inc(STOBJ_GET_SLOT(cx->fp->scopeChain, slot), -1, false);
|
||||
}
|
||||
|
||||
@ -3614,21 +3740,6 @@ bool TraceRecorder::record_JSOP_LOCALDEC()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_FORLOCAL()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_FORCONST()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_ENDITER()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::record_JSOP_GENERATOR()
|
||||
{
|
||||
return false;
|
||||
@ -3757,13 +3868,12 @@ bool TraceRecorder::record_JSOP_LENGTH()
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *obj = JSVAL_TO_OBJECT(l);
|
||||
JSObject* obj = JSVAL_TO_OBJECT(l);
|
||||
if (!OBJ_IS_DENSE_ARRAY(cx, obj))
|
||||
ABORT_TRACE("only dense arrays supported");
|
||||
LIns* dslots_ins;
|
||||
if (!guardThatObjectIsDenseArray(obj, get(&l), dslots_ins))
|
||||
if (!guardDenseArray(obj, get(&l)))
|
||||
ABORT_TRACE("OBJ_IS_DENSE_ARRAY but not?!?");
|
||||
LIns* v_ins = lir->ins1(LIR_i2f, stobj_get_slot(get(&l), JSSLOT_ARRAY_LENGTH, dslots_ins));
|
||||
LIns* v_ins = lir->ins1(LIR_i2f, stobj_get_fslot(get(&l), JSSLOT_ARRAY_LENGTH));
|
||||
set(&l, v_ins);
|
||||
return true;
|
||||
}
|
||||
|
@ -226,11 +226,13 @@ class TraceRecorder {
|
||||
bool bbinary(nanojit::LOpcode op);
|
||||
void demote(jsval& v, jsdouble result);
|
||||
|
||||
bool map_is_native(JSObjectMap* map, nanojit::LIns* map_ins);
|
||||
bool test_property_cache(JSObject* obj, nanojit::LIns* obj_ins, JSObject*& obj2, jsuword& pcval);
|
||||
bool map_is_native(JSObjectMap* map, nanojit::LIns* map_ins, nanojit::LIns*& ops_ins);
|
||||
bool test_property_cache(JSObject* obj, nanojit::LIns* obj_ins, JSObject*& obj2,
|
||||
jsuword& pcval);
|
||||
bool test_property_cache_direct_slot(JSObject* obj, nanojit::LIns* obj_ins, uint32& slot);
|
||||
void stobj_set_slot(nanojit::LIns* obj_ins, unsigned slot,
|
||||
nanojit::LIns*& dslots_ins, nanojit::LIns* v_ins);
|
||||
nanojit::LIns* stobj_get_fslot(nanojit::LIns* obj_ins, unsigned slot);
|
||||
nanojit::LIns* stobj_get_slot(nanojit::LIns* obj_ins, unsigned slot,
|
||||
nanojit::LIns*& dslots_ins);
|
||||
bool native_set(nanojit::LIns* obj_ins, JSScopeProperty* sprop,
|
||||
@ -247,13 +249,12 @@ class TraceRecorder {
|
||||
|
||||
bool box_jsval(jsval v, nanojit::LIns*& v_ins);
|
||||
bool unbox_jsval(jsval v, nanojit::LIns*& v_ins);
|
||||
bool guardThatObjectHasClass(JSObject* obj, nanojit::LIns* obj_ins,
|
||||
JSClass* cls, nanojit::LIns*& dslots_ins);
|
||||
bool guardThatObjectIsDenseArray(JSObject* obj, nanojit::LIns* obj_ins,
|
||||
nanojit::LIns*& dslots_ins);
|
||||
bool guardDenseArrayIndexWithinBounds(JSObject* obj, jsint idx, nanojit::LIns* obj_ins,
|
||||
nanojit::LIns*& dslots_ins, nanojit::LIns* idx_ins);
|
||||
bool guardClass(JSObject* obj, nanojit::LIns* obj_ins, JSClass* clasp);
|
||||
bool guardDenseArray(JSObject* obj, nanojit::LIns* obj_ins);
|
||||
bool guardDenseArrayIndex(JSObject* obj, jsint idx, nanojit::LIns* obj_ins,
|
||||
nanojit::LIns* dslots_ins, nanojit::LIns* idx_ins);
|
||||
void clearFrameSlotsFromCache();
|
||||
bool forInProlog(nanojit::LIns*& iterobj_ins);
|
||||
public:
|
||||
int backEdgeCount;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user