mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset a661b26a83a1 due to tinderbox failures.
This commit is contained in:
parent
469286fcd4
commit
ddcca372a7
@ -330,4 +330,3 @@ MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION, 247, 0, JSEXN_ERR, "call to Function() blo
|
||||
MSG_DEF(JSMSG_BAD_GET_SET_FIELD, 248, 1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function")
|
||||
MSG_DEF(JSMSG_BAD_PROXY_FIX, 249, 0, JSEXN_TYPEERR, "proxy was fixed while executing the handler")
|
||||
MSG_DEF(JSMSG_INVALID_EVAL_SCOPE_ARG, 250, 0, JSEXN_EVALERR, "invalid eval scope argument")
|
||||
MSG_DEF(JSMSG_NEED_DEBUG_MODE, 251, 0, JSEXN_ERR, "function can only be called in debug mode")
|
||||
|
@ -45,9 +45,6 @@ BEGIN_TEST(testTrap_gc)
|
||||
// Disable JIT for debugging
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) & ~JSOPTION_JIT);
|
||||
|
||||
// Enable debug mode
|
||||
CHECK(JS_SetDebugMode(cx, JS_TRUE));
|
||||
|
||||
jsbytecode *line2 = JS_LineNumberToPC(cx, script, 1);
|
||||
CHECK(line2);
|
||||
|
||||
|
@ -513,25 +513,6 @@ FrameRegsIter::operator++()
|
||||
return *this;
|
||||
}
|
||||
|
||||
AllFramesIter::AllFramesIter(JSContext *cx)
|
||||
: curcs(cx->stack().getCurrentSegment()),
|
||||
curfp(curcs ? curcs->getCurrentFrame() : NULL)
|
||||
{
|
||||
}
|
||||
|
||||
AllFramesIter&
|
||||
AllFramesIter::operator++()
|
||||
{
|
||||
JS_ASSERT(!done());
|
||||
if (curfp == curcs->getInitialFrame()) {
|
||||
curcs = curcs->getPreviousInMemory();
|
||||
curfp = curcs ? curcs->getCurrentFrame() : NULL;
|
||||
} else {
|
||||
curfp = curfp->down;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
JSThreadData::init()
|
||||
{
|
||||
@ -609,6 +590,9 @@ JSThreadData::purge(JSContext *cx)
|
||||
if (cx->runtime->gcRegenShapes)
|
||||
traceMonitor.needFlush = JS_TRUE;
|
||||
#endif
|
||||
#ifdef JS_METHODJIT
|
||||
jmData.purge(cx);
|
||||
#endif
|
||||
|
||||
/* Destroy eval'ed scripts. */
|
||||
js_DestroyScriptsToGC(cx, this);
|
||||
@ -2284,10 +2268,9 @@ void
|
||||
JSContext::purge()
|
||||
{
|
||||
FreeOldArenas(runtime, ®expPool);
|
||||
/* :XXX: Is this the right place for this? */
|
||||
compartment->purge(this);
|
||||
}
|
||||
|
||||
|
||||
namespace js {
|
||||
|
||||
void
|
||||
|
@ -237,6 +237,10 @@ namespace mjit {
|
||||
{
|
||||
JSC::ExecutableAllocator *execPool;
|
||||
|
||||
// Scripts that have had PICs patched or PIC stubs generated.
|
||||
typedef js::HashSet<JSScript*, DefaultHasher<JSScript*>, js::SystemAllocPolicy> ScriptSet;
|
||||
ScriptSet picScripts;
|
||||
|
||||
// Trampolines for JIT code.
|
||||
Trampolines trampolines;
|
||||
|
||||
@ -244,6 +248,10 @@ namespace mjit {
|
||||
|
||||
bool Initialize();
|
||||
void Finish();
|
||||
|
||||
bool addScript(JSScript *script);
|
||||
void removeScript(JSScript *script);
|
||||
void purge(JSContext *cx);
|
||||
};
|
||||
}
|
||||
#endif /* JS_METHODJIT */
|
||||
@ -815,24 +823,6 @@ class FrameRegsIter
|
||||
jsbytecode *pc() const { return curpc; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Utility class for iteration over all active stack frames.
|
||||
*/
|
||||
class AllFramesIter
|
||||
{
|
||||
public:
|
||||
AllFramesIter(JSContext *cx);
|
||||
|
||||
bool done() const { return curfp == NULL; }
|
||||
AllFramesIter& operator++();
|
||||
|
||||
JSStackFrame *fp() const { return curfp; }
|
||||
|
||||
private:
|
||||
CallStackSegment *curcs;
|
||||
JSStackFrame *curfp;
|
||||
};
|
||||
|
||||
/* Holds the number of recording attemps for an address. */
|
||||
typedef HashMap<jsbytecode*,
|
||||
size_t,
|
||||
@ -1241,7 +1231,6 @@ struct WrapperHasher
|
||||
};
|
||||
|
||||
typedef HashMap<Value, Value, WrapperHasher, SystemAllocPolicy> WrapperMap;
|
||||
typedef HashSet<JSScript *, DefaultHasher<JSScript *>, SystemAllocPolicy> ScriptSet;
|
||||
|
||||
class AutoValueVector;
|
||||
class AutoIdVector;
|
||||
@ -1254,15 +1243,6 @@ struct JSCompartment {
|
||||
void *data;
|
||||
bool marked;
|
||||
js::WrapperMap crossCompartmentWrappers;
|
||||
bool debugMode;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
/* Executable allocator for PIC buffers. */
|
||||
JSC::ExecutableAllocator *execPool;
|
||||
|
||||
/* Needed to re-JIT scripts for debug mode and so we can flush PICs. */
|
||||
js::ScriptSet jitScripts;
|
||||
#endif
|
||||
|
||||
JSCompartment(JSRuntime *cx);
|
||||
~JSCompartment();
|
||||
@ -1279,12 +1259,6 @@ struct JSCompartment {
|
||||
bool wrapException(JSContext *cx);
|
||||
|
||||
void sweep(JSContext *cx);
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
bool addScript(JSContext *cx, JSScript *script);
|
||||
void removeScript(JSScript *script);
|
||||
#endif
|
||||
void purge(JSContext *cx);
|
||||
};
|
||||
|
||||
struct JSRuntime {
|
||||
|
@ -69,8 +69,10 @@
|
||||
|
||||
#include "jsautooplen.h"
|
||||
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "methodjit/Retcon.h"
|
||||
#ifdef JS_METHODJIT
|
||||
# include "methodjit/MethodJIT.h"
|
||||
# include "methodjit/Retcon.h"
|
||||
#endif
|
||||
|
||||
using namespace js;
|
||||
|
||||
@ -87,79 +89,6 @@ typedef struct JSTrap {
|
||||
#define DBG_UNLOCK(rt) JS_RELEASE_LOCK((rt)->debuggerLock)
|
||||
#define DBG_LOCK_EVAL(rt,expr) (DBG_LOCK(rt), (expr), DBG_UNLOCK(rt))
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_GetDebugMode(JSContext *cx)
|
||||
{
|
||||
return cx->compartment->debugMode;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsScriptLive(JSContext *cx, JSScript *script)
|
||||
{
|
||||
for (AllFramesIter i(cx); !i.done(); ++i) {
|
||||
if (i.fp()->script == script)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_SetDebugMode(JSContext *cx, JSBool debug)
|
||||
{
|
||||
cx->compartment->debugMode = debug;
|
||||
#ifdef JS_METHODJIT
|
||||
for (ScriptSet::Range r = cx->compartment->jitScripts.all();
|
||||
!r.empty();
|
||||
r.popFront()) {
|
||||
JSScript *script = r.front();
|
||||
if (script->debugMode != debug &&
|
||||
script->ncode &&
|
||||
script->ncode != JS_UNJITTABLE_METHOD &&
|
||||
!IsScriptLive(cx, script)) {
|
||||
/*
|
||||
* In the event that this fails, debug mode is left partially on,
|
||||
* leading to a small performance overhead but no loss of
|
||||
* 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);
|
||||
if (!recompiler.recompile()) {
|
||||
cx->compartment->debugMode = JS_FALSE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebugMode(JSContext *cx, JSBool debug)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (AllFramesIter i(cx); !i.done(); ++i)
|
||||
JS_ASSERT(JS_IsNativeFrame(cx, i.fp()));
|
||||
#endif
|
||||
|
||||
return js_SetDebugMode(cx, debug);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
CheckDebugMode(JSContext *cx)
|
||||
{
|
||||
JSBool debugMode = JS_GetDebugMode(cx);
|
||||
/*
|
||||
* :TODO:
|
||||
* This probably should be an assertion, since it's indicative of a severe
|
||||
* API misuse.
|
||||
*/
|
||||
if (!debugMode) {
|
||||
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
|
||||
NULL, JSMSG_NEED_DEBUG_MODE);
|
||||
}
|
||||
return debugMode;
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: FindTrap must be called with rt->debuggerLock acquired.
|
||||
*/
|
||||
@ -224,9 +153,6 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSRuntime *rt;
|
||||
uint32 sample;
|
||||
|
||||
if (!CheckDebugMode(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
if (script == JSScript::emptyScript()) {
|
||||
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
|
||||
NULL, JSMSG_READ_ONLY, "empty script");
|
||||
@ -1447,9 +1373,6 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
{
|
||||
JS_ASSERT_NOT_ON_TRACE(cx);
|
||||
|
||||
if (!CheckDebugMode(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
JSObject *scobj = JS_GetFrameScopeChain(cx, fp);
|
||||
if (!scobj)
|
||||
return false;
|
||||
@ -1484,9 +1407,6 @@ JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
JSBool ok;
|
||||
size_t len = length;
|
||||
|
||||
if (!CheckDebugMode(cx))
|
||||
return JS_FALSE;
|
||||
|
||||
chars = js_InflateString(cx, bytes, &len);
|
||||
if (!chars)
|
||||
return JS_FALSE;
|
||||
|
@ -49,28 +49,6 @@
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* Debug mode is a compartment-wide mode that enables a debugger to attach
|
||||
* to and interact with running methodjit-ed frames. In particular, it causes
|
||||
* every function to be compiled as if an eval was present (so eval-in-frame)
|
||||
* can work, and it ensures that functions can be re-JITed for other debug
|
||||
* features. In general, it is not safe to interact with frames that were live
|
||||
* before debug mode was enabled. For this reason, it is also not safe to
|
||||
* enable debug mode while frames are live.
|
||||
*/
|
||||
|
||||
/* Get current state of debugging mode. */
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetDebugMode(JSContext *cx);
|
||||
|
||||
/* Turn on debugging mode, ignoring the presence of live frames. */
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_SetDebugMode(JSContext *cx, JSBool debug);
|
||||
|
||||
/* Turn on debugging mode. */
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebugMode(JSContext *cx, JSBool debug);
|
||||
|
||||
/*
|
||||
* Unexported library-private helper used to unpatch all traps in a script.
|
||||
* Returns script->code if script has no traps, else a JS_malloc'ed copy of
|
||||
|
@ -76,12 +76,7 @@ static const jsbytecode emptyScriptCode[] = {JSOP_STOP, SRC_NULL};
|
||||
/* static */ const JSScript JSScript::emptyScriptConst = {
|
||||
const_cast<jsbytecode*>(emptyScriptCode),
|
||||
1, JSVERSION_DEFAULT, 0, 0, 0, 0, 0, 0, 0, true, false, false, false, false,
|
||||
false, true,
|
||||
#ifdef JS_METHODJIT
|
||||
/* debugMode */
|
||||
false,
|
||||
#endif
|
||||
const_cast<jsbytecode*>(emptyScriptCode),
|
||||
false, true, const_cast<jsbytecode*>(emptyScriptCode),
|
||||
{0, NULL}, NULL, 0, 0, 0, NULL, {NULL},
|
||||
#ifdef CHECK_SCRIPT_OWNER
|
||||
reinterpret_cast<JSThread*>(1)
|
||||
@ -876,7 +871,6 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
|
||||
script = (JSScript *) cx->malloc(size);
|
||||
if (!script)
|
||||
return NULL;
|
||||
|
||||
PodZero(script);
|
||||
script->length = length;
|
||||
script->version = cx->version;
|
||||
|
@ -212,9 +212,6 @@ struct JSScript {
|
||||
bool warnedAboutTwoArgumentEval:1; /* have warned about use of
|
||||
obsolete eval(s, o) in
|
||||
this script */
|
||||
#ifdef JS_METHODJIT
|
||||
bool debugMode:1; /* script was compiled in debug mode */
|
||||
#endif
|
||||
|
||||
jsbytecode *main; /* main entry point, after predef'ing prolog */
|
||||
JSAtomMap atomMap; /* maps immediate index to literal struct */
|
||||
|
@ -45,8 +45,6 @@
|
||||
#include "jsnum.h"
|
||||
#include "jsregexp.h"
|
||||
#include "jswrapper.h"
|
||||
#include "methodjit/PolyIC.h"
|
||||
#include "assembler/jit/ExecutableAllocator.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
@ -291,26 +289,17 @@ TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, u
|
||||
}
|
||||
|
||||
JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
: rt(rt), principals(NULL), data(NULL), marked(false), debugMode(false)
|
||||
: rt(rt), principals(NULL), data(NULL), marked(false)
|
||||
{
|
||||
}
|
||||
|
||||
JSCompartment::~JSCompartment()
|
||||
{
|
||||
delete execPool;
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::init()
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
execPool = new JSC::ExecutableAllocator();
|
||||
if (!execPool)
|
||||
return false;
|
||||
|
||||
if (!jitScripts.init())
|
||||
return false;
|
||||
#endif
|
||||
return crossCompartmentWrappers.init();
|
||||
}
|
||||
|
||||
@ -485,48 +474,6 @@ JSCompartment::sweep(JSContext *cx)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
bool
|
||||
JSCompartment::addScript(JSContext *cx, JSScript *script)
|
||||
{
|
||||
ScriptSet::AddPtr ptr = jitScripts.lookupForAdd(script);
|
||||
if (!ptr.found()) {
|
||||
bool ok = jitScripts.add(ptr, script);
|
||||
if (!ok)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return ok;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::removeScript(JSScript *script)
|
||||
{
|
||||
ScriptSet::Ptr ptr = jitScripts.lookup(script);
|
||||
if (ptr.found())
|
||||
jitScripts.remove(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
JSCompartment::purge(JSContext *cx)
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
if (!cx->runtime->gcRegenShapes)
|
||||
return;
|
||||
|
||||
for (ScriptSet::Enum e(jitScripts); !e.empty(); e.popFront()) {
|
||||
# if defined JS_POLYIC
|
||||
JSScript *script = e.front();
|
||||
mjit::ic::PurgePICs(cx, script);
|
||||
# endif
|
||||
# if defined JS_MONOIC
|
||||
//mjit::ic::PurgeMICs(cx, script);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
SetupFakeFrame(JSContext *cx, ExecuteFrameGuard &frame, JSFrameRegs ®s, JSObject *obj)
|
||||
{
|
||||
|
@ -167,12 +167,8 @@ mjit::TryCompile(JSContext *cx, JSScript *script, JSFunction *fun, JSObject *sco
|
||||
JS_ASSERT(!script->isEmpty());
|
||||
|
||||
CompileStatus status = cc.Compile();
|
||||
if (status == Compile_Okay) {
|
||||
if (!cx->compartment->addScript(cx, script))
|
||||
status = Compile_Abort;
|
||||
} else {
|
||||
if (status != Compile_Okay)
|
||||
script->ncode = JS_UNJITTABLE_METHOD;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -418,10 +414,6 @@ mjit::Compiler::finishThisUp()
|
||||
}
|
||||
script->callSites = callSiteList;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
script->debugMode = cx->compartment->debugMode;
|
||||
#endif
|
||||
|
||||
return Compile_Okay;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ FrameState::init(uint32 nargs)
|
||||
}
|
||||
|
||||
uint32 nlocals = script->nslots;
|
||||
if ((eval = script->usesEval || cx->compartment->debugMode))
|
||||
if ((eval = script->usesEval))
|
||||
nlocals = 0;
|
||||
|
||||
uint8 *cursor = (uint8 *)cx->malloc(sizeof(FrameEntry) * nslots + // entries[]
|
||||
|
@ -578,6 +578,11 @@ ThreadData::Initialize()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!picScripts.init()) {
|
||||
delete execPool;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef JS_METHODJIT_PROFILE_STUBS
|
||||
for (size_t i = 0; i < STUB_CALLS_FOR_OP_COUNT; ++i)
|
||||
StubCallsForOp[i] = 0;
|
||||
@ -603,6 +608,43 @@ ThreadData::Finish()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ThreadData::addScript(JSScript *script)
|
||||
{
|
||||
ScriptSet::AddPtr p = picScripts.lookupForAdd(script);
|
||||
if (p)
|
||||
return true;
|
||||
return picScripts.add(p, script);
|
||||
}
|
||||
|
||||
void
|
||||
ThreadData::removeScript(JSScript *script)
|
||||
{
|
||||
ScriptSet::Ptr p = picScripts.lookup(script);
|
||||
if (p)
|
||||
picScripts.remove(p);
|
||||
}
|
||||
|
||||
void
|
||||
ThreadData::purge(JSContext *cx)
|
||||
{
|
||||
if (!cx->runtime->gcRegenShapes)
|
||||
return;
|
||||
|
||||
for (ThreadData::ScriptSet::Enum e(picScripts); !e.empty(); e.popFront()) {
|
||||
#if defined JS_POLYIC
|
||||
JSScript *script = e.front();
|
||||
ic::PurgePICs(cx, script);
|
||||
#endif
|
||||
#if defined JS_MONOIC
|
||||
//PurgeMICs(cs, script);
|
||||
#endif
|
||||
}
|
||||
|
||||
picScripts.clear();
|
||||
}
|
||||
|
||||
|
||||
extern "C" JSBool JaegerTrampoline(JSContext *cx, JSStackFrame *fp, void *code,
|
||||
uintptr_t inlineCallCount);
|
||||
|
||||
@ -683,7 +725,6 @@ mjit::ReleaseScriptCode(JSContext *cx, JSScript *script)
|
||||
script->inlineLength = 0;
|
||||
script->outOfLineLength = 0;
|
||||
|
||||
cx->compartment->removeScript(script);
|
||||
#if defined JS_POLYIC
|
||||
if (script->pics) {
|
||||
uint32 npics = script->numPICs();
|
||||
@ -691,6 +732,7 @@ mjit::ReleaseScriptCode(JSContext *cx, JSScript *script)
|
||||
script->pics[i].releasePools();
|
||||
Destroy(script->pics[i].execPools);
|
||||
}
|
||||
JS_METHODJIT_DATA(cx).removeScript(script);
|
||||
cx->free((uint8*)script->pics - sizeof(uint32));
|
||||
}
|
||||
#endif
|
||||
|
@ -131,7 +131,8 @@ class PICStubCompiler
|
||||
|
||||
JSC::ExecutablePool *getExecPool(size_t size)
|
||||
{
|
||||
return f.cx->compartment->execPool->poolForSize(size);
|
||||
mjit::ThreadData *jd = &JS_METHODJIT_DATA(f.cx);
|
||||
return jd->execPool->poolForSize(size);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -685,6 +686,12 @@ class GetPropCompiler : public PICStubCompiler
|
||||
if (!f.fp->script->compileAndGo)
|
||||
return disable("String.prototype without compile-and-go");
|
||||
|
||||
mjit::ThreadData &jm = JS_METHODJIT_DATA(f.cx);
|
||||
if (!jm.addScript(script)) {
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject *holder;
|
||||
JSProperty *prop;
|
||||
if (!obj->lookupProperty(f.cx, ATOM_TO_JSID(atom), &holder, &prop))
|
||||
@ -807,6 +814,12 @@ class GetPropCompiler : public PICStubCompiler
|
||||
spew("patch", "inline");
|
||||
PICRepatchBuffer repatcher(pic, pic.fastPathStart);
|
||||
|
||||
mjit::ThreadData &jm = JS_METHODJIT_DATA(f.cx);
|
||||
if (!jm.addScript(script)) {
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 offset;
|
||||
if (sprop->slot < JS_INITIAL_NSLOTS) {
|
||||
JSC::CodeLocationInstruction istr;
|
||||
|
@ -96,8 +96,7 @@ Recompiler::applyPatch(Compiler& c, PatchableAddress& toPatch)
|
||||
*toPatch.location = result;
|
||||
}
|
||||
|
||||
Recompiler::Recompiler(JSContext *cx, JSScript *script)
|
||||
: cx(cx), script(script)
|
||||
Recompiler::Recompiler(JSContext *cx, JSScript *script) : cx(cx), script(script)
|
||||
{
|
||||
}
|
||||
|
||||
@ -122,14 +121,17 @@ Recompiler::recompile()
|
||||
|
||||
/* Scan the stack, saving the ncode elements of the frames. */
|
||||
JSStackFrame *firstFrame = NULL;
|
||||
for (AllFramesIter i(cx); !i.done(); ++i) {
|
||||
if (!firstFrame && i.fp()->script == script)
|
||||
firstFrame = i.fp();
|
||||
if (script->isValidJitCode(i.fp()->ncode)) {
|
||||
if (!toPatch.append(findPatch(&i.fp()->ncode)))
|
||||
for (CallStackIterator cs(cx); !cs.done(); ++cs) {
|
||||
FrameIterator fp = cs.top();
|
||||
for (FrameIterator fp = cs.top(); fp != cs.bottom(); ++fp) {
|
||||
if (!firstFrame && fp.fp()->script == script)
|
||||
firstFrame = fp.fp();
|
||||
if (script->isValidJitCode(fp.fp()->ncode)) {
|
||||
if (!toPatch.append(findPatch(&fp.fp()->ncode)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate over VMFrames saving the machine and scripted return. */
|
||||
for (VMFrame *f = JS_METHODJIT_DATA(cx).activeFrame;
|
||||
@ -142,11 +144,10 @@ Recompiler::recompile()
|
||||
}
|
||||
|
||||
void **machineReturn = f->returnAddressLocation();
|
||||
if (script->isValidJitCode(*machineReturn)) {
|
||||
if (script->isValidJitCode(*machineReturn))
|
||||
if (!toPatch.append(findPatch(machineReturn)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseScriptCode(cx, script);
|
||||
|
||||
@ -154,9 +155,6 @@ Recompiler::recompile()
|
||||
if (!firstFrame)
|
||||
return true;
|
||||
|
||||
/* If we get this far, the script is live, and we better be safe to re-jit. */
|
||||
JS_ASSERT(cx->compartment->debugMode);
|
||||
|
||||
Compiler c(cx, script, firstFrame->fun, firstFrame->scopeChain);
|
||||
if (c.Compile() != Compile_Okay)
|
||||
return false;
|
||||
@ -168,6 +166,42 @@ Recompiler::recompile()
|
||||
return true;
|
||||
}
|
||||
|
||||
FrameIterator&
|
||||
FrameIterator::operator++() {
|
||||
JS_ASSERT(curfp);
|
||||
curfp = curfp->down;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
FrameIterator::operator==(const FrameIterator& other) const {
|
||||
return curfp == other.curfp;
|
||||
}
|
||||
|
||||
bool
|
||||
FrameIterator::operator!=(const FrameIterator& other) const {
|
||||
return curfp != other.curfp;
|
||||
}
|
||||
|
||||
CallStackIterator&
|
||||
CallStackIterator::operator++() {
|
||||
JS_ASSERT(curcs);
|
||||
curcs = curcs->getPreviousInMemory();
|
||||
return *this;
|
||||
}
|
||||
|
||||
FrameIterator
|
||||
CallStackIterator::top() const {
|
||||
JS_ASSERT(curcs);
|
||||
return FrameIterator(curcs->getCurrentFrame());
|
||||
}
|
||||
|
||||
FrameIterator
|
||||
CallStackIterator::bottom() const {
|
||||
JS_ASSERT(curcs);
|
||||
return FrameIterator(curcs->getInitialFrame()->down);
|
||||
}
|
||||
|
||||
} /* namespace mjit */
|
||||
} /* namespace js */
|
||||
|
||||
|
@ -101,6 +101,41 @@ private:
|
||||
void applyPatch(Compiler& c, PatchableAddress& toPatch);
|
||||
};
|
||||
|
||||
/*
|
||||
* Utility classes to make iteration over the stack clean.
|
||||
*/
|
||||
class FrameIterator
|
||||
{
|
||||
public:
|
||||
FrameIterator(JSStackFrame *frame) : curfp(frame) { };
|
||||
|
||||
bool done() const { return curfp == NULL; }
|
||||
FrameIterator& operator++();
|
||||
bool operator==(const FrameIterator& other) const;
|
||||
bool operator!=(const FrameIterator& other) const;
|
||||
|
||||
JSStackFrame *fp() const { return curfp; }
|
||||
|
||||
private:
|
||||
JSStackFrame *curfp;
|
||||
};
|
||||
|
||||
class CallStackIterator
|
||||
{
|
||||
public:
|
||||
CallStackIterator(JSContext *cx) : curcs(cx->stack().getCurrentSegment()) { };
|
||||
|
||||
bool done() const { return curcs == NULL; }
|
||||
CallStackIterator& operator++();
|
||||
FrameIterator top() const;
|
||||
FrameIterator bottom() const;
|
||||
|
||||
CallStackSegment *cs() const { return curcs; }
|
||||
|
||||
private:
|
||||
CallStackSegment *curcs;
|
||||
};
|
||||
|
||||
} /* namespace mjit */
|
||||
} /* namespace js */
|
||||
|
||||
|
@ -1462,20 +1462,6 @@ ValueToScript(JSContext *cx, jsval v)
|
||||
return script;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
SetDebug(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
if (argc == 0 || !JSVAL_IS_BOOLEAN(argv[0])) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
|
||||
JSSMSG_NOT_ENOUGH_ARGS, "setDebug");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
js_SetDebugMode(cx, JSVAL_TO_BOOLEAN(argv[0]));
|
||||
*rval = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
|
||||
int32 *ip)
|
||||
@ -3947,7 +3933,6 @@ static JSFunctionSpec shell_functions[] = {
|
||||
#ifdef JS_GC_ZEAL
|
||||
JS_FN("gczeal", GCZeal, 1,0),
|
||||
#endif
|
||||
JS_FS("setDebug", SetDebug, 1,0,0),
|
||||
JS_FS("trap", Trap, 3,0,0),
|
||||
JS_FS("untrap", Untrap, 2,0,0),
|
||||
JS_FS("line2pc", LineToPC, 0,0,0),
|
||||
@ -4049,7 +4034,6 @@ static const char *const shell_help_messages[] = {
|
||||
#ifdef JS_GC_ZEAL
|
||||
"gczeal(level) How zealous the garbage collector should be",
|
||||
#endif
|
||||
"setDebug(debug) Set debug mode",
|
||||
"trap([fun, [pc,]] exp) Trap bytecode execution",
|
||||
"untrap(fun[, pc]) Remove a trap",
|
||||
"line2pc([fun,] line) Map line number to PC",
|
||||
|
@ -1,36 +0,0 @@
|
||||
setDebug(true);
|
||||
var a = new Array();
|
||||
|
||||
function i(save) {
|
||||
var x = 9;
|
||||
evalInFrame(0, "a.push(x)", save);
|
||||
evalInFrame(1, "a.push(z)", save);
|
||||
evalInFrame(2, "a.push(z)", save);
|
||||
evalInFrame(3, "a.push(y)", save);
|
||||
evalInFrame(4, "a.push(x)", save);
|
||||
}
|
||||
|
||||
function h() {
|
||||
var z = 5;
|
||||
evalInFrame(0, "a.push(z)");
|
||||
evalInFrame(1, "a.push(y)");
|
||||
evalInFrame(2, "a.push(x)");
|
||||
evalInFrame(0, "i(false)");
|
||||
evalInFrame(0, "a.push(z)", true);
|
||||
evalInFrame(1, "a.push(y)", true);
|
||||
evalInFrame(2, "a.push(x)", true);
|
||||
evalInFrame(0, "i(true)", true);
|
||||
}
|
||||
|
||||
function g() {
|
||||
var y = 4;
|
||||
h();
|
||||
}
|
||||
|
||||
function f() {
|
||||
var x = 3;
|
||||
g();
|
||||
}
|
||||
|
||||
f();
|
||||
assertEq(a+'', [5, 4, 3, 9, 5, 5, 4, 3, 5, 4, 3, 9, 5, 5, 4, 3]+'');
|
@ -1,13 +0,0 @@
|
||||
setDebug(true);
|
||||
|
||||
function callee() {
|
||||
assertJit();
|
||||
evalInFrame(1, "var x = 'success'");
|
||||
}
|
||||
function caller() {
|
||||
assertJit();
|
||||
callee();
|
||||
return x;
|
||||
}
|
||||
assertEq(caller(), "success");
|
||||
assertEq(typeof x, "undefined");
|
@ -1,13 +0,0 @@
|
||||
setDebug(true);
|
||||
|
||||
function callee() {
|
||||
assertJit();
|
||||
evalInFrame(1, "x = 'success'");
|
||||
}
|
||||
function caller() {
|
||||
assertJit();
|
||||
var x = ({ dana : "zuul" });
|
||||
callee();
|
||||
return x;
|
||||
}
|
||||
assertEq(caller(), "success");
|
@ -1,13 +0,0 @@
|
||||
setDebug(true);
|
||||
|
||||
function callee() {
|
||||
assertJit();
|
||||
evalInFrame(1, "x = 'success'");
|
||||
}
|
||||
function caller() {
|
||||
assertJit();
|
||||
var x = "failure";
|
||||
callee();
|
||||
return x;
|
||||
}
|
||||
assertEq(caller(), "success");
|
@ -1,9 +0,0 @@
|
||||
setDebug(true);
|
||||
|
||||
__defineGetter__("someProperty", function () { evalInFrame(1, "var x = 'success'"); });
|
||||
function caller(obj) {
|
||||
assertJit();
|
||||
obj.someProperty;
|
||||
return x;
|
||||
}
|
||||
assertEq(caller(this), "success");
|
@ -1,10 +0,0 @@
|
||||
setDebug(true);
|
||||
|
||||
__defineGetter__("someProperty", function () { evalInFrame(1, "var x = 'success'"); });
|
||||
function caller(obj) {
|
||||
assertJit();
|
||||
var x = ({ dana : 'zuul' });
|
||||
obj.someProperty;
|
||||
return x;
|
||||
}
|
||||
assertEq(caller(this), "success");
|
@ -1,10 +0,0 @@
|
||||
setDebug(true);
|
||||
|
||||
__defineGetter__("someProperty", function () { evalInFrame(1, "x = 'success'"); });
|
||||
function caller(obj) {
|
||||
assertJit();
|
||||
var x = "failure";
|
||||
obj.someProperty;
|
||||
return x;
|
||||
}
|
||||
assertEq(caller(this), "success");
|
@ -1,9 +0,0 @@
|
||||
setDebug(true);
|
||||
|
||||
function nop(){}
|
||||
function caller(obj) {
|
||||
assertJit();
|
||||
return x;
|
||||
}
|
||||
trap(caller, 9, "var x = 'success'; nop()");
|
||||
assertEq(caller(this), "success");
|
@ -1,10 +0,0 @@
|
||||
setDebug(true);
|
||||
|
||||
function nop(){}
|
||||
function caller(obj) {
|
||||
assertJit();
|
||||
var x = ({ dana : "zuul" });
|
||||
return x;
|
||||
}
|
||||
trap(caller, 22, "x = 'success'; nop()");
|
||||
assertEq(caller(this), "success");
|
@ -1,10 +0,0 @@
|
||||
setDebug(true);
|
||||
|
||||
function nop(){}
|
||||
function caller(obj) {
|
||||
assertJit();
|
||||
var x = "failure";
|
||||
return x;
|
||||
}
|
||||
trap(caller, 16, "x = 'success'; nop()");
|
||||
assertEq(caller(this), "success");
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
var x = "failure";
|
||||
function main() { x = "success"; }
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
var x = "notset";
|
||||
function main() { x = "failure"; }
|
||||
function success() { x = "success"; }
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
var x = "notset";
|
||||
function main() { x = "success"; }
|
||||
function failure() { x = "failure"; }
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
function main() {
|
||||
return "failure";
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
function main() {
|
||||
return 1;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
x = "notset";
|
||||
function myparent(nested) {
|
||||
if (nested) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
x = "notset";
|
||||
|
||||
function child() {
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
x = "notset";
|
||||
function child() {
|
||||
/* JSOP_STOP in parent. */
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
x = "notset";
|
||||
|
||||
function myparent(nested) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
x = "notset";
|
||||
|
||||
function doNothing() { }
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
x = "notset";
|
||||
function main() {
|
||||
/* The JSOP_STOP in a. */
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
x = "notset";
|
||||
function child() {
|
||||
/* JSOP_STOP in parent */
|
||||
|
@ -1,4 +1,3 @@
|
||||
setDebug(true);
|
||||
x = "notset";
|
||||
function main() {
|
||||
/* JSOP_STOP in main. */
|
||||
|
Loading…
Reference in New Issue
Block a user