mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset a8aeff259925 and fix due to random crashes.
This commit is contained in:
parent
e4ec6d69ff
commit
ebfb6d0eca
@ -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 be called only 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);
|
||||
/* FIXME: bug 586161 */
|
||||
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,
|
||||
@ -1253,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. */
|
||||
JSCList scripts;
|
||||
#endif
|
||||
|
||||
JSCompartment(JSRuntime *cx);
|
||||
~JSCompartment();
|
||||
@ -1278,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,78 +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 (JSScript *script = (JSScript *)cx->compartment->scripts.next;
|
||||
&script->links != &cx->compartment->scripts;
|
||||
script = (JSScript *)script->links.next) {
|
||||
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.
|
||||
*/
|
||||
@ -223,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");
|
||||
@ -1446,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;
|
||||
@ -1483,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
|
||||
|
@ -74,15 +74,9 @@ using namespace js;
|
||||
static const jsbytecode emptyScriptCode[] = {JSOP_STOP, SRC_NULL};
|
||||
|
||||
/* static */ const JSScript JSScript::emptyScriptConst = {
|
||||
JS_INIT_STATIC_CLIST(NULL),
|
||||
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)
|
||||
@ -877,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;
|
||||
@ -987,8 +980,6 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
|
||||
#ifdef CHECK_SCRIPT_OWNER
|
||||
script->owner = cx->thread;
|
||||
#endif
|
||||
|
||||
JS_APPEND_LINK(&script->links, &cx->compartment->scripts);
|
||||
return script;
|
||||
}
|
||||
|
||||
@ -1259,7 +1250,6 @@ js_DestroyScript(JSContext *cx, JSScript *script)
|
||||
#if defined(JS_METHODJIT)
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
#endif
|
||||
JS_REMOVE_LINK(&script->links);
|
||||
|
||||
cx->free(script);
|
||||
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "jsatom.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsclist.h"
|
||||
|
||||
/*
|
||||
* Type of try note associated with each catch or finally block, and also with
|
||||
@ -185,8 +184,6 @@ union CallSite;
|
||||
#endif
|
||||
|
||||
struct JSScript {
|
||||
/* FIXME: bug 586181 */
|
||||
JSCList links; /* Links for compartment script list */
|
||||
jsbytecode *code; /* bytecodes and their immediate operands */
|
||||
uint32 length; /* length of code vector */
|
||||
uint16 version; /* JS version under which script was compiled */
|
||||
@ -215,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,24 +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)
|
||||
{
|
||||
JS_INIT_CLIST(&scripts);
|
||||
}
|
||||
|
||||
JSCompartment::~JSCompartment()
|
||||
{
|
||||
delete execPool;
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::init()
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
execPool = new JSC::ExecutableAllocator();
|
||||
if (!execPool)
|
||||
return false;
|
||||
#endif
|
||||
return crossCompartmentWrappers.init();
|
||||
}
|
||||
|
||||
@ -483,26 +474,6 @@ JSCompartment::sweep(JSContext *cx)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::purge(JSContext *cx)
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
if (!cx->runtime->gcRegenShapes)
|
||||
return;
|
||||
|
||||
for (JSScript *script = (JSScript *)scripts.next;
|
||||
&script->links != &scripts;
|
||||
script = (JSScript *)script->links.next) {
|
||||
# if defined JS_POLYIC
|
||||
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)
|
||||
{
|
||||
|
@ -337,8 +337,6 @@ mjit::Compiler::finishThisUp()
|
||||
*(uint32*)cursor = pics.length();
|
||||
cursor += sizeof(uint32);
|
||||
script->pics = (ic::PICInfo *)cursor;
|
||||
} else {
|
||||
script->pics = NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pics.length(); i++) {
|
||||
@ -415,10 +413,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[]
|
||||
|
@ -580,6 +580,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;
|
||||
@ -605,6 +610,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);
|
||||
|
||||
@ -692,6 +734,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
|
||||
|
@ -128,7 +128,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:
|
||||
@ -683,6 +684,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))
|
||||
@ -808,6 +815,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,12 +121,15 @@ 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)))
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,10 +144,9 @@ 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 */
|
||||
|
||||
|
@ -1470,20 +1470,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)
|
||||
@ -3997,7 +3983,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),
|
||||
@ -4103,7 +4088,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