mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1022773 - Return value rooting for JS engine, r=terrence
--HG-- extra : rebase_source : 3d0934277a0edb7d3a22c12823b50840de9f6161
This commit is contained in:
parent
36ca527ad7
commit
e193d1faaa
@ -311,7 +311,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFrame
|
||||
esg.lookupInEvalCache(flatStr, callerScript, pc);
|
||||
|
||||
if (!esg.foundScript()) {
|
||||
JSScript *maybeScript;
|
||||
RootedScript maybeScript(cx);
|
||||
unsigned lineno;
|
||||
const char *filename;
|
||||
JSPrincipals *originPrincipals;
|
||||
@ -387,7 +387,7 @@ js::DirectEvalStringFromIon(JSContext *cx,
|
||||
esg.lookupInEvalCache(flatStr, callerScript, pc);
|
||||
|
||||
if (!esg.foundScript()) {
|
||||
JSScript *maybeScript;
|
||||
RootedScript maybeScript(cx);
|
||||
const char *filename;
|
||||
unsigned lineno;
|
||||
JSPrincipals *originPrincipals;
|
||||
|
117
js/src/jsapi.cpp
117
js/src/jsapi.cpp
@ -1109,54 +1109,58 @@ JS_TransplantObject(JSContext *cx, HandleObject origobj, HandleObject target)
|
||||
JS_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
|
||||
JS_ASSERT(!target->is<CrossCompartmentWrapperObject>());
|
||||
|
||||
AutoMaybeTouchDeadZones agc(cx);
|
||||
AutoDisableProxyCheck adpc(cx->runtime());
|
||||
|
||||
JSCompartment *destination = target->compartment();
|
||||
RootedValue origv(cx, ObjectValue(*origobj));
|
||||
RootedObject newIdentity(cx);
|
||||
|
||||
if (origobj->compartment() == destination) {
|
||||
// If the original object is in the same compartment as the
|
||||
// destination, then we know that we won't find a wrapper in the
|
||||
// destination's cross compartment map and that the same
|
||||
// object will continue to work.
|
||||
if (!JSObject::swap(cx, origobj, target))
|
||||
MOZ_CRASH();
|
||||
newIdentity = origobj;
|
||||
} else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
|
||||
// There might already be a wrapper for the original object in
|
||||
// the new compartment. If there is, we use its identity and swap
|
||||
// in the contents of |target|.
|
||||
newIdentity = &p->value().get().toObject();
|
||||
{
|
||||
// Scope to make ~AutoMaybeTouchDeadZones do its GC before the return value is on the stack.
|
||||
AutoMaybeTouchDeadZones agc(cx);
|
||||
AutoDisableProxyCheck adpc(cx->runtime());
|
||||
|
||||
// When we remove origv from the wrapper map, its wrapper, newIdentity,
|
||||
// must immediately cease to be a cross-compartment wrapper. Neuter it.
|
||||
destination->removeWrapper(p);
|
||||
NukeCrossCompartmentWrapper(cx, newIdentity);
|
||||
JSCompartment *destination = target->compartment();
|
||||
|
||||
if (!JSObject::swap(cx, newIdentity, target))
|
||||
MOZ_CRASH();
|
||||
} else {
|
||||
// Otherwise, we use |target| for the new identity object.
|
||||
newIdentity = target;
|
||||
}
|
||||
if (origobj->compartment() == destination) {
|
||||
// If the original object is in the same compartment as the
|
||||
// destination, then we know that we won't find a wrapper in the
|
||||
// destination's cross compartment map and that the same
|
||||
// object will continue to work.
|
||||
if (!JSObject::swap(cx, origobj, target))
|
||||
MOZ_CRASH();
|
||||
newIdentity = origobj;
|
||||
} else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
|
||||
// There might already be a wrapper for the original object in
|
||||
// the new compartment. If there is, we use its identity and swap
|
||||
// in the contents of |target|.
|
||||
newIdentity = &p->value().get().toObject();
|
||||
|
||||
// Now, iterate through other scopes looking for references to the
|
||||
// old object, and update the relevant cross-compartment wrappers.
|
||||
if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
|
||||
MOZ_CRASH();
|
||||
// When we remove origv from the wrapper map, its wrapper, newIdentity,
|
||||
// must immediately cease to be a cross-compartment wrapper. Neuter it.
|
||||
destination->removeWrapper(p);
|
||||
NukeCrossCompartmentWrapper(cx, newIdentity);
|
||||
|
||||
// Lastly, update the original object to point to the new one.
|
||||
if (origobj->compartment() != destination) {
|
||||
RootedObject newIdentityWrapper(cx, newIdentity);
|
||||
AutoCompartment ac(cx, origobj);
|
||||
if (!JS_WrapObject(cx, &newIdentityWrapper))
|
||||
if (!JSObject::swap(cx, newIdentity, target))
|
||||
MOZ_CRASH();
|
||||
} else {
|
||||
// Otherwise, we use |target| for the new identity object.
|
||||
newIdentity = target;
|
||||
}
|
||||
|
||||
// Now, iterate through other scopes looking for references to the
|
||||
// old object, and update the relevant cross-compartment wrappers.
|
||||
if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
|
||||
MOZ_CRASH();
|
||||
JS_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
|
||||
if (!JSObject::swap(cx, origobj, newIdentityWrapper))
|
||||
MOZ_CRASH();
|
||||
origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv);
|
||||
|
||||
// Lastly, update the original object to point to the new one.
|
||||
if (origobj->compartment() != destination) {
|
||||
RootedObject newIdentityWrapper(cx, newIdentity);
|
||||
AutoCompartment ac(cx, origobj);
|
||||
if (!JS_WrapObject(cx, &newIdentityWrapper))
|
||||
MOZ_CRASH();
|
||||
JS_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
|
||||
if (!JSObject::swap(cx, origobj, newIdentityWrapper))
|
||||
MOZ_CRASH();
|
||||
origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv);
|
||||
}
|
||||
}
|
||||
|
||||
// The new identity object might be one of several things. Return it to avoid
|
||||
@ -4639,11 +4643,16 @@ JS::FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token)
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||
|
||||
Maybe<AutoLastFrameCheck> lfc;
|
||||
if (maybecx)
|
||||
lfc.construct(maybecx);
|
||||
|
||||
return HelperThreadState().finishParseTask(maybecx, rt, token);
|
||||
if (maybecx) {
|
||||
RootedScript script(maybecx);
|
||||
{
|
||||
AutoLastFrameCheck lfc(maybecx);
|
||||
script = HelperThreadState().finishParseTask(maybecx, rt, token);
|
||||
}
|
||||
return script;
|
||||
} else {
|
||||
return HelperThreadState().finishParseTask(maybecx, rt, token);
|
||||
}
|
||||
#else
|
||||
MOZ_ASSUME_UNREACHABLE("Off thread compilation is not available.");
|
||||
#endif
|
||||
@ -4717,9 +4726,9 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOption
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
RootedAtom funAtom(cx);
|
||||
AutoLastFrameCheck lfc(cx);
|
||||
|
||||
RootedAtom funAtom(cx);
|
||||
if (name) {
|
||||
funAtom = Atomize(cx, name, strlen(name));
|
||||
if (!funAtom)
|
||||
@ -5135,13 +5144,12 @@ JS::Construct(JSContext *cx, HandleValue fval, const JS::HandleValueArray& args,
|
||||
return InvokeConstructor(cx, fval, args.length(), args.begin(), rval.address());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_New(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
|
||||
static JSObject *
|
||||
JS_NewHelper(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, ctor, inputArgs);
|
||||
AutoLastFrameCheck lfc(cx);
|
||||
|
||||
// This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
|
||||
// is not a simple variation of JSOP_CALL. We have to determine what class
|
||||
@ -5174,6 +5182,17 @@ JS_New(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
|
||||
return &args.rval().toObject();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_New(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
|
||||
{
|
||||
RootedObject obj(cx);
|
||||
{
|
||||
AutoLastFrameCheck lfc(cx);
|
||||
obj = JS_NewHelper(cx, ctor, inputArgs);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSInterruptCallback)
|
||||
JS_SetInterruptCallback(JSRuntime *rt, JSInterruptCallback callback)
|
||||
{
|
||||
|
@ -924,7 +924,7 @@ JSCompartment::removeDebuggeeUnderGC(FreeOp *fop,
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::clearBreakpointsIn(FreeOp *fop, js::Debugger *dbg, JSObject *handler)
|
||||
JSCompartment::clearBreakpointsIn(FreeOp *fop, js::Debugger *dbg, HandleObject handler)
|
||||
{
|
||||
for (gc::ZoneCellIter i(zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
|
@ -425,7 +425,7 @@ struct JSCompartment
|
||||
bool setDebugModeFromC(JSContext *cx, bool b,
|
||||
js::AutoDebugModeInvalidation &invalidate);
|
||||
|
||||
void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JSObject *handler);
|
||||
void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JS::HandleObject handler);
|
||||
void clearTraps(js::FreeOp *fop);
|
||||
|
||||
private:
|
||||
|
@ -1541,7 +1541,7 @@ FunctionConstructor(JSContext *cx, unsigned argc, Value *vp, GeneratorKind gener
|
||||
bool isStarGenerator = generatorKind == StarGenerator;
|
||||
JS_ASSERT(generatorKind != LegacyGenerator);
|
||||
|
||||
JSScript *maybeScript = nullptr;
|
||||
RootedScript maybeScript(cx);
|
||||
const char *filename;
|
||||
unsigned lineno;
|
||||
JSPrincipals *originPrincipals;
|
||||
|
@ -2884,29 +2884,29 @@ js_GetScriptLineExtent(JSScript *script)
|
||||
}
|
||||
|
||||
void
|
||||
js::DescribeScriptedCallerForCompilation(JSContext *cx, JSScript **maybeScript,
|
||||
js::DescribeScriptedCallerForCompilation(JSContext *cx, MutableHandleScript maybeScript,
|
||||
const char **file, unsigned *linenop,
|
||||
uint32_t *pcOffset, JSPrincipals **origin,
|
||||
LineOption opt)
|
||||
{
|
||||
if (opt == CALLED_FROM_JSOP_EVAL) {
|
||||
jsbytecode *pc = nullptr;
|
||||
*maybeScript = cx->currentScript(&pc);
|
||||
maybeScript.set(cx->currentScript(&pc));
|
||||
JS_ASSERT(JSOp(*pc) == JSOP_EVAL || JSOp(*pc) == JSOP_SPREADEVAL);
|
||||
JS_ASSERT(*(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH
|
||||
: JSOP_SPREADEVAL_LENGTH)) == JSOP_LINENO);
|
||||
*file = (*maybeScript)->filename();
|
||||
*file = maybeScript->filename();
|
||||
*linenop = GET_UINT16(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH
|
||||
: JSOP_SPREADEVAL_LENGTH));
|
||||
*pcOffset = pc - (*maybeScript)->code();
|
||||
*origin = (*maybeScript)->originPrincipals();
|
||||
*pcOffset = pc - maybeScript->code();
|
||||
*origin = maybeScript->originPrincipals();
|
||||
return;
|
||||
}
|
||||
|
||||
NonBuiltinFrameIter iter(cx);
|
||||
|
||||
if (iter.done()) {
|
||||
*maybeScript = nullptr;
|
||||
maybeScript.set(nullptr);
|
||||
*file = nullptr;
|
||||
*linenop = 0;
|
||||
*pcOffset = 0;
|
||||
@ -2921,10 +2921,10 @@ js::DescribeScriptedCallerForCompilation(JSContext *cx, JSScript **maybeScript,
|
||||
// These values are only used for introducer fields which are debugging
|
||||
// information and can be safely left null for asm.js frames.
|
||||
if (iter.hasScript()) {
|
||||
*maybeScript = iter.script();
|
||||
*pcOffset = iter.pc() - (*maybeScript)->code();
|
||||
maybeScript.set(iter.script());
|
||||
*pcOffset = iter.pc() - maybeScript->code();
|
||||
} else {
|
||||
*maybeScript = nullptr;
|
||||
maybeScript.set(nullptr);
|
||||
*pcOffset = 0;
|
||||
}
|
||||
}
|
||||
|
@ -2023,7 +2023,7 @@ enum LineOption {
|
||||
};
|
||||
|
||||
extern void
|
||||
DescribeScriptedCallerForCompilation(JSContext *cx, JSScript **maybeScript,
|
||||
DescribeScriptedCallerForCompilation(JSContext *cx, MutableHandleScript maybeScript,
|
||||
const char **file, unsigned *linenop,
|
||||
uint32_t *pcOffset, JSPrincipals **origin,
|
||||
LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);
|
||||
|
@ -2197,7 +2197,7 @@ Debugger::clearAllBreakpoints(JSContext *cx, unsigned argc, Value *vp)
|
||||
THIS_DEBUGGER(cx, argc, vp, "clearAllBreakpoints", args, dbg);
|
||||
for (GlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront())
|
||||
r.front()->compartment()->clearBreakpointsIn(cx->runtime()->defaultFreeOp(),
|
||||
dbg, nullptr);
|
||||
dbg, NullPtr());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2201,7 +2201,7 @@ class ParallelSpewer
|
||||
|
||||
if (cx) {
|
||||
jsbytecode *pc;
|
||||
JSScript *script = cx->currentScript(&pc);
|
||||
RootedScript script(cx, cx->currentScript(&pc));
|
||||
if (script && pc) {
|
||||
NonBuiltinScriptFrameIter iter(cx);
|
||||
if (iter.done()) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "jit/BaselineFrame.h"
|
||||
#include "jit/JitCompartment.h"
|
||||
#endif
|
||||
#include "js/GCAPI.h"
|
||||
#include "vm/Opcodes.h"
|
||||
|
||||
#include "jit/JitFrameIterator-inl.h"
|
||||
@ -31,7 +32,7 @@ using mozilla::PodCopy;
|
||||
|
||||
void
|
||||
InterpreterFrame::initExecuteFrame(JSContext *cx, JSScript *script, AbstractFramePtr evalInFramePrev,
|
||||
const Value &thisv, JSObject &scopeChain, ExecuteType type)
|
||||
const Value &thisv, JSObject &scopeChain, ExecuteType type)
|
||||
{
|
||||
/*
|
||||
* See encoding of ExecuteType. When GLOBAL isn't set, we are executing a
|
||||
@ -666,6 +667,8 @@ FrameIter::FrameIter(ThreadSafeContext *cx, SavedOption savedOption)
|
||||
, ionInlineFrames_(cx, (js::jit::JitFrameIterator*) nullptr)
|
||||
#endif
|
||||
{
|
||||
// settleOnActivation can only GC if principals are given.
|
||||
JS::AutoSuppressGCAnalysis nogc;
|
||||
settleOnActivation();
|
||||
}
|
||||
|
||||
@ -676,6 +679,8 @@ FrameIter::FrameIter(ThreadSafeContext *cx, ContextOption contextOption,
|
||||
, ionInlineFrames_(cx, (js::jit::JitFrameIterator*) nullptr)
|
||||
#endif
|
||||
{
|
||||
// settleOnActivation can only GC if principals are given.
|
||||
JS::AutoSuppressGCAnalysis nogc;
|
||||
settleOnActivation();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user