This commit is contained in:
David Mandelin 2010-08-06 11:41:42 -07:00
commit 314a2c0c91
39 changed files with 161 additions and 418 deletions

View File

@ -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")

View File

@ -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);

View File

@ -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, &regexpPool);
/* :XXX: Is this the right place for this? */
compartment->purge(this);
}
namespace js {
void

View File

@ -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 {

View File

@ -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");
@ -311,7 +237,7 @@ JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler *handlerp, jsval *closurep)
{
JSTrap *trap;
DBG_LOCK(cx->runtime);
trap = FindTrap(cx->runtime, script, pc);
if (handlerp)
@ -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;
@ -1483,9 +1406,6 @@ JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
jschar *chars;
JSBool ok;
size_t len = length;
if (!CheckDebugMode(cx))
return JS_FALSE;
chars = js_InflateString(cx, bytes, &len);
if (!chars)

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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 &regs, JSObject *obj)
{

View File

@ -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;
}

View File

@ -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[]

View File

@ -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);
@ -682,8 +724,7 @@ mjit::ReleaseScriptCode(JSContext *cx, JSScript *script)
script->ncode = NULL;
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

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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",

View File

@ -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]+'');

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -1,4 +1,3 @@
setDebug(true);
var x = "failure";
function main() { x = "success"; }

View File

@ -1,4 +1,3 @@
setDebug(true);
var x = "notset";
function main() { x = "failure"; }
function success() { x = "success"; }

View File

@ -1,4 +1,3 @@
setDebug(true);
var x = "notset";
function main() { x = "success"; }
function failure() { x = "failure"; }

View File

@ -1,4 +1,3 @@
setDebug(true);
function main() {
return "failure";
}

View File

@ -1,4 +1,3 @@
setDebug(true);
function main() {
return 1;
}

View File

@ -1,4 +1,3 @@
setDebug(true);
x = "notset";
function myparent(nested) {
if (nested) {

View File

@ -1,4 +1,3 @@
setDebug(true);
x = "notset";
function child() {

View File

@ -1,4 +1,3 @@
setDebug(true);
x = "notset";
function child() {
/* JSOP_STOP in parent. */

View File

@ -1,4 +1,3 @@
setDebug(true);
x = "notset";
function myparent(nested) {

View File

@ -1,4 +1,3 @@
setDebug(true);
x = "notset";
function doNothing() { }

View File

@ -1,4 +1,3 @@
setDebug(true);
x = "notset";
function main() {
/* The JSOP_STOP in a. */

View File

@ -1,4 +1,3 @@
setDebug(true);
x = "notset";
function child() {
/* JSOP_STOP in parent */

View File

@ -1,4 +1,3 @@
setDebug(true);
x = "notset";
function main() {
/* JSOP_STOP in main. */