forked from mirrors/gecko-dev
Use the garbage collector to manage code (bug 670816 part 4, r=billm).
--HG-- extra : rebase_source : 8c93cd92ecd1266e12d6b42afadd63bcef3bac93
This commit is contained in:
parent
4a035b6b2f
commit
1271075287
11 changed files with 153 additions and 23 deletions
|
|
@ -59,12 +59,17 @@
|
||||||
# include "arm/Lowering-arm.h"
|
# include "arm/Lowering-arm.h"
|
||||||
# include "arm/CodeGenerator-arm.h"
|
# include "arm/CodeGenerator-arm.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "jsgcmark.h"
|
||||||
|
#include "jsgcinlines.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::ion;
|
using namespace js::ion;
|
||||||
|
|
||||||
IonOptions ion::js_IonOptions;
|
IonOptions ion::js_IonOptions;
|
||||||
|
|
||||||
|
// Assert that IonCode is gc::Cell aligned.
|
||||||
|
JS_STATIC_ASSERT(sizeof(IonCode) % gc::Cell::CellSize == 0);
|
||||||
|
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
static bool IonTLSInitialized = false;
|
static bool IonTLSInitialized = false;
|
||||||
static PRUintn IonTLSIndex;
|
static PRUintn IonTLSIndex;
|
||||||
|
|
@ -128,15 +133,31 @@ ion::SetIonContext(IonContext *ctx)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
IonCode *
|
||||||
|
IonCode::New(JSContext *cx, uint8 *code, uint32 size, JSC::ExecutablePool *pool)
|
||||||
|
{
|
||||||
|
IonCode *codeObj = NewGCThing<IonCode>(cx, gc::FINALIZE_IONCODE, sizeof(IonCode));
|
||||||
|
if (!codeObj) {
|
||||||
|
pool->release();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
new (codeObj) IonCode(code, size, pool);
|
||||||
|
return codeObj;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IonCode::release()
|
IonCode::finalize(JSContext *cx)
|
||||||
{
|
{
|
||||||
if (pool_)
|
if (pool_)
|
||||||
pool_->release();
|
pool_->release();
|
||||||
#ifdef DEBUG
|
}
|
||||||
pool_ = NULL;
|
|
||||||
code_ = NULL;
|
void
|
||||||
#endif
|
IonScript::trace(JSTracer *trc, JSScript *script)
|
||||||
|
{
|
||||||
|
if (method)
|
||||||
|
MarkIonCode(trc, method, "method");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -145,7 +166,6 @@ IonScript::Destroy(JSContext *cx, JSScript *script)
|
||||||
if (!script->ion || script->ion == ION_DISABLED_SCRIPT)
|
if (!script->ion || script->ion == ION_DISABLED_SCRIPT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
script->ion->method.release();
|
|
||||||
cx->free_(script->ion);
|
cx->free_(script->ion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,6 @@ struct IonOptions
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ION_DISABLED_SCRIPT ((IonScript *)0x1)
|
|
||||||
|
|
||||||
enum MethodStatus
|
enum MethodStatus
|
||||||
{
|
{
|
||||||
Method_CantCompile,
|
Method_CantCompile,
|
||||||
|
|
|
||||||
|
|
@ -49,37 +49,53 @@ namespace JSC {
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace ion {
|
namespace ion {
|
||||||
|
|
||||||
class IonCode
|
class IonCode : public gc::Cell
|
||||||
{
|
{
|
||||||
uint8 *code_;
|
uint8 *code_;
|
||||||
size_t size_;
|
uint32 size_;
|
||||||
JSC::ExecutablePool *pool_;
|
JSC::ExecutablePool *pool_;
|
||||||
|
uint32 padding_;
|
||||||
|
|
||||||
public:
|
|
||||||
IonCode()
|
IonCode()
|
||||||
: code_(NULL),
|
: code_(NULL),
|
||||||
pool_(NULL)
|
pool_(NULL)
|
||||||
{ }
|
{ }
|
||||||
IonCode(uint8 *code, size_t size, JSC::ExecutablePool *pool)
|
IonCode(uint8 *code, uint32 size, JSC::ExecutablePool *pool)
|
||||||
: code_(code),
|
: code_(code),
|
||||||
size_(size),
|
size_(size),
|
||||||
pool_(pool)
|
pool_(pool)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
public:
|
||||||
uint8 *code() const {
|
uint8 *code() const {
|
||||||
return code_;
|
return code_;
|
||||||
}
|
}
|
||||||
size_t size() const {
|
uint32 size() const {
|
||||||
return size_;
|
return size_;
|
||||||
}
|
}
|
||||||
void release();
|
void finalize(JSContext *cx);
|
||||||
|
|
||||||
|
// Allocates a new IonCode object which will be managed by the GC. If no
|
||||||
|
// object can be allocated, NULL is returned. On failure, |pool| is
|
||||||
|
// automatically released, so the code may be freed.
|
||||||
|
static IonCode *New(JSContext *cx, uint8 *code, uint32 size, JSC::ExecutablePool *pool);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ION_DISABLED_SCRIPT ((IonScript *)0x1)
|
||||||
|
|
||||||
// An IonScript attaches Ion-generated information to a JSScript.
|
// An IonScript attaches Ion-generated information to a JSScript.
|
||||||
struct IonScript
|
struct IonScript
|
||||||
{
|
{
|
||||||
IonCode method;
|
IonCode *method;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void trace(JSTracer *trc, JSScript *script);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Trace(JSTracer *trc, JSScript *script) {
|
||||||
|
if (script->ion && script->ion != ION_DISABLED_SCRIPT)
|
||||||
|
script->ion->trace(trc, script);
|
||||||
|
}
|
||||||
static void Destroy(JSContext *cx, JSScript *script);
|
static void Destroy(JSContext *cx, JSScript *script);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -402,6 +402,7 @@ struct JSRuntime {
|
||||||
void *gcMarkStackRopes[js::ROPES_MARK_STACK_SIZE / sizeof(void *)];
|
void *gcMarkStackRopes[js::ROPES_MARK_STACK_SIZE / sizeof(void *)];
|
||||||
void *gcMarkStackXMLs[js::XML_MARK_STACK_SIZE / sizeof(void *)];
|
void *gcMarkStackXMLs[js::XML_MARK_STACK_SIZE / sizeof(void *)];
|
||||||
void *gcMarkStackLarges[js::LARGE_MARK_STACK_SIZE / sizeof(void *)];
|
void *gcMarkStackLarges[js::LARGE_MARK_STACK_SIZE / sizeof(void *)];
|
||||||
|
void *gcMarkStackIonCode[js::IONCODE_MARK_STACK_SIZE / sizeof(void *)];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compartment that triggered GC. If more than one Compatment need GC,
|
* Compartment that triggered GC. If more than one Compatment need GC,
|
||||||
|
|
|
||||||
|
|
@ -496,6 +496,7 @@ struct JS_FRIEND_API(JSCompartment) {
|
||||||
void finalizeObjectArenaLists(JSContext *cx);
|
void finalizeObjectArenaLists(JSContext *cx);
|
||||||
void finalizeStringArenaLists(JSContext *cx);
|
void finalizeStringArenaLists(JSContext *cx);
|
||||||
void finalizeShapeArenaLists(JSContext *cx);
|
void finalizeShapeArenaLists(JSContext *cx);
|
||||||
|
void finalizeIonCodeArenaLists(JSContext *cx);
|
||||||
bool arenaListsAreEmpty();
|
bool arenaListsAreEmpty();
|
||||||
|
|
||||||
void setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind);
|
void setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind);
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
#include "vm/String-inl.h"
|
#include "vm/String-inl.h"
|
||||||
|
#include "ion/IonCode.h"
|
||||||
|
|
||||||
#ifdef MOZ_VALGRIND
|
#ifdef MOZ_VALGRIND
|
||||||
# define JS_VALGRIND
|
# define JS_VALGRIND
|
||||||
|
|
@ -110,13 +111,14 @@ using namespace js::gc;
|
||||||
JS_STATIC_ASSERT(JSTRACE_OBJECT == 0);
|
JS_STATIC_ASSERT(JSTRACE_OBJECT == 0);
|
||||||
JS_STATIC_ASSERT(JSTRACE_STRING == 1);
|
JS_STATIC_ASSERT(JSTRACE_STRING == 1);
|
||||||
JS_STATIC_ASSERT(JSTRACE_SHAPE == 2);
|
JS_STATIC_ASSERT(JSTRACE_SHAPE == 2);
|
||||||
JS_STATIC_ASSERT(JSTRACE_XML == 3);
|
JS_STATIC_ASSERT(JSTRACE_IONCODE == 3);
|
||||||
|
JS_STATIC_ASSERT(JSTRACE_XML == 4);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_SHAPE is the last non-xml
|
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_IONCODE is the last non-xml
|
||||||
* trace kind when JS_HAS_XML_SUPPORT is false.
|
* trace kind when JS_HAS_XML_SUPPORT is false.
|
||||||
*/
|
*/
|
||||||
JS_STATIC_ASSERT(JSTRACE_SHAPE + 1 == JSTRACE_XML);
|
JS_STATIC_ASSERT(JSTRACE_IONCODE + 1 == JSTRACE_XML);
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace gc {
|
namespace gc {
|
||||||
|
|
@ -153,6 +155,7 @@ const uint8 GCThingSizeMap[] = {
|
||||||
sizeof(JSShortString), /* FINALIZE_SHORT_STRING */
|
sizeof(JSShortString), /* FINALIZE_SHORT_STRING */
|
||||||
sizeof(JSString), /* FINALIZE_STRING */
|
sizeof(JSString), /* FINALIZE_STRING */
|
||||||
sizeof(JSExternalString), /* FINALIZE_EXTERNAL_STRING */
|
sizeof(JSExternalString), /* FINALIZE_EXTERNAL_STRING */
|
||||||
|
sizeof(ion::IonCode), /* FINALIZE_IONCODE */
|
||||||
};
|
};
|
||||||
|
|
||||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GCThingSizeMap) == FINALIZE_LIMIT);
|
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GCThingSizeMap) == FINALIZE_LIMIT);
|
||||||
|
|
@ -806,6 +809,9 @@ MarkIfGCThingWord(JSTracer *trc, jsuword w)
|
||||||
test = MarkArenaPtrConservatively<JSXML>(trc, aheader, addr);
|
test = MarkArenaPtrConservatively<JSXML>(trc, aheader, addr);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case FINALIZE_IONCODE:
|
||||||
|
test = MarkArenaPtrConservatively<ion::IonCode>(trc, aheader, addr);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
test = CGCT_WRONGTAG;
|
test = CGCT_WRONGTAG;
|
||||||
JS_NOT_REACHED("wrong tag");
|
JS_NOT_REACHED("wrong tag");
|
||||||
|
|
@ -1471,6 +1477,8 @@ RefillFinalizableFreeList(JSContext *cx, unsigned thingKind)
|
||||||
case FINALIZE_XML:
|
case FINALIZE_XML:
|
||||||
return RefillTypedFreeList<JSXML>(cx, thingKind);
|
return RefillTypedFreeList<JSXML>(cx, thingKind);
|
||||||
#endif
|
#endif
|
||||||
|
case FINALIZE_IONCODE:
|
||||||
|
return RefillTypedFreeList<ion::IonCode>(cx, thingKind);
|
||||||
default:
|
default:
|
||||||
JS_NOT_REACHED("bad finalize kind");
|
JS_NOT_REACHED("bad finalize kind");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1539,7 +1547,8 @@ GCMarker::GCMarker(JSContext *cx)
|
||||||
objStack(cx->runtime->gcMarkStackObjs, sizeof(cx->runtime->gcMarkStackObjs)),
|
objStack(cx->runtime->gcMarkStackObjs, sizeof(cx->runtime->gcMarkStackObjs)),
|
||||||
ropeStack(cx->runtime->gcMarkStackRopes, sizeof(cx->runtime->gcMarkStackRopes)),
|
ropeStack(cx->runtime->gcMarkStackRopes, sizeof(cx->runtime->gcMarkStackRopes)),
|
||||||
xmlStack(cx->runtime->gcMarkStackXMLs, sizeof(cx->runtime->gcMarkStackXMLs)),
|
xmlStack(cx->runtime->gcMarkStackXMLs, sizeof(cx->runtime->gcMarkStackXMLs)),
|
||||||
largeStack(cx->runtime->gcMarkStackLarges, sizeof(cx->runtime->gcMarkStackLarges))
|
largeStack(cx->runtime->gcMarkStackLarges, sizeof(cx->runtime->gcMarkStackLarges)),
|
||||||
|
ionCodeStack(cx->runtime->gcMarkStackIonCode, sizeof(cx->runtime->gcMarkStackIonCode))
|
||||||
{
|
{
|
||||||
JS_TRACER_INIT(this, cx, NULL);
|
JS_TRACER_INIT(this, cx, NULL);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
@ -2014,6 +2023,12 @@ JSCompartment::finalizeShapeArenaLists(JSContext *cx)
|
||||||
arenas[FINALIZE_SHAPE].finalizeNow<Shape>(cx);
|
arenas[FINALIZE_SHAPE].finalizeNow<Shape>(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JSCompartment::finalizeIonCodeArenaLists(JSContext *cx)
|
||||||
|
{
|
||||||
|
arenas[FINALIZE_IONCODE].finalizeNow<ion::IonCode>(cx);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
@ -2351,6 +2366,8 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
||||||
GCTIMESTAMP(sweepObjectEnd);
|
GCTIMESTAMP(sweepObjectEnd);
|
||||||
comp->finalizeStringArenaLists(cx);
|
comp->finalizeStringArenaLists(cx);
|
||||||
GCTIMESTAMP(sweepStringEnd);
|
GCTIMESTAMP(sweepStringEnd);
|
||||||
|
comp->finalizeIonCodeArenaLists(cx);
|
||||||
|
GCTIMESTAMP(sweepIonCodeEnd);
|
||||||
comp->finalizeShapeArenaLists(cx);
|
comp->finalizeShapeArenaLists(cx);
|
||||||
GCTIMESTAMP(sweepShapeEnd);
|
GCTIMESTAMP(sweepShapeEnd);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2373,6 +2390,11 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
||||||
|
|
||||||
GCTIMESTAMP(sweepStringEnd);
|
GCTIMESTAMP(sweepStringEnd);
|
||||||
|
|
||||||
|
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
|
||||||
|
(*c)->finalizeIonCodeArenaLists(cx);
|
||||||
|
|
||||||
|
GCTIMESTAMP(sweepIonCodeEnd);
|
||||||
|
|
||||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++) {
|
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++) {
|
||||||
(*c)->finalizeShapeArenaLists(cx);
|
(*c)->finalizeShapeArenaLists(cx);
|
||||||
Probes::GCEndSweepPhase(*c);
|
Probes::GCEndSweepPhase(*c);
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,10 @@ namespace js {
|
||||||
class GCHelperThread;
|
class GCHelperThread;
|
||||||
struct Shape;
|
struct Shape;
|
||||||
|
|
||||||
|
namespace ion {
|
||||||
|
class IonCode;
|
||||||
|
}
|
||||||
|
|
||||||
namespace gc {
|
namespace gc {
|
||||||
|
|
||||||
struct Arena;
|
struct Arena;
|
||||||
|
|
@ -104,6 +108,7 @@ enum FinalizeKind {
|
||||||
FINALIZE_SHORT_STRING,
|
FINALIZE_SHORT_STRING,
|
||||||
FINALIZE_STRING,
|
FINALIZE_STRING,
|
||||||
FINALIZE_EXTERNAL_STRING,
|
FINALIZE_EXTERNAL_STRING,
|
||||||
|
FINALIZE_IONCODE,
|
||||||
FINALIZE_LIMIT
|
FINALIZE_LIMIT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -607,12 +612,13 @@ Cell::compartment() const
|
||||||
return arenaHeader()->compartment;
|
return arenaHeader()->compartment;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define JSTRACE_XML 3
|
#define JSTRACE_IONCODE 3
|
||||||
|
#define JSTRACE_XML 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* One past the maximum trace kind.
|
* One past the maximum trace kind.
|
||||||
*/
|
*/
|
||||||
#define JSTRACE_LIMIT 4
|
#define JSTRACE_LIMIT 5
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lower limit after which we limit the heap growth
|
* Lower limit after which we limit the heap growth
|
||||||
|
|
@ -656,6 +662,7 @@ GetFinalizableTraceKind(size_t thingKind)
|
||||||
JSTRACE_STRING, /* FINALIZE_SHORT_STRING */
|
JSTRACE_STRING, /* FINALIZE_SHORT_STRING */
|
||||||
JSTRACE_STRING, /* FINALIZE_STRING */
|
JSTRACE_STRING, /* FINALIZE_STRING */
|
||||||
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING */
|
JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING */
|
||||||
|
JSTRACE_IONCODE, /* FINALIZE_IONCODE */
|
||||||
};
|
};
|
||||||
|
|
||||||
JS_ASSERT(thingKind < FINALIZE_LIMIT);
|
JS_ASSERT(thingKind < FINALIZE_LIMIT);
|
||||||
|
|
@ -1261,6 +1268,7 @@ static const size_t OBJECT_MARK_STACK_SIZE = 32768 * sizeof(JSObject *);
|
||||||
static const size_t ROPES_MARK_STACK_SIZE = 1024 * sizeof(JSString *);
|
static const size_t ROPES_MARK_STACK_SIZE = 1024 * sizeof(JSString *);
|
||||||
static const size_t XML_MARK_STACK_SIZE = 1024 * sizeof(JSXML *);
|
static const size_t XML_MARK_STACK_SIZE = 1024 * sizeof(JSXML *);
|
||||||
static const size_t LARGE_MARK_STACK_SIZE = 64 * sizeof(LargeMarkItem);
|
static const size_t LARGE_MARK_STACK_SIZE = 64 * sizeof(LargeMarkItem);
|
||||||
|
static const size_t IONCODE_MARK_STACK_SIZE = 1024 * sizeof(ion::IonCode *);
|
||||||
|
|
||||||
struct GCMarker : public JSTracer {
|
struct GCMarker : public JSTracer {
|
||||||
private:
|
private:
|
||||||
|
|
@ -1285,6 +1293,7 @@ struct GCMarker : public JSTracer {
|
||||||
MarkStack<JSRope *> ropeStack;
|
MarkStack<JSRope *> ropeStack;
|
||||||
MarkStack<JSXML *> xmlStack;
|
MarkStack<JSXML *> xmlStack;
|
||||||
MarkStack<LargeMarkItem> largeStack;
|
MarkStack<LargeMarkItem> largeStack;
|
||||||
|
MarkStack<ion::IonCode *> ionCodeStack;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GCMarker(JSContext *cx);
|
explicit GCMarker(JSContext *cx);
|
||||||
|
|
@ -1308,7 +1317,8 @@ struct GCMarker : public JSTracer {
|
||||||
return objStack.isEmpty() &&
|
return objStack.isEmpty() &&
|
||||||
ropeStack.isEmpty() &&
|
ropeStack.isEmpty() &&
|
||||||
xmlStack.isEmpty() &&
|
xmlStack.isEmpty() &&
|
||||||
largeStack.isEmpty();
|
largeStack.isEmpty() &&
|
||||||
|
ionCodeStack.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(void) drainMarkStack();
|
JS_FRIEND_API(void) drainMarkStack();
|
||||||
|
|
@ -1327,6 +1337,11 @@ struct GCMarker : public JSTracer {
|
||||||
if (!xmlStack.push(xml))
|
if (!xmlStack.push(xml))
|
||||||
delayMarkingChildren(xml);
|
delayMarkingChildren(xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pushIonCode(ion::IonCode *code) {
|
||||||
|
if (!ionCodeStack.push(code))
|
||||||
|
delayMarkingChildren(code);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1369,7 +1384,7 @@ js_MarkTraps(JSTracer *trc);
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) < JSTRACE_LIMIT)
|
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) < JSTRACE_LIMIT)
|
||||||
#else
|
#else
|
||||||
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_SHAPE)
|
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_IONCODE)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
#include "jsscopeinlines.h"
|
#include "jsscopeinlines.h"
|
||||||
|
|
||||||
|
#include "ion/IonCode.h"
|
||||||
#include "vm/String-inl.h"
|
#include "vm/String-inl.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -193,6 +194,15 @@ MarkShape(JSTracer *trc, const Shape *shape, const char *name)
|
||||||
Mark(trc, shape);
|
Mark(trc, shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MarkIonCode(JSTracer *trc, ion::IonCode *code, const char *name)
|
||||||
|
{
|
||||||
|
JS_ASSERT(trc);
|
||||||
|
JS_ASSERT(code);
|
||||||
|
JS_SET_TRACING_NAME(trc, name);
|
||||||
|
Mark(trc, code);
|
||||||
|
}
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
void
|
void
|
||||||
MarkXML(JSTracer *trc, JSXML *xml, const char *name)
|
MarkXML(JSTracer *trc, JSXML *xml, const char *name)
|
||||||
|
|
@ -243,6 +253,16 @@ PushMarkStack(GCMarker *gcmarker, JSShortString *thing)
|
||||||
(void) thing->markIfUnmarked(gcmarker->getMarkColor());
|
(void) thing->markIfUnmarked(gcmarker->getMarkColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PushMarkStack(GCMarker *gcmarker, ion::IonCode *thing)
|
||||||
|
{
|
||||||
|
JS_ASSERT_IF(gcmarker->context->runtime->gcCurrentCompartment,
|
||||||
|
thing->compartment() == gcmarker->context->runtime->gcCurrentCompartment);
|
||||||
|
|
||||||
|
if (thing->markIfUnmarked(gcmarker->getMarkColor()))
|
||||||
|
gcmarker->pushIonCode(thing);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ScanShape(GCMarker *gcmarker, const Shape *shape);
|
ScanShape(GCMarker *gcmarker, const Shape *shape);
|
||||||
|
|
||||||
|
|
@ -340,6 +360,9 @@ MarkKind(JSTracer *trc, void *thing, uint32 kind)
|
||||||
case JSTRACE_SHAPE:
|
case JSTRACE_SHAPE:
|
||||||
Mark(trc, reinterpret_cast<Shape *>(thing));
|
Mark(trc, reinterpret_cast<Shape *>(thing));
|
||||||
break;
|
break;
|
||||||
|
case JSTRACE_IONCODE:
|
||||||
|
Mark(trc, reinterpret_cast<ion::IonCode *>(thing));
|
||||||
|
break;
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
case JSTRACE_XML:
|
case JSTRACE_XML:
|
||||||
Mark(trc, reinterpret_cast<JSXML *>(thing));
|
Mark(trc, reinterpret_cast<JSXML *>(thing));
|
||||||
|
|
@ -477,6 +500,12 @@ MarkRoot(JSTracer *trc, JSXML *thing, const char *name)
|
||||||
MarkXML(trc, thing, name);
|
MarkXML(trc, thing, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MarkRoot(JSTracer *trc, ion::IonCode *code, const char *name)
|
||||||
|
{
|
||||||
|
MarkIonCode(trc, code, name);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
PrintPropertyGetterOrSetter(JSTracer *trc, char *buf, size_t bufsize)
|
PrintPropertyGetterOrSetter(JSTracer *trc, char *buf, size_t bufsize)
|
||||||
{
|
{
|
||||||
|
|
@ -767,6 +796,11 @@ restart:
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MarkChildren(JSTracer *trc, ion::IonCode *code)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef JS_HAS_XML_SUPPORT
|
#ifdef JS_HAS_XML_SUPPORT
|
||||||
void
|
void
|
||||||
MarkChildren(JSTracer *trc, JSXML *xml)
|
MarkChildren(JSTracer *trc, JSXML *xml)
|
||||||
|
|
@ -793,6 +827,9 @@ GCMarker::drainMarkStack()
|
||||||
while (!xmlStack.isEmpty())
|
while (!xmlStack.isEmpty())
|
||||||
MarkChildren(this, xmlStack.pop());
|
MarkChildren(this, xmlStack.pop());
|
||||||
|
|
||||||
|
while (!ionCodeStack.isEmpty())
|
||||||
|
MarkChildren(this, ionCodeStack.pop());
|
||||||
|
|
||||||
if (!largeStack.isEmpty()) {
|
if (!largeStack.isEmpty()) {
|
||||||
LargeMarkItem &item = largeStack.peek();
|
LargeMarkItem &item = largeStack.peek();
|
||||||
if (ScanLargeObject(this, item))
|
if (ScanLargeObject(this, item))
|
||||||
|
|
@ -829,6 +866,10 @@ JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind)
|
||||||
MarkChildren(trc, (js::Shape *)thing);
|
MarkChildren(trc, (js::Shape *)thing);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case JSTRACE_IONCODE:
|
||||||
|
MarkChildren(trc, (js::ion::IonCode *)thing);
|
||||||
|
break;
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
case JSTRACE_XML:
|
case JSTRACE_XML:
|
||||||
MarkChildren(trc, (JSXML *)thing);
|
MarkChildren(trc, (JSXML *)thing);
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,11 @@
|
||||||
#include "jstl.h"
|
#include "jstl.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
namespace ion {
|
||||||
|
class IonCode;
|
||||||
|
}
|
||||||
|
|
||||||
namespace gc {
|
namespace gc {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -62,6 +67,9 @@ MarkString(JSTracer *trc, JSString *str, const char *name);
|
||||||
void
|
void
|
||||||
MarkObject(JSTracer *trc, JSObject &obj, const char *name);
|
MarkObject(JSTracer *trc, JSObject &obj, const char *name);
|
||||||
|
|
||||||
|
void
|
||||||
|
MarkIonCode(JSTracer *trc, ion::IonCode *code, const char *name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark an object that may be in a different compartment from the compartment
|
* Mark an object that may be in a different compartment from the compartment
|
||||||
* being GC'd. (Although it won't be marked if it's in the wrong compartment.)
|
* being GC'd. (Although it won't be marked if it's in the wrong compartment.)
|
||||||
|
|
@ -156,6 +164,9 @@ MarkRoot(JSTracer *trc, const Shape *thing, const char *name);
|
||||||
void
|
void
|
||||||
MarkRoot(JSTracer *trc, JSXML *thing, const char *name);
|
MarkRoot(JSTracer *trc, JSXML *thing, const char *name);
|
||||||
|
|
||||||
|
void
|
||||||
|
MarkRoot(JSTracer *trc, ion::IonCode *code, const char *name);
|
||||||
|
|
||||||
void
|
void
|
||||||
MarkChildren(JSTracer *trc, JSObject *obj);
|
MarkChildren(JSTracer *trc, JSObject *obj);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ struct GCTimer
|
||||||
uint64 sweepStringEnd;
|
uint64 sweepStringEnd;
|
||||||
uint64 sweepShapeEnd;
|
uint64 sweepShapeEnd;
|
||||||
uint64 sweepDestroyEnd;
|
uint64 sweepDestroyEnd;
|
||||||
|
uint64 sweepIonCodeEnd;
|
||||||
uint64 end;
|
uint64 end;
|
||||||
|
|
||||||
bool isCompartmental;
|
bool isCompartmental;
|
||||||
|
|
|
||||||
|
|
@ -1518,6 +1518,10 @@ js_TraceScript(JSTracer *trc, JSScript *script)
|
||||||
if (IS_GC_MARKING_TRACER(trc) && script->filename)
|
if (IS_GC_MARKING_TRACER(trc) && script->filename)
|
||||||
js_MarkScriptFilename(script->filename);
|
js_MarkScriptFilename(script->filename);
|
||||||
|
|
||||||
|
#ifdef JS_ION
|
||||||
|
ion::IonScript::Trace(trc, script);
|
||||||
|
#endif
|
||||||
|
|
||||||
script->bindings.trace(trc);
|
script->bindings.trace(trc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue