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