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;
|
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
|
* Macro to access the private slot of the function object after the slot is
|
||||||
* initialized.
|
* 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. */
|
/* 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);
|
obj->nativeSetSlot(shape->slot, value);
|
||||||
|
}
|
||||||
|
|
||||||
/* XXXbe called with lock held */
|
/* XXXbe called with lock held */
|
||||||
valueCopy = value;
|
valueCopy = value;
|
||||||
@ -4922,6 +4924,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, Value
|
|||||||
slot = shape->slot;
|
slot = shape->slot;
|
||||||
if (slot != SHAPE_INVALID_SLOT) {
|
if (slot != SHAPE_INVALID_SLOT) {
|
||||||
JS_ASSERT(obj->containsSlot(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 has a stub setter, keep obj locked and just store *vp. */
|
||||||
if (shape->hasDefaultSetter()) {
|
if (shape->hasDefaultSetter()) {
|
||||||
|
@ -11514,7 +11514,7 @@ TraceRecorder::record_JSOP_DELNAME()
|
|||||||
return ARECORD_STOP;
|
return ARECORD_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool JS_FASTCALL
|
static JSBool JS_FASTCALL
|
||||||
DeleteIntKey(JSContext* cx, JSObject* obj, int32 i, JSBool strict)
|
DeleteIntKey(JSContext* cx, JSObject* obj, int32 i, JSBool strict)
|
||||||
{
|
{
|
||||||
LeaveTraceIfGlobalObject(cx, obj);
|
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,
|
JS_DEFINE_CALLINFO_4(extern, BOOL_FAIL, DeleteIntKey, CONTEXT, OBJECT, INT32, BOOL,
|
||||||
0, ACCSET_STORE_ANY)
|
0, ACCSET_STORE_ANY)
|
||||||
|
|
||||||
JSBool JS_FASTCALL
|
static JSBool JS_FASTCALL
|
||||||
DeleteStrKey(JSContext* cx, JSObject* obj, JSString* str, JSBool strict)
|
DeleteStrKey(JSContext* cx, JSObject* obj, JSString* str, JSBool strict)
|
||||||
{
|
{
|
||||||
LeaveTraceIfGlobalObject(cx, obj);
|
LeaveTraceIfGlobalObject(cx, obj);
|
||||||
|
@ -1839,4 +1839,18 @@ struct TraceVisStateObj {
|
|||||||
|
|
||||||
#endif /* !JS_TRACER */
|
#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___ */
|
#endif /* jstracer_h___ */
|
||||||
|
@ -4204,6 +4204,59 @@ Deserialize(JSContext *cx, uintN argc, jsval *vp)
|
|||||||
return true;
|
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. */
|
/* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
|
||||||
static JSFunctionSpec shell_functions[] = {
|
static JSFunctionSpec shell_functions[] = {
|
||||||
JS_FN("version", Version, 0,0),
|
JS_FN("version", Version, 0,0),
|
||||||
@ -4301,6 +4354,8 @@ static JSFunctionSpec shell_functions[] = {
|
|||||||
JS_FN("wrap", Wrap, 1,0),
|
JS_FN("wrap", Wrap, 1,0),
|
||||||
JS_FN("serialize", Serialize, 1,0),
|
JS_FN("serialize", Serialize, 1,0),
|
||||||
JS_FN("deserialize", Deserialize, 1,0),
|
JS_FN("deserialize", Deserialize, 1,0),
|
||||||
|
JS_FN("setGlobalPropIf",SetGlobalPropIf,3,0),
|
||||||
|
JS_FN("defGlobalPropIf",DefGlobalPropIf,3,0),
|
||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4429,7 +4484,10 @@ static const char *const shell_help_messages[] = {
|
|||||||
"parent(obj) Returns the parent of obj.\n",
|
"parent(obj) Returns the parent of obj.\n",
|
||||||
"wrap(obj) Wrap an object into a noop wrapper.\n",
|
"wrap(obj) Wrap an object into a noop wrapper.\n",
|
||||||
"serialize(sd) Serialize sd using JS_WriteStructuredClone. Returns a TypedArray.\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. */
|
/* Help messages must match shell functions. */
|
||||||
|
Loading…
Reference in New Issue
Block a user