mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 561954 - Avoid costly deep bail by aborting earlier on bad global prop access (r=jorendorff)
This commit is contained in:
parent
96d0c8e0fa
commit
319ccaa65d
@ -0,0 +1,19 @@
|
||||
/* Touch/init early so global shape doesn't change in loop */
|
||||
var SetOnIter = HOTLOOP - 1;
|
||||
var x = 3;
|
||||
var i = 0;
|
||||
assertEq(true, true);
|
||||
|
||||
for (i = 0; i < SetOnIter + 10; ++i) {
|
||||
x = 3;
|
||||
setGlobalPropIf(i == SetOnIter, 'x', 'pretty');
|
||||
assertEq(x == 'pretty', i == SetOnIter);
|
||||
x = 3;
|
||||
}
|
||||
|
||||
for (i = 0; i < SetOnIter + 10; ++i) {
|
||||
x = 3;
|
||||
defGlobalPropIf(i == SetOnIter, 'x', { value:'pretty' });
|
||||
assertEq(x == 'pretty', i == SetOnIter);
|
||||
x = 3;
|
||||
}
|
@ -435,6 +435,14 @@ IsFunctionObject(const js::Value &v, JSFunction **fun)
|
||||
return b;
|
||||
}
|
||||
|
||||
extern JS_ALWAYS_INLINE bool
|
||||
SameTraceType(const Value &lhs, const Value &rhs)
|
||||
{
|
||||
return SameType(lhs, rhs) &&
|
||||
(lhs.isPrimitive() ||
|
||||
lhs.toObject().isFunction() == rhs.toObject().isFunction());
|
||||
}
|
||||
|
||||
/*
|
||||
* Macro to access the private slot of the function object after the slot is
|
||||
* initialized.
|
||||
|
@ -4458,8 +4458,10 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu
|
||||
}
|
||||
|
||||
/* Store value before calling addProperty, in case the latter GC's. */
|
||||
if (obj->containsSlot(shape->slot))
|
||||
if (obj->containsSlot(shape->slot)) {
|
||||
AbortRecordingIfChangingGlobalSlotType(cx, obj, value, shape->slot);
|
||||
obj->nativeSetSlot(shape->slot, value);
|
||||
}
|
||||
|
||||
/* XXXbe called with lock held */
|
||||
valueCopy = value;
|
||||
@ -4922,6 +4924,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, Value
|
||||
slot = shape->slot;
|
||||
if (slot != SHAPE_INVALID_SLOT) {
|
||||
JS_ASSERT(obj->containsSlot(slot));
|
||||
AbortRecordingIfChangingGlobalSlotType(cx, obj, *vp, slot);
|
||||
|
||||
/* If shape has a stub setter, keep obj locked and just store *vp. */
|
||||
if (shape->hasDefaultSetter()) {
|
||||
|
@ -11514,7 +11514,7 @@ TraceRecorder::record_JSOP_DELNAME()
|
||||
return ARECORD_STOP;
|
||||
}
|
||||
|
||||
JSBool JS_FASTCALL
|
||||
static JSBool JS_FASTCALL
|
||||
DeleteIntKey(JSContext* cx, JSObject* obj, int32 i, JSBool strict)
|
||||
{
|
||||
LeaveTraceIfGlobalObject(cx, obj);
|
||||
@ -11536,7 +11536,7 @@ DeleteIntKey(JSContext* cx, JSObject* obj, int32 i, JSBool strict)
|
||||
JS_DEFINE_CALLINFO_4(extern, BOOL_FAIL, DeleteIntKey, CONTEXT, OBJECT, INT32, BOOL,
|
||||
0, ACCSET_STORE_ANY)
|
||||
|
||||
JSBool JS_FASTCALL
|
||||
static JSBool JS_FASTCALL
|
||||
DeleteStrKey(JSContext* cx, JSObject* obj, JSString* str, JSBool strict)
|
||||
{
|
||||
LeaveTraceIfGlobalObject(cx, obj);
|
||||
|
@ -1839,4 +1839,18 @@ struct TraceVisStateObj {
|
||||
|
||||
#endif /* !JS_TRACER */
|
||||
|
||||
namespace js {
|
||||
|
||||
static JS_INLINE void
|
||||
AbortRecordingIfChangingGlobalSlotType(JSContext *cx, JSObject *obj,
|
||||
const Value &v, unsigned slot)
|
||||
{
|
||||
#ifdef JS_TRACER
|
||||
if (TRACE_RECORDER(cx) && !obj->parent && !SameTraceType(v, obj->nativeGetSlot(slot)))
|
||||
AbortRecording(cx, "Global slot type changed outside tracer supervision");
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jstracer_h___ */
|
||||
|
@ -4204,6 +4204,59 @@ Deserialize(JSContext *cx, uintN argc, jsval *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
SetGlobalPropIf(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc != 3) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "setGlobalPropIf");
|
||||
return false;
|
||||
}
|
||||
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
|
||||
JSBool doSet;
|
||||
if (!JS_ValueToBoolean(cx, argv[0], &doSet))
|
||||
return false;
|
||||
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
if (!doSet)
|
||||
return true;
|
||||
|
||||
jsid id;
|
||||
if (!JS_ValueToId(cx, argv[1], &id))
|
||||
return false;
|
||||
|
||||
JSObject *global = JS_GetGlobalForScopeChain(cx);
|
||||
return global && JS_SetPropertyById(cx, global, id, &argv[2]);
|
||||
}
|
||||
|
||||
JSBool
|
||||
DefGlobalPropIf(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc != 3) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "setGlobalPropIf");
|
||||
return false;
|
||||
}
|
||||
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
|
||||
JSBool doSet;
|
||||
if (!JS_ValueToBoolean(cx, argv[0], &doSet))
|
||||
return false;
|
||||
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
if (!doSet)
|
||||
return true;
|
||||
|
||||
jsid id;
|
||||
if (!JS_ValueToId(cx, argv[1], &id))
|
||||
return false;
|
||||
|
||||
JSObject *global = JS_GetGlobalForScopeChain(cx);
|
||||
JSBool ignore;
|
||||
return global && JS_DefineOwnProperty(cx, global, id, argv[2], &ignore);
|
||||
}
|
||||
|
||||
/* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
|
||||
static JSFunctionSpec shell_functions[] = {
|
||||
JS_FN("version", Version, 0,0),
|
||||
@ -4301,6 +4354,8 @@ static JSFunctionSpec shell_functions[] = {
|
||||
JS_FN("wrap", Wrap, 1,0),
|
||||
JS_FN("serialize", Serialize, 1,0),
|
||||
JS_FN("deserialize", Deserialize, 1,0),
|
||||
JS_FN("setGlobalPropIf",SetGlobalPropIf,3,0),
|
||||
JS_FN("defGlobalPropIf",DefGlobalPropIf,3,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
@ -4429,7 +4484,10 @@ static const char *const shell_help_messages[] = {
|
||||
"parent(obj) Returns the parent of obj.\n",
|
||||
"wrap(obj) Wrap an object into a noop wrapper.\n",
|
||||
"serialize(sd) Serialize sd using JS_WriteStructuredClone. Returns a TypedArray.\n",
|
||||
"deserialize(a) Deserialize data generated by serialize.\n"
|
||||
"deserialize(a) Deserialize data generated by serialize.\n",
|
||||
"setGlobalPropIf(b,id,v) If b, get the global object o and perform o[id] = v.\n",
|
||||
"defGlobalPropIf(b,id,dsc)If b, get the global object o and perform\n"
|
||||
" Object.defineProperty(o, id, dsc).\n"
|
||||
};
|
||||
|
||||
/* Help messages must match shell functions. */
|
||||
|
Loading…
Reference in New Issue
Block a user