Bug 1291476 - Baldr: add Instance-to-WasmInstanceObject edge (r=terrence)

MozReview-Commit-ID: EgX6342KaHJ
This commit is contained in:
Luke Wagner 2016-08-03 08:30:42 -05:00
parent b081892756
commit 043c7d716a
9 changed files with 38 additions and 38 deletions

View File

@ -29,7 +29,6 @@ using namespace wasm;
Compartment::Compartment(Zone* zone)
: mutatingInstances_(false),
instanceObjects_(zone, InstanceObjectSet()),
activationCount_(0),
profilingEnabled_(false)
{}
@ -37,7 +36,6 @@ Compartment::Compartment(Zone* zone)
Compartment::~Compartment()
{
MOZ_ASSERT(activationCount_ == 0);
MOZ_ASSERT(!instanceObjects_.initialized() || instanceObjects_.empty());
MOZ_ASSERT(instances_.empty());
MOZ_ASSERT(!mutatingInstances_);
}
@ -63,8 +61,10 @@ Compartment::trace(JSTracer* trc)
// unreachable while executing on the stack. Since wasm does not otherwise
// scan the stack during GC to identify live instances, we mark all instance
// objects live if there is any running wasm in the compartment.
if (activationCount_)
instanceObjects_.get().trace(trc);
if (activationCount_) {
for (Instance* i : instances_)
i->trace(trc);
}
}
bool
@ -76,16 +76,6 @@ Compartment::registerInstance(JSContext* cx, HandleWasmInstanceObject instanceOb
if (!instance.ensureProfilingState(cx, profilingEnabled_))
return false;
if (!instanceObjects_.initialized() && !instanceObjects_.init()) {
ReportOutOfMemory(cx);
return false;
}
if (!instanceObjects_.putNew(instanceObj)) {
ReportOutOfMemory(cx);
return false;
}
size_t index;
if (BinarySearchIf(instances_, 0, instances_.length(), InstanceComparator(instance), &index))
MOZ_CRASH("duplicate registration");
@ -182,5 +172,5 @@ Compartment::profilingEnabled() const
void
Compartment::addSizeOfExcludingThis(MallocSizeOf mallocSizeOf, size_t* compartmentTables)
{
*compartmentTables += instanceObjects_.sizeOfExcludingThis(mallocSizeOf);
*compartmentTables += instances_.sizeOfExcludingThis(mallocSizeOf);
}

View File

@ -28,6 +28,7 @@ class WasmActivation;
namespace wasm {
class Code;
typedef Vector<Instance*, 0, SystemAllocPolicy> InstanceVector;
// wasm::Compartment lives in JSCompartment and contains the wasm-related
// per-compartment state. wasm::Compartment tracks every live instance in the
@ -36,17 +37,10 @@ class Code;
class Compartment
{
using InstanceObjectSet = GCHashSet<ReadBarriered<WasmInstanceObject*>,
MovableCellHasher<ReadBarriered<WasmInstanceObject*>>,
SystemAllocPolicy>;
using WeakInstanceObjectSet = JS::WeakCache<InstanceObjectSet>;
using InstanceVector = Vector<Instance*, 0, SystemAllocPolicy>;
InstanceVector instances_;
volatile bool mutatingInstances_;
WeakInstanceObjectSet instanceObjects_;
size_t activationCount_;
bool profilingEnabled_;
InstanceVector instances_;
volatile bool mutatingInstances_;
size_t activationCount_;
bool profilingEnabled_;
friend class js::WasmActivation;
@ -76,11 +70,12 @@ class Compartment
bool registerInstance(JSContext* cx, HandleWasmInstanceObject instanceObj);
void unregisterInstance(Instance& instance);
// Return a weak set of all live instances in the compartment. Accessing
// objects of the set will trigger a read-barrier which will mark the
// object.
// Return a vector of all live instances in the compartment. The lifetime of
// these Instances is determined by their owning WasmInstanceObject.
// Note that accessing instances()[i]->object() triggers a read barrier
// since instances() is effectively a weak list.
const WeakInstanceObjectSet& instanceObjects() const { return instanceObjects_; }
const InstanceVector& instances() const { return instances_; }
// This methods returns the wasm::Code containing the given pc, if any
// exists in the compartment.

View File

@ -271,12 +271,14 @@ Instance::callImport_f64(Instance* instance, int32_t funcImportIndex, int32_t ar
}
Instance::Instance(JSContext* cx,
Handle<WasmInstanceObject*> object,
UniqueCode code,
HandleWasmMemoryObject memory,
SharedTableVector&& tables,
Handle<FunctionVector> funcImports,
const ValVector& globalImports)
: compartment_(cx->compartment()),
object_(object),
code_(Move(code)),
memory_(memory),
tables_(Move(tables))
@ -380,8 +382,16 @@ Instance::~Instance()
void
Instance::trace(JSTracer* trc)
{
// Ordinarily, an Instance is only marked via WasmInstanceObject's trace
// hook and so this TraceEdge() call is only useful to update the pointer on
// moving GC. However, if wasm is active in a wasm::Compartment during GC,
// all Instances are marked directly via Instance::trace() making this a
// necessary strong edge.
TraceEdge(trc, &object_, "wasm object");
for (const FuncImport& fi : metadata().funcImports)
TraceNullableEdge(trc, &funcImportToExit(fi).fun, "wasm function import");
TraceNullableEdge(trc, &memory_, "wasm buffer");
}

View File

@ -26,7 +26,6 @@
namespace js {
class WasmActivation;
class WasmInstanceObject;
namespace wasm {
@ -40,6 +39,7 @@ namespace wasm {
class Instance
{
JSCompartment* const compartment_;
ReadBarrieredWasmInstanceObject object_;
const UniqueCode code_;
GCPtrWasmMemoryObject memory_;
SharedTableVector tables_;
@ -66,6 +66,7 @@ class Instance
public:
Instance(JSContext* cx,
Handle<WasmInstanceObject*> object,
UniqueCode code,
HandleWasmMemoryObject memory,
SharedTableVector&& tables,
@ -86,6 +87,12 @@ class Instance
SharedMem<uint8_t*> memoryBase() const;
size_t memoryLength() const;
// This method returns a pointer to the GC object that owns this Instance.
// Instances may be reached via weak edges (e.g., Compartment::instances_)
// so this perform a read-barrier on the returned object.
WasmInstanceObject* object() const { return object_; }
// Execute the given export given the JS call arguments, storing the return
// value in args.rval.

View File

@ -729,6 +729,7 @@ Module::instantiate(JSContext* cx,
return false;
auto instance = cx->make_unique<Instance>(cx,
instanceObj,
Move(code),
memory,
Move(tables),

View File

@ -907,6 +907,7 @@ class ScriptSourceObject;
class Shape;
class BaseShape;
class UnownedBaseShape;
class WasmInstanceObject;
namespace jit {
class JitCode;
} // namespace jit
@ -958,6 +959,7 @@ typedef ReadBarriered<Shape*> ReadBarrieredShape;
typedef ReadBarriered<jit::JitCode*> ReadBarrieredJitCode;
typedef ReadBarriered<ObjectGroup*> ReadBarrieredObjectGroup;
typedef ReadBarriered<JS::Symbol*> ReadBarrieredSymbol;
typedef ReadBarriered<WasmInstanceObject*> ReadBarrieredWasmInstanceObject;
typedef ReadBarriered<Value> ReadBarrieredValue;

View File

@ -50,7 +50,6 @@ class Shape;
class SharedArrayBufferObject;
class StructTypeDescr;
class UnownedBaseShape;
class WasmInstanceObject;
class WasmMemoryObject;
namespace jit {
class JitCode;

View File

@ -927,7 +927,6 @@ JSCompartment::clearTables()
MOZ_ASSERT(!debugScopes);
MOZ_ASSERT(enumerators->next() == enumerators);
MOZ_ASSERT(regExps.empty());
MOZ_ASSERT(!wasm.instanceObjects().initialized() || wasm.instanceObjects().empty());
objectGroups.clearTables();
if (baseShapes.initialized())

View File

@ -4167,11 +4167,8 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery
// TODOshu: Until such time that wasm modules are real ES6 modules,
// unconditionally consider all wasm toplevel instance scripts.
for (WeakGlobalObjectSet::Range r = debugger->allDebuggees(); !r.empty(); r.popFront()) {
auto& instanceObjects = r.front()->compartment()->wasm.instanceObjects();
if (!instanceObjects.initialized())
continue;
for (auto i = instanceObjects.all(); !i.empty(); i.popFront())
consider(i.front());
for (wasm::Instance* instance : r.front()->compartment()->wasm.instances())
consider(instance->object());
}
return true;