Bug 556315 part 2 - JSObject::getGlobal() and JSStackFrame::getThisObject(). r=gal.

--HG--
extra : rebase_source : 103e73537d3c2f537a914b69a620136451a664ba
This commit is contained in:
Jason Orendorff 2010-03-31 17:57:03 -05:00
Родитель 80b07733e2
Коммит 54b9b7f300
8 изменённых файлов: 46 добавлений и 40 удалений

Просмотреть файл

@ -1685,9 +1685,7 @@ JS_GetScopeChain(JSContext *cx)
JS_PUBLIC_API(JSObject *)
JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
{
while (JSObject *parent = obj->getParent())
obj = parent;
return obj;
return obj->getGlobal();
}
JS_PUBLIC_API(jsval)

Просмотреть файл

@ -1227,10 +1227,7 @@ JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp)
JS_PUBLIC_API(JSObject *)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp)
{
if (!(fp->flags & JSFRAME_COMPUTED_THIS) && fp->argv)
fp->thisv = OBJECT_TO_JSVAL(js_ComputeThis(cx, fp->argv));
return JSVAL_TO_OBJECT(fp->thisv);
return fp->getThisObject(cx);
}
JS_PUBLIC_API(JSFunction *)

Просмотреть файл

@ -407,7 +407,7 @@ js_ComputeGlobalThis(JSContext *cx, jsval *argv)
!JSVAL_TO_OBJECT(argv[-2])->getParent()) {
thisp = cx->globalObject;
} else {
thisp = JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(argv[-2]));
thisp = JSVAL_TO_OBJECT(argv[-2])->getGlobal();
}
return CallThisObjectHook(cx, thisp, argv);

Просмотреть файл

@ -167,6 +167,8 @@ struct JSStackFrame {
/* Short for: varobj(cx->activeCallStack()). */
JSObject *varobj(JSContext *cx);
inline JSObject *getThisObject(JSContext *cx);
};
#ifdef __cplusplus
@ -274,21 +276,6 @@ extern const uint16 js_PrimitiveTestFlags[];
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \
js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1]))
#ifdef __cplusplus /* Aargh, libgjs, bug 492720. */
static JS_INLINE JSObject *
js_ComputeThisForFrame(JSContext *cx, JSStackFrame *fp)
{
if (fp->flags & JSFRAME_COMPUTED_THIS)
return JSVAL_TO_OBJECT(fp->thisv); /* JSVAL_COMPUTED_THIS invariant */
JSObject* obj = js_ComputeThis(cx, fp->argv);
if (!obj)
return NULL;
fp->thisv = OBJECT_TO_JSVAL(obj);
fp->flags |= JSFRAME_COMPUTED_THIS;
return obj;
}
#endif
/*
* NB: js_Invoke requires that cx is currently running JS (i.e., that cx->fp
* is non-null), and that vp points to the callee, |this| parameter, and
@ -472,4 +459,17 @@ js_MeterSlotOpcode(JSOp op, uint32 slot);
JS_END_EXTERN_C
inline JSObject *
JSStackFrame::getThisObject(JSContext *cx)
{
if (flags & JSFRAME_COMPUTED_THIS)
return JSVAL_TO_OBJECT(thisv); /* JSVAL_COMPUTED_THIS invariant */
JSObject* obj = js_ComputeThis(cx, argv);
if (!obj)
return NULL;
thisv = OBJECT_TO_JSVAL(obj);
flags |= JSFRAME_COMPUTED_THIS;
return obj;
}
#endif /* jsinterp_h___ */

Просмотреть файл

