mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 889543 - Use AutoCycleDetector instead of CloneMemory; r=till
--HG-- extra : rebase_source : 394255ac2da12eaea09c8be95847a5d19f6b3b21
This commit is contained in:
parent
92c7a79f42
commit
d01e2ab502
@ -970,25 +970,20 @@ JSRuntime::isSelfHostingCompartment(JSCompartment *comp)
|
||||
return selfHostingGlobal_->compartment() == comp;
|
||||
}
|
||||
|
||||
// CloneMemory maps objects to each other which may be in different
|
||||
// runtimes. This class should only be used within an AutoSuppressGC,
|
||||
// so that issues of managing which objects should be traced can be ignored.
|
||||
typedef HashMap<JSObject *, JSObject *> CloneMemory;
|
||||
static bool
|
||||
CloneValue(JSContext *cx, HandleValue selfHostedValue, MutableHandleValue vp);
|
||||
|
||||
static bool
|
||||
CloneValue(JSContext *cx, const Value &selfHostedValue, MutableHandleValue vp, CloneMemory &clonedObjects);
|
||||
|
||||
static bool
|
||||
GetUnclonedValue(JSContext *cx, JSObject *selfHostedObject, jsid id, Value *vp)
|
||||
GetUnclonedValue(JSContext *cx, HandleObject selfHostedObject, HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
*vp = UndefinedValue();
|
||||
vp.setUndefined();
|
||||
|
||||
if (JSID_IS_INT(id)) {
|
||||
size_t index = JSID_TO_INT(id);
|
||||
if (index < selfHostedObject->getDenseInitializedLength() &&
|
||||
!selfHostedObject->getDenseElement(index).isMagic(JS_ELEMENTS_HOLE))
|
||||
{
|
||||
*vp = selfHostedObject->getDenseElement(JSID_TO_INT(id));
|
||||
vp.set(selfHostedObject->getDenseElement(JSID_TO_INT(id)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -999,30 +994,27 @@ GetUnclonedValue(JSContext *cx, JSObject *selfHostedObject, jsid id, Value *vp)
|
||||
// hosted global which aren't present.
|
||||
if (JSID_IS_STRING(id) && !JSID_TO_STRING(id)->isPermanentAtom()) {
|
||||
JS_ASSERT(selfHostedObject->is<GlobalObject>());
|
||||
gc::AutoSuppressGC suppress(cx);
|
||||
RootedValue value(cx, IdToValue(id));
|
||||
return js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_NO_SUCH_SELF_HOSTED_PROP,
|
||||
JSDVG_IGNORE_STACK, value, NullPtr(), nullptr, nullptr);
|
||||
}
|
||||
|
||||
Shape *shape = selfHostedObject->nativeLookupPure(id);
|
||||
RootedShape shape(cx, selfHostedObject->nativeLookupPure(id));
|
||||
if (!shape) {
|
||||
gc::AutoSuppressGC suppress(cx);
|
||||
RootedValue value(cx, IdToValue(id));
|
||||
return js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_NO_SUCH_SELF_HOSTED_PROP,
|
||||
JSDVG_IGNORE_STACK, value, NullPtr(), nullptr, nullptr);
|
||||
}
|
||||
|
||||
JS_ASSERT(shape->hasSlot() && shape->hasDefaultGetter());
|
||||
*vp = selfHostedObject->getSlot(shape->slot());
|
||||
vp.set(selfHostedObject->getSlot(shape->slot()));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CloneProperties(JSContext *cx, JSObject *selfHostedObject,
|
||||
HandleObject clone, CloneMemory &clonedObjects)
|
||||
CloneProperties(JSContext *cx, HandleObject selfHostedObject, HandleObject clone)
|
||||
{
|
||||
Vector<jsid> ids(cx);
|
||||
AutoIdVector ids(cx);
|
||||
|
||||
for (size_t i = 0; i < selfHostedObject->getDenseInitializedLength(); i++) {
|
||||
if (!selfHostedObject->getDenseElement(i).isMagic(JS_ELEMENTS_HOLE)) {
|
||||
@ -1039,12 +1031,12 @@ CloneProperties(JSContext *cx, JSObject *selfHostedObject,
|
||||
|
||||
RootedId id(cx);
|
||||
RootedValue val(cx);
|
||||
RootedValue selfHostedValue(cx);
|
||||
for (uint32_t i = 0; i < ids.length(); i++) {
|
||||
id = ids[i];
|
||||
Value selfHostedValue;
|
||||
if (!GetUnclonedValue(cx, selfHostedObject, id, &selfHostedValue))
|
||||
return false;
|
||||
if (!CloneValue(cx, selfHostedValue, &val, clonedObjects) ||
|
||||
if (!CloneValue(cx, selfHostedValue, &val) ||
|
||||
!JS_DefinePropertyById(cx, clone, id, val.get(), nullptr, nullptr, 0))
|
||||
{
|
||||
return false;
|
||||
@ -1055,20 +1047,24 @@ CloneProperties(JSContext *cx, JSObject *selfHostedObject,
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
CloneObject(JSContext *cx, JSObject *selfHostedObject, CloneMemory &clonedObjects)
|
||||
CloneObject(JSContext *cx, HandleObject selfHostedObject)
|
||||
{
|
||||
DependentAddPtr<CloneMemory> p(cx, clonedObjects, selfHostedObject);
|
||||
if (p)
|
||||
return p->value();
|
||||
AutoCycleDetector detect(cx, selfHostedObject);
|
||||
if (!detect.init())
|
||||
return nullptr;
|
||||
if (detect.foundCycle()) {
|
||||
JS_ReportError(cx, "SelfHosted cloning cannot handle cyclic object graphs.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RootedObject clone(cx);
|
||||
if (selfHostedObject->is<JSFunction>()) {
|
||||
JSFunction *selfHostedFunction = &selfHostedObject->as<JSFunction>();
|
||||
RootedFunction selfHostedFunction(cx, &selfHostedObject->as<JSFunction>());
|
||||
bool hasName = selfHostedFunction->atom() != nullptr;
|
||||
js::gc::AllocKind kind = hasName
|
||||
? JSFunction::ExtendedFinalizeKind
|
||||
: selfHostedFunction->getAllocKind();
|
||||
clone = CloneFunctionObject(cx, HandleFunction::fromMarkedLocation(&selfHostedFunction),
|
||||
cx->global(), kind, TenuredObject);
|
||||
clone = CloneFunctionObject(cx, selfHostedFunction, cx->global(), kind, TenuredObject);
|
||||
// To be able to re-lazify the cloned function, its name in the
|
||||
// self-hosting compartment has to be stored on the clone.
|
||||
if (clone && hasName)
|
||||
@ -1104,21 +1100,17 @@ CloneObject(JSContext *cx, JSObject *selfHostedObject, CloneMemory &clonedObject
|
||||
}
|
||||
if (!clone)
|
||||
return nullptr;
|
||||
if (!p.add(cx, clonedObjects, selfHostedObject, clone))
|
||||
if (!CloneProperties(cx, selfHostedObject, clone))
|
||||
return nullptr;
|
||||
if (!CloneProperties(cx, selfHostedObject, clone, clonedObjects)) {
|
||||
clonedObjects.remove(selfHostedObject);
|
||||
return nullptr;
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
static bool
|
||||
CloneValue(JSContext *cx, const Value &selfHostedValue, MutableHandleValue vp, CloneMemory &clonedObjects)
|
||||
CloneValue(JSContext *cx, HandleValue selfHostedValue, MutableHandleValue vp)
|
||||
{
|
||||
if (selfHostedValue.isObject()) {
|
||||
JSObject *selfHostedObject = &selfHostedValue.toObject();
|
||||
RootedObject clone(cx, CloneObject(cx, selfHostedObject, clonedObjects));
|
||||
RootedObject selfHostedObject(cx, &selfHostedValue.toObject());
|
||||
JSObject *clone = CloneObject(cx, selfHostedObject);
|
||||
if (!clone)
|
||||
return false;
|
||||
vp.setObject(*clone);
|
||||
@ -1129,25 +1121,25 @@ CloneValue(JSContext *cx, const Value &selfHostedValue, MutableHandleValue vp, C
|
||||
if (!selfHostedValue.toString()->isFlat())
|
||||
MOZ_CRASH();
|
||||
JSFlatString *selfHostedString = &selfHostedValue.toString()->asFlat();
|
||||
RootedString clone(cx, js_NewStringCopyN<CanGC>(cx,
|
||||
JSString *clone = js_NewStringCopyN<CanGC>(cx,
|
||||
selfHostedString->chars(),
|
||||
selfHostedString->length()));
|
||||
selfHostedString->length());
|
||||
if (!clone)
|
||||
return false;
|
||||
vp.setString(clone);
|
||||
} else {
|
||||
MOZ_ASSUME_UNREACHABLE("Self-hosting CloneValue can't clone given value.");
|
||||
MOZ_CRASH("Self-hosting CloneValue can't clone given value.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSRuntime::cloneSelfHostedFunctionScript(JSContext *cx, Handle<PropertyName*> name,
|
||||
Handle<JSFunction*> targetFun)
|
||||
JSRuntime::cloneSelfHostedFunctionScript(JSContext *cx, HandlePropertyName name,
|
||||
HandleFunction targetFun)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
Value funVal;
|
||||
if (!GetUnclonedValue(cx, selfHostingGlobal_, id, &funVal))
|
||||
RootedValue funVal(cx);
|
||||
if (!GetUnclonedValue(cx, HandleObject::fromMarkedLocation(&selfHostingGlobal_), id, &funVal))
|
||||
return false;
|
||||
|
||||
RootedFunction sourceFun(cx, &funVal.toObject().as<JSFunction>());
|
||||
@ -1173,11 +1165,11 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext *cx, Handle<PropertyName*> na
|
||||
}
|
||||
|
||||
bool
|
||||
JSRuntime::cloneSelfHostedValue(JSContext *cx, Handle<PropertyName*> name, MutableHandleValue vp)
|
||||
JSRuntime::cloneSelfHostedValue(JSContext *cx, HandlePropertyName name, MutableHandleValue vp)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
Value selfHostedValue;
|
||||
if (!GetUnclonedValue(cx, selfHostingGlobal_, id, &selfHostedValue))
|
||||
RootedValue selfHostedValue(cx);
|
||||
if (!GetUnclonedValue(cx, HandleObject::fromMarkedLocation(&selfHostingGlobal_), id, &selfHostedValue))
|
||||
return false;
|
||||
|
||||
/*
|
||||
@ -1185,17 +1177,14 @@ JSRuntime::cloneSelfHostedValue(JSContext *cx, Handle<PropertyName*> name, Mutab
|
||||
* means we're currently executing the self-hosting script while
|
||||
* initializing the runtime (see JSRuntime::initSelfHosting).
|
||||
*/
|
||||
if (cx->global() != selfHostingGlobal_) {
|
||||
gc::AutoSuppressGC suppress(cx);
|
||||
CloneMemory clonedObjects(cx);
|
||||
if (!clonedObjects.init() || !CloneValue(cx, selfHostedValue, vp, clonedObjects))
|
||||
return false;
|
||||
} else {
|
||||
if (cx->global() == selfHostingGlobal_) {
|
||||
vp.set(selfHostedValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return CloneValue(cx, selfHostedValue, vp);
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
js::SelfHostedFunction(JSContext *cx, HandlePropertyName propName)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user