Bug 889543 - Use AutoCycleDetector instead of CloneMemory; r=till

--HG--
extra : rebase_source : 394255ac2da12eaea09c8be95847a5d19f6b3b21
This commit is contained in:
Terrence Cole 2014-03-11 09:00:16 -07:00
parent 92c7a79f42
commit d01e2ab502

View File

@ -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,
selfHostedString->chars(),
selfHostedString->length()));
JSString *clone = js_NewStringCopyN<CanGC>(cx,
selfHostedString->chars(),
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,15 +1177,12 @@ 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 true;
return CloneValue(cx, selfHostedValue, vp);
}
JSFunction *