@ -1352,7 +1352,7 @@ obj_eval(JSContext *cx, uintN argc, jsval *vp)
* with object to maintain invariants in the engine (see bug 520164).
*/
if (scopeobj->getParent()) {
JSObject *global = JS_GetGlobalForObject(cx, scopeobj);
JSObject *global = scopeobj->getGlobal();
withGuard.obj = js_NewWithObject(cx, scopeobj, global, 0);
if (!withGuard.obj)
return JS_FALSE;
@ -6746,6 +6746,15 @@ js_GetWrappedObject(JSContext *cx, JSObject *obj)
return obj;
}
JSObject *
JSObject::getGlobal()
{
JSObject *obj = this;
while (JSObject *parent = obj->getParent())
obj = parent;
return obj;
}
bool
JSObject::isCallable()
{

Просмотреть файл

@ -356,6 +356,8 @@ struct JSObject {
JS_CALL_OBJECT_TRACER(trc, parent, "__parent__");
}
JSObject *getGlobal();
void *getPrivate() const {
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
jsval v = fslots[JSSLOT_PRIVATE];

Просмотреть файл

@ -1420,7 +1420,7 @@ BEGIN_CASE(JSOP_GVARINC)
#define COMPUTE_THIS(cx, fp, obj) \
JS_BEGIN_MACRO \
if (!(obj = js_ComputeThisForFrame(cx, fp))) \
if (!(obj = (fp)->getThisObject(cx))) \
goto error; \
JS_END_MACRO

Просмотреть файл

@ -1112,7 +1112,7 @@ GlobalSlotHash(JSContext* cx, unsigned slot)
fp = fp->down;
HashAccum(h, uintptr_t(fp->script), ORACLE_MASK);
HashAccum(h, uintptr_t(OBJ_SHAPE(JS_GetGlobalForObject(cx, fp->scopeChain))), ORACLE_MASK);
HashAccum(h, uintptr_t(OBJ_SHAPE(fp->scopeChain->getGlobal())), ORACLE_MASK);
HashAccum(h, uintptr_t(slot), ORACLE_MASK);
return int(h);
}
@ -1812,7 +1812,7 @@ template <typename Visitor>
static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
VisitGlobalSlots(Visitor &visitor, JSContext *cx, SlotList &gslots)
{
VisitGlobalSlots(visitor, cx, JS_GetGlobalForObject(cx, cx->fp->scopeChain),
VisitGlobalSlots(visitor, cx, cx->fp->scopeChain->getGlobal(),
gslots.length(), gslots.data());
}
@ -1831,7 +1831,7 @@ static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
VisitSlots(Visitor& visitor, JSContext* cx, unsigned callDepth,
unsigned ngslots, uint16* gslots)
{
VisitSlots(visitor, cx, JS_GetGlobalForObject(cx, cx->fp->scopeChain),
VisitSlots(visitor, cx, cx->fp->scopeChain->getGlobal(),
callDepth, ngslots, gslots);
}
@ -1849,7 +1849,7 @@ static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
VisitSlots(Visitor &visitor, JSContext *cx, unsigned callDepth,
const SlotList& slots)
{
VisitSlots(visitor, cx, JS_GetGlobalForObject(cx, cx->fp->scopeChain),
VisitSlots(visitor, cx, cx->fp->scopeChain->getGlobal(),
callDepth, slots.length(), slots.data());
}
@ -2166,7 +2166,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag
generatedSpecializedNative(),
tempTypeMap(cx)
{
JS_ASSERT(globalObj == JS_GetGlobalForObject(cx, cx->fp->scopeChain));
JS_ASSERT(globalObj == cx->fp->scopeChain->getGlobal());
JS_ASSERT(cx->fp->regs->pc == (jsbytecode*)fragment->ip);
fragment->lirbuf = lirbuf;
@ -5908,7 +5908,7 @@ JS_REQUIRES_STACK bool
TraceRecorder::recordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCallCount)
{
#ifdef JS_THREADSAFE
if (OBJ_SCOPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain))->title.ownercx != cx) {
if (OBJ_SCOPE(cx->fp->scopeChain->getGlobal())->title.ownercx != cx) {
AbortRecording(cx, "Global object not owned by this context");
return false; /* we stay away from shared global objects */
}
@ -5931,7 +5931,7 @@ TraceRecorder::recordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCall
* Make sure the shape of the global object still matches (this might flush
* the JIT cache).
*/
JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
JSObject* globalObj = cx->fp->scopeChain->getGlobal();
uint32 globalShape = -1;
SlotList* globalSlots = NULL;
if (!CheckGlobalObjectShape(cx, tm, globalObj, &globalShape, &globalSlots)) {
@ -6399,7 +6399,7 @@ ExecuteTrace(JSContext* cx, Fragment* f, InterpState& state)
static JS_REQUIRES_STACK JS_ALWAYS_INLINE bool
ScopeChainCheck(JSContext* cx, TreeFragment* f)
{
JS_ASSERT(f->globalObj == JS_GetGlobalForObject(cx, cx->fp->scopeChain));
JS_ASSERT(f->globalObj == cx->fp->scopeChain->getGlobal());
/*
* The JIT records and expects to execute with two scope-chain
@ -6896,7 +6896,7 @@ MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount, RecordReason reason)
* Make sure the shape of the global object still matches (this might flush
* the JIT cache).
*/
JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
JSObject* globalObj = cx->fp->scopeChain->getGlobal();
uint32 globalShape = -1;
SlotList* globalSlots = NULL;
@ -9423,7 +9423,7 @@ JS_REQUIRES_STACK RecordingStatus
TraceRecorder::getThis(LIns*& this_ins)
{
/*
* js_ComputeThisForFrame updates cx->fp->argv[-1], so sample it into 'original' first.
* JSStackFrame::getThisObject updates cx->fp->argv[-1], so sample it into 'original' first.
*/
jsval original = JSVAL_NULL;
if (cx->fp->argv) {
@ -9435,9 +9435,9 @@ TraceRecorder::getThis(LIns*& this_ins)
}
}
JSObject* thisObj = js_ComputeThisForFrame(cx, cx->fp);
JSObject* thisObj = cx->fp->getThisObject(cx);
if (!thisObj)
RETURN_ERROR("js_ComputeThisForFrame failed");
RETURN_ERROR("fp->getThisObject failed");
/* In global code, bake in the global object as 'this' object. */
if (!cx->fp->callee()) {
@ -9459,7 +9459,7 @@ TraceRecorder::getThis(LIns*& this_ins)
* a null value in argv[-1], this trace will only match if we see null at
* runtime as well. Bake in the global object as 'this' object, updating
* the tracker as well. We can only detect this condition prior to calling
* js_ComputeThisForFrame, since it updates the interpreter's copy of
* JSStackFrame::getThisObject, since it updates the interpreter's copy of
* argv[-1].
*/
JSClass* clasp = NULL;;
@ -9811,7 +9811,7 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount)
* Make sure the shape of the global object still matches (this might
* flush the JIT cache).
*/
JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
JSObject* globalObj = cx->fp->scopeChain->getGlobal();
uint32 globalShape = -1;
SlotList* globalSlots = NULL;
if (!CheckGlobalObjectShape(cx, traceMonitor, globalObj, &globalShape, &globalSlots))
@ -12425,7 +12425,7 @@ TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc,
return RECORD_CONTINUE;
}
if (JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(fval)) != globalObj)
if (JSVAL_TO_OBJECT(fval)->getGlobal() != globalObj)
RETURN_STOP("JSOP_CALL or JSOP_NEW crosses global scopes");
JSStackFrame* fp = cx->fp;