Bug 604798: move JM global data to compartment, r=dvander

This commit is contained in:
David Mandelin 2010-10-29 15:37:13 -07:00
parent 186692a59a
commit 0e7c06846a
12 changed files with 129 additions and 78 deletions

View File

@ -495,9 +495,6 @@ JSThreadData::init()
return false;
#ifdef JS_TRACER
InitJIT(&traceMonitor);
#endif
#ifdef JS_METHODJIT
jmData.Initialize();
#endif
dtoaState = js_NewDtoaState();
if (!dtoaState) {
@ -533,9 +530,6 @@ JSThreadData::finish()
propertyCache.~PropertyCache();
#if defined JS_TRACER
FinishJIT(&traceMonitor);
#endif
#if defined JS_METHODJIT
jmData.Finish();
#endif
stackSpace.finish();
delete mathCache;

View File

@ -128,10 +128,6 @@ namespace JSC {
namespace js {
#ifdef JS_METHODJIT
struct VMFrame;
#endif
/* Tracer constants. */
static const size_t MONITOR_N_GLOBAL_STATES = 4;
static const size_t FRAGMENT_TABLE_SIZE = 512;
@ -163,7 +159,7 @@ typedef nanojit::HashMap<uint32, FragPI, nanojit::DefaultHash<uint32> > FragStat
#endif
namespace mjit {
class CallStackIterator;
class JaegerCompartment;
}
/*
@ -227,34 +223,6 @@ struct TracerState
~TracerState();
};
#ifdef JS_METHODJIT
namespace mjit {
struct Trampolines
{
typedef void (*TrampolinePtr)();
TrampolinePtr forceReturn;
JSC::ExecutablePool *forceReturnPool;
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
TrampolinePtr forceReturnFast;
JSC::ExecutablePool *forceReturnFastPool;
#endif
};
struct ThreadData
{
JSC::ExecutableAllocator *execAlloc;
// Trampolines for JIT code.
Trampolines trampolines;
VMFrame *activeFrame;
bool Initialize();
void Finish();
};
}
#endif /* JS_METHODJIT */
/*
* Storage for the execution state and store during trace execution. Generated
* code depends on the fact that the globals begin |MAX_NATIVE_STACK_SLOTS|
@ -1158,10 +1126,6 @@ struct JSThreadData {
unsigned iterationCounter;
#endif
#ifdef JS_METHODJIT
js::mjit::ThreadData jmData;
#endif
/* Lock-free hashed lists of scripts created by eval to garbage-collect. */
JSScript *scriptsToGC[JS_EVAL_CACHE_SIZE];
@ -1757,7 +1721,6 @@ struct JSRuntime {
#define JS_GSN_CACHE(cx) (JS_THREAD_DATA(cx)->gsnCache)
#define JS_PROPERTY_CACHE(cx) (JS_THREAD_DATA(cx)->propertyCache)
#define JS_TRACE_MONITOR(cx) (JS_THREAD_DATA(cx)->traceMonitor)
#define JS_METHODJIT_DATA(cx) (JS_THREAD_DATA(cx)->jmData)
#define JS_SCRIPTS_TO_GC(cx) (JS_THREAD_DATA(cx)->scriptsToGC)
#ifdef DEBUG
@ -2254,6 +2217,10 @@ struct JSContext
js::Vector<JSGenerator *, 2, js::SystemAllocPolicy> genStack;
public:
#ifdef JS_METHODJIT
inline js::mjit::JaegerCompartment *jaegerCompartment();
#endif
/* Return the generator object for the given generator frame. */
JSGenerator *generatorFor(JSStackFrame *fp) const;

View File

@ -47,6 +47,7 @@
#include "jsxml.h"
#include "jsregexp.h"
#include "jsgc.h"
#include "jscompartment.h"
namespace js {
@ -77,6 +78,13 @@ GetGlobalForScopeChain(JSContext *cx)
}
#ifdef JS_METHODJIT
inline js::mjit::JaegerCompartment *JSContext::jaegerCompartment()
{
return compartment->jaegerCompartment;
}
#endif
inline bool
JSContext::ensureGeneratorStackSpace()
{

View File

@ -44,6 +44,7 @@
#include "jsiter.h"
#include "jsproxy.h"
#include "jsscope.h"
#include "methodjit/MethodJIT.h"
#include "methodjit/PolyIC.h"
#include "methodjit/MonoIC.h"
@ -61,6 +62,9 @@ JSCompartment::JSCompartment(JSRuntime *rt)
JSCompartment::~JSCompartment()
{
#ifdef JS_METHODJIT
delete jaegerCompartment;
#endif
}
bool
@ -74,7 +78,16 @@ JSCompartment::init()
#ifdef JS_GCMETER
memset(&compartmentStats, 0, sizeof(JSGCArenaStats) * FINALIZE_LIMIT);
#endif
return crossCompartmentWrappers.init();
if (!crossCompartmentWrappers.init())
return false;
#ifdef JS_METHODJIT
if (!(jaegerCompartment = new mjit::JaegerCompartment))
return false;
return jaegerCompartment->Initialize();
#else
return true;
#endif
}
bool

View File

@ -54,25 +54,34 @@
#pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */
#endif
struct JS_FRIEND_API(JSCompartment) {
JSRuntime *rt;
JSPrincipals *principals;
js::gc::Chunk *chunk;
namespace js {
namespace mjit {
class JaegerCompartment;
}
}
js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT];
js::gc::FreeLists freeLists;
struct JS_FRIEND_API(JSCompartment) {
JSRuntime *rt;
JSPrincipals *principals;
js::gc::Chunk *chunk;
js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT];
js::gc::FreeLists freeLists;
#ifdef JS_GCMETER
js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT];
js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT];
#endif
void *data;
bool marked;
js::WrapperMap crossCompartmentWrappers;
bool debugMode;
void *data;
bool marked;
js::WrapperMap crossCompartmentWrappers;
/* List all scripts in this compartment. */
JSCList scripts;
#ifdef JS_METHODJIT
js::mjit::JaegerCompartment *jaegerCompartment;
#endif
bool debugMode; // true iff debug mode on
JSCList scripts; // scripts in this compartment
/*
* Weak references to lazily-created, well-known XML singletons.
@ -81,8 +90,8 @@ struct JS_FRIEND_API(JSCompartment) {
* the object graph usually associated with a JSContext's global object,
* including the set of standard class objects. See jsxml.c for details.
*/
JSObject *anynameObject;
JSObject *functionNamespaceObject;
JSObject *anynameObject;
JSObject *functionNamespaceObject;
JSCompartment(JSRuntime *cx);
~JSCompartment();

View File

@ -131,7 +131,7 @@ js_SetDebugMode(JSContext *cx, JSBool debug)
* correctness. We set the debug flag to false so that the caller
* will not later attempt to use debugging features.
*/
mjit::Recompiler recompiler(cx, script);
js::mjit::Recompiler recompiler(cx, script);
if (!recompiler.recompile()) {
cx->compartment->debugMode = JS_FALSE;
return JS_FALSE;
@ -281,7 +281,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
#ifdef JS_METHODJIT
if (script->hasJITCode()) {
mjit::Recompiler recompiler(cx, script);
js::mjit::Recompiler recompiler(cx, script);
if (!recompiler.recompile())
return JS_FALSE;
}

View File

@ -93,8 +93,7 @@ class BaseCompiler : public MacroAssemblerTypedefs
public:
static JSC::ExecutablePool *
GetExecPool(JSContext *cx, size_t size) {
ThreadData *jaegerData = &JS_METHODJIT_DATA(cx);
JSC::ExecutablePool *pool = jaegerData->execAlloc->poolForSize(size);
JSC::ExecutablePool *pool = cx->jaegerCompartment()->poolForSize(size);
if (!pool)
js_ReportOutOfMemory(cx);
return pool;

View File

@ -515,7 +515,7 @@ js_InternalThrow(VMFrame &f)
cx->throwing = JS_FALSE;
cx->fp()->setReturnValue(rval);
return JS_FUNC_TO_DATA_PTR(void *,
JS_METHODJIT_DATA(cx).trampolines.forceReturn);
cx->jaegerCompartment()->forceReturnTrampoline());
case JSTRAP_THROW:
cx->exception = rval;

View File

@ -116,17 +116,14 @@ extern "C" void JaegerTrampolineReturn();
extern "C" void JS_FASTCALL
PushActiveVMFrame(VMFrame &f)
{
f.previous = JS_METHODJIT_DATA(f.cx).activeFrame;
JS_METHODJIT_DATA(f.cx).activeFrame = &f;
f.cx->jaegerCompartment()->pushActiveFrame(&f);
f.regs.fp->setNativeReturnAddress(JS_FUNC_TO_DATA_PTR(void*, JaegerTrampolineReturn));
}
extern "C" void JS_FASTCALL
PopActiveVMFrame(VMFrame &f)
{
JS_ASSERT(JS_METHODJIT_DATA(f.cx).activeFrame);
JS_METHODJIT_DATA(f.cx).activeFrame = JS_METHODJIT_DATA(f.cx).activeFrame->previous;
f.cx->jaegerCompartment()->popActiveFrame();
}
extern "C" void JS_FASTCALL
@ -683,7 +680,7 @@ JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL);
#endif /* _MSC_VER */
bool
ThreadData::Initialize()
JaegerCompartment::Initialize()
{
execAlloc = new JSC::ExecutableAllocator();
if (!execAlloc)
@ -700,13 +697,13 @@ ThreadData::Initialize()
StubCallsForOp[i] = 0;
#endif
activeFrame = NULL;
activeFrame_ = NULL;
return true;
}
void
ThreadData::Finish()
JaegerCompartment::Finish()
{
TrampolineCompiler::release(&trampolines);
delete execAlloc;

View File

@ -140,6 +140,70 @@ extern "C" void JaegerStubVeneer(void);
#endif
namespace mjit {
/*
* Trampolines to force returns from jit code.
* See also TrampolineCompiler::generateForceReturn(Fast).
*/
struct Trampolines {
typedef void (*TrampolinePtr)();
TrampolinePtr forceReturn;
JSC::ExecutablePool *forceReturnPool;
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
TrampolinePtr forceReturnFast;
JSC::ExecutablePool *forceReturnFastPool;
#endif
};
/*
* Method JIT compartment data. Currently, there is exactly one per
* JS compartment. It would be safe for multiple JS compartments to
* share a JaegerCompartment as long as only one thread can enter
* the JaegerCompartment at a time.
*/
class JaegerCompartment {
JSC::ExecutableAllocator *execAlloc; // allocator for jit code
Trampolines trampolines; // force-return trampolines
VMFrame *activeFrame_; // current active VMFrame
friend struct JSCompartment;
bool Initialize();
void Finish();
~JaegerCompartment() { Finish(); }
public:
JSC::ExecutablePool *poolForSize(size_t size) {
return execAlloc->poolForSize(size);
}
VMFrame *activeFrame() {
return activeFrame_;
}
void pushActiveFrame(VMFrame *f) {
f->previous = activeFrame_;
activeFrame_ = f;
}
void popActiveFrame() {
JS_ASSERT(activeFrame_);
activeFrame_ = activeFrame_->previous;
}
Trampolines::TrampolinePtr forceReturnTrampoline() const {
return trampolines.forceReturn;
}
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
Trampolines::TrampolinePtr forceReturnFastTrampoline() const {
return trampolines.forceReturnFast;
}
#endif
};
namespace ic {
# if defined JS_POLYIC
struct PICInfo;

View File

@ -143,7 +143,7 @@ Recompiler::recompile()
}
/* Iterate over VMFrames saving the machine and scripted return. */
for (VMFrame *f = JS_METHODJIT_DATA(cx).activeFrame;
for (VMFrame *f = cx->jaegerCompartment()->activeFrame();
f != NULL;
f = f->previous) {

View File

@ -1294,10 +1294,10 @@ stubs::Debugger(VMFrame &f, jsbytecode *pc)
f.cx->fp()->setReturnValue(rval);
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
*f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *,
JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast);
f.cx->jaegerCompartment()->forceReturnFastTrampoline());
#else
*f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *,
JS_METHODJIT_DATA(f.cx).trampolines.forceReturn);
f.cx->jaegerCompartment()->forceReturnTrampoline());
#endif
break;
@ -1334,10 +1334,10 @@ stubs::Trap(VMFrame &f, jsbytecode *pc)
f.cx->fp()->setReturnValue(rval);
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
*f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *,
JS_METHODJIT_DATA(f.cx).trampolines.forceReturnFast);
f.cx->jaegerCompartment()->forceReturnFastTrampoline());
#else
*f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *,
JS_METHODJIT_DATA(f.cx).trampolines.forceReturn);
f.cx->jaegerCompartment()->forceReturnTrampoline());
#endif
break;