From 4fc71515e06f842facedd48047b6460ad44a5b03 Mon Sep 17 00:00:00 2001 From: "shaver@mozilla.org" Date: Fri, 27 Jun 2008 23:58:06 -0400 Subject: [PATCH] Add guards for XML objects, and some tracer bits to accommodate them. --- js/src/jsinterp.cpp | 14 ++++++++------ js/src/jsinterpinlines.h | 27 +++++++++++++++++++++++++++ js/src/jstracer.cpp | 32 ++++++++++++++++++++++++++++---- js/src/jstracer.h | 6 +++++- js/src/jstracerinlines.h | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+), 11 deletions(-) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 4202ba6564f..b1b7d0b17be 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -3767,12 +3767,14 @@ JS_INTERPRET(JSContext *cx, JSInterpreterState *state) */ #if JS_HAS_XML_SUPPORT #define XML_EQUALITY_OP(OP) \ - if ((ltmp == JSVAL_OBJECT && \ - (obj2 = JSVAL_TO_OBJECT(lval)) && \ - OBJECT_IS_XML(cx, obj2)) || \ - (rtmp == JSVAL_OBJECT && \ - (obj2 = JSVAL_TO_OBJECT(rval)) && \ - OBJECT_IS_XML(cx, obj2))) { \ + if ((JSVAL_IS_OBJECT(lval) && \ + !guard_jsval_is_null(cx, regs, lval) && \ + (prim_jsval_to_object(cx, lval, obj2), \ + guard_obj_is_xml(cx, regs, obj2))) || \ + (JSVAL_IS_OBJECT(rval) && \ + !guard_jsval_is_null(cx, regs, rval) && \ + (prim_jsval_to_object(cx, rval, obj2), \ + guard_obj_is_xml(cx, regs, obj2)))) { \ JSXMLObjectOps *ops; \ \ ops = (JSXMLObjectOps *) obj2->map->ops; \ diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index d3a243c0307..d50918c52c4 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -212,6 +212,33 @@ PRIMITIVE(guard_obj_is_null)(JSContext* cx, JSFrameRegs& regs, JSObject*& obj) return !obj; } +static inline void +PRIMITIVE(prim_load_map_from_obj)(JSContext *cx, JSFrameRegs& regs, + JSObject*& obj, JSObjectMap*& map) +{ + map = obj->map; +} + +static inline void +PRIMITIVE(prim_load_ops_from_map)(JSContext *cx, JSFrameRegs& regs, + JSObjectMap*& map, JSObjectOps*& ops) +{ + ops = map->ops; +} + +static inline bool +PRIMITIVE(prim_ops_are_xml)(JSContext *cx, JSFrameRegs& regs, + JSObjectOps*& ops) +{ + return ops == &js_XMLObjectOps.base; +} + +static inline bool +PRIMITIVE(guard_obj_is_xml)(JSContext *cx, JSFrameRegs& regs, JSObject*& obj) +{ + return OBJECT_IS_XML(cx, obj); +} + static inline void PRIMITIVE(call_ValueToNonNullObject)(JSContext* cx, jsval& v, JSObject*& obj) { diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index edb658a3cc5..a701f482c44 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -247,11 +247,11 @@ TraceRecorder::TraceRecorder(JSContext* cx, JSFrameRegs& regs, Fragmento* fragme JSStackFrame* fp = cx->fp; unsigned n; for (n = 0; n < fp->argc; ++n) - load(&fp->argv[n]); + readstack(&fp->argv[n]); for (n = 0; n < fp->nvars; ++n) - load(&fp->vars[n]); + readstack(&fp->vars[n]); for (n = 0; n < (unsigned)(regs.sp - fp->spbase); ++n) - load(&fp->spbase[n]); + readstack(&fp->spbase[n]); } TraceRecorder::~TraceRecorder() @@ -265,7 +265,7 @@ TraceRecorder::~TraceRecorder() } void -TraceRecorder::load(void* p) +TraceRecorder::readstack(void* p) { JS_ASSERT(frameStack.contains(p)); tracker.set(p, lir->insLoadi(tracker.get(&entryState.sp), @@ -402,6 +402,24 @@ TraceRecorder::guard_ov(bool expected, void* a, JSFrameRegs& regs) #endif } +void +TraceRecorder::guard_eq(bool expected, void* a, void* b, JSFrameRegs& regs) +{ + SideExit exit; + lir->insGuard(expected ? LIR_xf : LIR_xt, + lir->ins2(LIR_eq, get(a), get(b)), + snapshot(exit, regs)); +} + +void +TraceRecorder::guard_eqi(bool expected, void* a, int i, JSFrameRegs& regs) +{ + SideExit exit; + lir->insGuard(expected ? LIR_xf : LIR_xt, + lir->ins2i(LIR_eq, get(a), i), + snapshot(exit, regs)); +} + void TraceRecorder::closeLoop(Fragmento* fragmento) { @@ -409,6 +427,12 @@ TraceRecorder::closeLoop(Fragmento* fragmento) compile(fragmento->assm(), fragment); } +void +TraceRecorder::load(void* a, int32_t i, void* v) +{ + set(v, lir->insLoadi(get(a), i)); +} + bool js_StartRecording(JSContext* cx, JSFrameRegs& regs) { diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 8bf02812149..9799a95d2e6 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -112,7 +112,7 @@ public: void set(void* p, nanojit::LIns* l); nanojit::LIns* get(void* p); - void load(void*); + void readstack(void*); void copy(void* a, void* v); void imm(jsint i, void* v); @@ -129,8 +129,12 @@ public: void guard_0(bool expected, void* a, JSFrameRegs& regs); void guard_h(bool expected, void* a, JSFrameRegs& regs); void guard_ov(bool expected, void* a, JSFrameRegs& regs); + void guard_eq(bool expected, void* a, void* b, JSFrameRegs& regs); + void guard_eqi(bool expected, void* a, int i, JSFrameRegs& regs); void closeLoop(nanojit::Fragmento* fragmento); + + void load(void* a, int32_t i, void* v); }; /* diff --git a/js/src/jstracerinlines.h b/js/src/jstracerinlines.h index 7fd507e1f6d..cb6782d8068 100644 --- a/js/src/jstracerinlines.h +++ b/js/src/jstracerinlines.h @@ -474,4 +474,39 @@ prim_object_as_boolean(JSContext* cx, JSObject*& obj, JSBool& r) recorder(cx)->binary0(LIR_eq, &obj, &r); } +static inline void +prim_load_ops_from_map(JSContext *cx, JSFrameRegs& regs, JSObjectMap*& map, + JSObjectOps*& ops) +{ + interp_prim_load_ops_from_map(cx, regs, map, ops); + recorder(cx)->load(&map, offsetof(JSObjectMap, ops), &ops); +} + +static inline void +prim_load_map_from_obj(JSContext *cx, JSFrameRegs& regs, JSObject*& obj, + JSObjectMap*& map) +{ + interp_prim_load_map_from_obj(cx, regs, obj, map); + recorder(cx)->load(&obj, offsetof(JSObject, map), &map); +} + +static inline bool +guard_ops_are_xml(JSContext *cx, JSFrameRegs& regs, JSObjectOps*& ops) +{ + bool ok = interp_prim_ops_are_xml(cx, regs, ops); + recorder(cx)->guard_eqi(ok, &ops, (int)&js_XMLObjectOps.base, regs); + return ok; +} + +static inline bool +guard_obj_is_xml(JSContext* cx, JSFrameRegs& regs, JSObject*& obj) +{ + JSObjectMap *map; + JSObjectOps *ops; + prim_load_map_from_obj(cx, regs, obj, map); + prim_load_ops_from_map(cx, regs, map, ops); + + return guard_ops_are_xml(cx, regs, ops); +} + #endif /* jstracerinlines_h___ */