mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1083456 - Part 1: Add JS_TraceIncomingCCWs. r=terrence
This commit is contained in:
parent
f92fbf9f5d
commit
d44fae4043
@ -9,8 +9,11 @@
|
||||
|
||||
#include "mozilla/NullPtr.h"
|
||||
|
||||
#include "jsalloc.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/HashTable.h"
|
||||
|
||||
class JS_PUBLIC_API(JSTracer);
|
||||
|
||||
namespace JS {
|
||||
@ -212,6 +215,15 @@ JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind);
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TraceRuntime(JSTracer *trc);
|
||||
|
||||
namespace JS {
|
||||
typedef js::HashSet<Zone *, js::DefaultHasher<Zone *>, js::SystemAllocPolicy> ZoneSet;
|
||||
}
|
||||
|
||||
// Trace every value within |zones| that is wrapped by a cross-compartment
|
||||
// wrapper from a zone that is not an element of |zones|.
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TraceIncomingCCWs(JSTracer *trc, const JS::ZoneSet &zones);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
|
||||
void *thing, JSGCTraceKind kind, bool includeDetails);
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/TracingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
// JS::ubi::Node
|
||||
@ -135,7 +136,6 @@
|
||||
// teach the GC how to root ubi::Nodes, fix up hash tables that use them as
|
||||
// keys, etc.
|
||||
|
||||
|
||||
namespace JS {
|
||||
namespace ubi {
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "gc/GCInternals.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "gc/Zone.h"
|
||||
|
||||
#include "vm/Symbol.h"
|
||||
|
||||
@ -119,6 +120,37 @@ JS_TraceRuntime(JSTracer *trc)
|
||||
TraceRuntime(trc);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_TraceIncomingCCWs(JSTracer *trc, const JS::ZoneSet &zones)
|
||||
{
|
||||
for (js::ZonesIter z(trc->runtime(), SkipAtoms); !z.done(); z.next()) {
|
||||
Zone *zone = z.get();
|
||||
if (!zone || zones.has(zone))
|
||||
continue;
|
||||
|
||||
for (js::CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
|
||||
JSCompartment *comp = c.get();
|
||||
if (!comp)
|
||||
continue;
|
||||
|
||||
for (JSCompartment::WrapperEnum e(comp); !e.empty(); e.popFront()) {
|
||||
const CrossCompartmentKey &key = e.front().key();
|
||||
// StringWrappers are just used to avoid copying strings across
|
||||
// zones multiple times, and don't hold a strong reference.
|
||||
if (key.kind == CrossCompartmentKey::StringWrapper)
|
||||
continue;
|
||||
// Ignore CCWs whose wrapped value doesn't live in our given set
|
||||
// of zones.
|
||||
if (!zones.has(static_cast<JSObject *>(key.wrapped)->zone()))
|
||||
continue;
|
||||
|
||||
void *thing = key.wrapped;
|
||||
trc->callback(trc, &thing, GetGCThingTraceKind(key.wrapped));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
CountDecimalDigits(size_t num)
|
||||
{
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "gc/FindSCCs.h"
|
||||
#include "gc/GCRuntime.h"
|
||||
#include "js/TracingAPI.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -259,7 +260,6 @@ struct Zone : public JS::shadow::Zone,
|
||||
//
|
||||
// This is used during GC while calculating zone groups to record edges that
|
||||
// can't be determined by examining this zone by itself.
|
||||
typedef js::HashSet<Zone *, js::DefaultHasher<Zone *>, js::SystemAllocPolicy> ZoneSet;
|
||||
ZoneSet gcZoneGroupEdges;
|
||||
|
||||
// Malloc counter to measure memory pressure for GC scheduling. It runs from
|
||||
|
@ -37,6 +37,7 @@ UNIFIED_SOURCES += [
|
||||
'testGCExactRooting.cpp',
|
||||
'testGCFinalizeCallback.cpp',
|
||||
'testGCHeapPostBarriers.cpp',
|
||||
'testGCMarking.cpp',
|
||||
'testGCOutOfMemory.cpp',
|
||||
'testGCStoreBufferRemoval.cpp',
|
||||
'testHashTable.cpp',
|
||||
|
79
js/src/jsapi-tests/testGCMarking.cpp
Normal file
79
js/src/jsapi-tests/testGCMarking.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
class CCWTestTracer : public JSTracer {
|
||||
static void staticCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind) {
|
||||
static_cast<CCWTestTracer *>(trc)->callback(thingp, kind);
|
||||
}
|
||||
|
||||
void callback(void **thingp, JSGCTraceKind kind) {
|
||||
numberOfThingsTraced++;
|
||||
|
||||
printf("*thingp = %p\n", *thingp);
|
||||
printf("*expectedThingp = %p\n", *expectedThingp);
|
||||
|
||||
printf("kind = %d\n", kind);
|
||||
printf("expectedKind = %d\n", expectedKind);
|
||||
|
||||
if (*thingp != *expectedThingp || kind != expectedKind)
|
||||
okay = false;
|
||||
}
|
||||
|
||||
public:
|
||||
bool okay;
|
||||
size_t numberOfThingsTraced;
|
||||
void **expectedThingp;
|
||||
JSGCTraceKind expectedKind;
|
||||
|
||||
CCWTestTracer(JSContext *cx, void **expectedThingp, JSGCTraceKind expectedKind)
|
||||
: JSTracer(JS_GetRuntime(cx), staticCallback),
|
||||
okay(true),
|
||||
numberOfThingsTraced(0),
|
||||
expectedThingp(expectedThingp),
|
||||
expectedKind(expectedKind)
|
||||
{ }
|
||||
};
|
||||
|
||||
BEGIN_TEST(testTracingIncomingCCWs)
|
||||
{
|
||||
// Get two globals, in two different zones.
|
||||
|
||||
JS::RootedObject global1(cx, JS::CurrentGlobalOrNull(cx));
|
||||
CHECK(global1);
|
||||
JS::RootedObject global2(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
|
||||
JS::FireOnNewGlobalHook));
|
||||
CHECK(global2);
|
||||
CHECK(global1->zone() != global2->zone());
|
||||
|
||||
// Define an object in one zone, that is wrapped by a CCW in another zone.
|
||||
|
||||
JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
|
||||
CHECK(obj->zone() == global1->zone());
|
||||
|
||||
JSAutoCompartment ac(cx, global2);
|
||||
JS::RootedObject wrapper(cx, obj);
|
||||
CHECK(JS_WrapObject(cx, &wrapper));
|
||||
JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
|
||||
CHECK(JS_SetProperty(cx, global2, "ccw", v));
|
||||
|
||||
// Ensure that |JS_TraceIncomingCCWs| finds the object wrapped by the CCW.
|
||||
|
||||
JS::ZoneSet zones;
|
||||
CHECK(zones.init());
|
||||
CHECK(zones.put(global1->zone()));
|
||||
|
||||
void *thing = obj.get();
|
||||
CCWTestTracer trc(cx, &thing, JSTRACE_OBJECT);
|
||||
JS_TraceIncomingCCWs(&trc, zones);
|
||||
CHECK(trc.numberOfThingsTraced == 1);
|
||||
CHECK(trc.okay);
|
||||
|
||||
return true;
|
||||
}
|
||||
END_TEST(testTracingIncomingCCWs)
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "gc/Marking.h"
|
||||
#include "js/Debug.h"
|
||||
#include "js/TracingAPI.h"
|
||||
#include "js/UbiNode.h"
|
||||
#include "js/UbiNodeTraverse.h"
|
||||
#include "vm/Debugger.h"
|
||||
@ -304,7 +305,7 @@ namespace dbg {
|
||||
// Common data for census traversals.
|
||||
struct Census {
|
||||
JSContext * const cx;
|
||||
Zone::ZoneSet debuggeeZones;
|
||||
JS::ZoneSet debuggeeZones;
|
||||
Zone *atomsZone;
|
||||
|
||||
explicit Census(JSContext *cx) : cx(cx), atomsZone(nullptr) { }
|
||||
|
Loading…
Reference in New Issue
Block a user