mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-02 07:05:24 +00:00
[JAEGER] Merge.
This commit is contained in:
commit
7357103c6c
@ -320,7 +320,7 @@ CPPSRCS += MethodJIT.cpp \
|
||||
|
||||
ifeq (86, $(findstring 86,$(TARGET_CPU)))
|
||||
ifeq (x86_64, $(TARGET_CPU))
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifdef _MSC_VER
|
||||
ASFILES += TrampolineMasmX64.asm
|
||||
endif
|
||||
ifdef SOLARIS_SUNPRO_CXX
|
||||
|
@ -1115,12 +1115,21 @@ private:
|
||||
int flags_edx = 0;
|
||||
int flags_ecx = 0;
|
||||
#if WTF_COMPILER_MSVC
|
||||
#if WTF_CPU_X86_64
|
||||
extern void __cpuid(int a[4], int b);
|
||||
int cpuinfo[4];
|
||||
|
||||
__cpuid(cpuinfo, 1);
|
||||
flags_ecx = cpuinfo[2];
|
||||
flags_edx = cpuinfo[3];
|
||||
#else
|
||||
_asm {
|
||||
mov eax, 1 // cpuid function 1 gives us the standard feature set
|
||||
cpuid;
|
||||
mov flags_ecx, ecx;
|
||||
mov flags_edx, edx;
|
||||
}
|
||||
#endif
|
||||
#elif WTF_COMPILER_GCC
|
||||
asm (
|
||||
"movl $0x1, %%eax;"
|
||||
|
@ -849,7 +849,9 @@ public:
|
||||
#if WTF_CPU_X86_64
|
||||
void xorq_rr(RegisterID src, RegisterID dst)
|
||||
{
|
||||
FIXME_INSN_PRINTING;
|
||||
js::JaegerSpew(js::JSpew_Insns,
|
||||
IPFX "xorq %s, %s\n", MAYBE_PAD,
|
||||
nameIReg(4,src), nameIReg(4, dst));
|
||||
m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst);
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ static void printf_stderr_common(const char* format, ...)
|
||||
|
||||
static void printCallSite(const char* file, int line, const char* function)
|
||||
{
|
||||
#if WTF_PLATFORM_WIN && !WTF_PLATFORM_WINCE && defined _DEBUG
|
||||
#if WTF_COMPILER_MSVC && !WTF_PLATFORM_WINCE && defined _DEBUG
|
||||
_CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
|
||||
#else
|
||||
printf_stderr_common("(%s:%d %s)\n", file, line, function);
|
||||
|
@ -2058,6 +2058,9 @@ ia64*-hpux*)
|
||||
HOST_CC='$(CC)'
|
||||
HOST_CXX='$(CXX)'
|
||||
HOST_LD='$(LD)'
|
||||
if test "$AS_BIN"; then
|
||||
AS="$(basename "$AS_BIN")"
|
||||
fi
|
||||
AR='lib -NOLOGO -OUT:"$@"'
|
||||
AR_FLAGS=
|
||||
RANLIB='echo not_ranlib'
|
||||
@ -2067,6 +2070,7 @@ ia64*-hpux*)
|
||||
UNZIP=unzip
|
||||
DOXYGEN=:
|
||||
GARBAGE='$(OBJDIR)/vc20.pdb $(OBJDIR)/vc40.pdb'
|
||||
ASM_SUFFIX=asm
|
||||
OBJ_SUFFIX=obj
|
||||
LIB_SUFFIX=lib
|
||||
DLL_PREFIX=
|
||||
|
@ -68,6 +68,8 @@ BEGIN_TEST(testContexts_bug561444)
|
||||
JS_BeginRequest(cx);
|
||||
{
|
||||
jsvalRoot v(cx);
|
||||
JSAutoCrossCompartmentCall crossCall;
|
||||
crossCall.enter(cx, d->obj);
|
||||
if (!JS_EvaluateScript(cx, d->obj, d->code, strlen(d->code), __FILE__, __LINE__, v.addr()))
|
||||
return;
|
||||
}
|
||||
|
@ -4414,6 +4414,10 @@ JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *prin
|
||||
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT;
|
||||
JSScript *script = Compiler::compileScript(cx, obj, NULL, principals, tcflags,
|
||||
chars, length, NULL, filename, lineno);
|
||||
if (script && !js_NewScriptObject(cx, script)) {
|
||||
js_DestroyScript(cx, script);
|
||||
script = NULL;
|
||||
}
|
||||
LAST_FRAME_CHECKS(cx, script);
|
||||
return script;
|
||||
}
|
||||
@ -4509,11 +4513,15 @@ JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
|
||||
tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT;
|
||||
script = Compiler::compileScript(cx, obj, NULL, NULL, tcflags,
|
||||
NULL, 0, fp, filename, 1);
|
||||
if (fp != stdin)
|
||||
fclose(fp);
|
||||
if (script && !js_NewScriptObject(cx, script)) {
|
||||
js_DestroyScript(cx, script);
|
||||
script = NULL;
|
||||
}
|
||||
LAST_FRAME_CHECKS(cx, script);
|
||||
return script;
|
||||
}
|
||||
@ -4527,9 +4535,13 @@ JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj, const char *file
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, principals);
|
||||
tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
|
||||
tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT;
|
||||
script = Compiler::compileScript(cx, obj, NULL, principals, tcflags,
|
||||
NULL, 0, file, filename, 1);
|
||||
if (script && !js_NewScriptObject(cx, script)) {
|
||||
js_DestroyScript(cx, script);
|
||||
script = NULL;
|
||||
}
|
||||
LAST_FRAME_CHECKS(cx, script);
|
||||
return script;
|
||||
}
|
||||
@ -4543,34 +4555,29 @@ JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, FILE *f
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_NewScriptObject(JSContext *cx, JSScript *script)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, script);
|
||||
if (!script)
|
||||
return NewNonFunction<WithProto::Class>(cx, &js_ScriptClass, NULL, NULL);
|
||||
|
||||
JS_ASSERT(!script->u.object);
|
||||
|
||||
{
|
||||
AutoScriptRooter root(cx, script);
|
||||
|
||||
obj = NewNonFunction<WithProto::Class>(cx, &js_ScriptClass, NULL, NULL);
|
||||
if (obj) {
|
||||
obj->setPrivate(script);
|
||||
script->u.object = obj;
|
||||
#ifdef CHECK_SCRIPT_OWNER
|
||||
script->owner = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
/*
|
||||
* This function should only ever be applied to JSScripts that had
|
||||
* script objects allocated for them when they were created, as
|
||||
* described in the comment for JSScript::u.object.
|
||||
*/
|
||||
JS_ASSERT(script->u.object);
|
||||
return script->u.object;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetScriptObject(JSScript *script)
|
||||
{
|
||||
/*
|
||||
* This function should only ever be applied to JSScripts that had
|
||||
* script objects allocated for them when they were created, as
|
||||
* described in the comment for JSScript::u.object.
|
||||
*/
|
||||
JS_ASSERT(script->u.object);
|
||||
return script->u.object;
|
||||
}
|
||||
|
||||
@ -4578,8 +4585,17 @@ JS_PUBLIC_API(void)
|
||||
JS_DestroyScript(JSContext *cx, JSScript *script)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, script);
|
||||
js_DestroyScript(cx, script);
|
||||
|
||||
/*
|
||||
* Originally, JSScript lifetimes were managed explicitly, and this function
|
||||
* was used to free a JSScript. Now, this function does nothing, and the
|
||||
* garbage collector manages JSScripts; you must root the JSScript's script
|
||||
* object (obtained via JS_GetScriptObject) to keep it alive.
|
||||
*
|
||||
* However, since the script objects have taken over this responsibility, it
|
||||
* follows that every script passed here must have a script object.
|
||||
*/
|
||||
JS_ASSERT(script->u.object);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
@ -4741,6 +4757,8 @@ JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, script);
|
||||
/* This should receive only scripts handed out via the JSAPI. */
|
||||
JS_ASSERT(script == JSScript::emptyScript() || script->u.object);
|
||||
ok = Execute(cx, obj, script, NULL, 0, Valueify(rval));
|
||||
LAST_FRAME_CHECKS(cx, ok);
|
||||
return ok;
|
||||
@ -4768,7 +4786,7 @@ JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
|
||||
}
|
||||
ok = Execute(cx, obj, script, NULL, 0, Valueify(rval));
|
||||
LAST_FRAME_CHECKS(cx, ok);
|
||||
JS_DestroyScript(cx, script);
|
||||
js_DestroyScript(cx, script);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ namespace mjit {
|
||||
{
|
||||
void (* forceReturn)();
|
||||
JSC::ExecutablePool *forceReturnPool;
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
|
||||
void (* forceReturnFast)();
|
||||
JSC::ExecutablePool *forceReturnFastPool;
|
||||
#endif
|
||||
|
@ -384,8 +384,10 @@ JS_REQUIRES_STACK inline
|
||||
FrameRegsIter::FrameRegsIter(JSContext *cx)
|
||||
{
|
||||
curseg = cx->getCurrentSegment();
|
||||
if (JS_UNLIKELY(!curseg || !curseg->isActive()))
|
||||
if (JS_UNLIKELY(!curseg || !curseg->isActive())) {
|
||||
initSlow();
|
||||
return;
|
||||
}
|
||||
JS_ASSERT(cx->fp);
|
||||
curfp = cx->fp;
|
||||
cursp = cx->regs->sp;
|
||||
|
@ -293,7 +293,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
|
||||
stackDepth = 0;
|
||||
valueCount = 0;
|
||||
for (fp = js_GetTopStackFrame(cx); fp; fp = fp->down) {
|
||||
if (fp->hasFunction() && fp->argv) {
|
||||
if (fp->hasFunction() && fp->argv && !fp->isEvalFrame()) {
|
||||
Value v = NullValue();
|
||||
if (checkAccess &&
|
||||
!checkAccess(cx, fp->callee(), callerid, JSACC_READ, &v)) {
|
||||
@ -334,7 +334,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
|
||||
values = GetStackTraceValueBuffer(priv);
|
||||
elem = priv->stackElems;
|
||||
for (fp = js_GetTopStackFrame(cx); fp != fpstop; fp = fp->down) {
|
||||
if (!fp->hasFunction()) {
|
||||
if (!fp->hasFunction() || fp->isEvalFrame()) {
|
||||
elem->funName = NULL;
|
||||
elem->argc = 0;
|
||||
} else {
|
||||
|
@ -874,12 +874,13 @@ Execute(JSContext *cx, JSObject *chain, JSScript *script,
|
||||
JSObject *initialVarObj;
|
||||
if (down) {
|
||||
/* Propagate arg state for eval and the debugger API. */
|
||||
JS_ASSERT_IF(down->hasFunction(), down->hasCallObj());
|
||||
fp->setCallObj(down->maybeCallObj());
|
||||
fp->setArgsObj(NULL);
|
||||
fp->setFunction((script->staticLevel > 0) ? down->maybeFunction() : NULL);
|
||||
fp->setThisValue(down->getThisValue());
|
||||
fp->flags = flags;
|
||||
fp->setNumActualArgs(down->numActualArgs());
|
||||
fp->setNumActualArgs(0);
|
||||
fp->argv = down->argv;
|
||||
fp->setAnnotation(down->maybeAnnotation());
|
||||
fp->setScopeChain(chain);
|
||||
|
@ -185,6 +185,7 @@ struct JSStackFrame
|
||||
|
||||
JSObject* getArgsObj() const {
|
||||
JS_ASSERT(hasArgsObj());
|
||||
JS_ASSERT(!isEvalFrame());
|
||||
return argsobj;
|
||||
}
|
||||
|
||||
@ -409,6 +410,7 @@ struct JSStackFrame
|
||||
}
|
||||
|
||||
size_t numFormalArgs() const {
|
||||
JS_ASSERT(!isEvalFrame());
|
||||
return getFunction()->nargs;
|
||||
}
|
||||
|
||||
@ -455,6 +457,7 @@ struct JSStackFrame
|
||||
/* Argument count accessors */
|
||||
|
||||
size_t numActualArgs() const {
|
||||
JS_ASSERT(!isEvalFrame());
|
||||
return argc;
|
||||
}
|
||||
|
||||
@ -528,6 +531,7 @@ struct JSStackFrame
|
||||
}
|
||||
|
||||
bool isDummyFrame() const { return !!(flags & JSFRAME_DUMMY); }
|
||||
bool isEvalFrame() const { return !!(flags & JSFRAME_EVAL); }
|
||||
|
||||
private:
|
||||
JSObject *computeThisObject(JSContext *cx);
|
||||
|
@ -102,7 +102,7 @@ JS_END_EXTERN_C
|
||||
static JS_ALWAYS_INLINE int
|
||||
NativeCompareAndSwap(volatile jsword *w, jsword ov, jsword nv)
|
||||
{
|
||||
return _InterlockedCompareExchange64(w, nv, ov) == ov;
|
||||
return _InterlockedCompareExchange64((long long *volatile)w, nv, ov) == ov;
|
||||
}
|
||||
|
||||
#elif defined(XP_MACOSX) || defined(DARWIN)
|
||||
|
@ -6082,8 +6082,11 @@ JSObject::getCompartment(JSContext *cx)
|
||||
return cx->runtime->defaultCompartment;
|
||||
}
|
||||
|
||||
// Compile-time Function, Block, and RegExp objects are not parented.
|
||||
if (clasp == &js_FunctionClass || clasp == &js_BlockClass || clasp == &js_RegExpClass) {
|
||||
/*
|
||||
* Script objects and compile-time Function, Block, RegExp objects
|
||||
* are not parented.
|
||||
*/
|
||||
if (clasp == &js_FunctionClass || clasp == &js_BlockClass || clasp == &js_RegExpClass || clasp == &js_ScriptClass) {
|
||||
// This is a bogus answer, but it'll do for now.
|
||||
return cx->runtime->defaultCompartment;
|
||||
}
|
||||
|
@ -1322,6 +1322,33 @@ js_TraceScript(JSTracer *trc, JSScript *script)
|
||||
js_MarkScriptFilename(script->filename);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NewScriptObject(JSContext *cx, JSScript *script)
|
||||
{
|
||||
AutoScriptRooter root(cx, script);
|
||||
|
||||
JS_ASSERT(!script->u.object);
|
||||
JS_ASSERT(script != JSScript::emptyScript());
|
||||
|
||||
JSObject *obj = NewNonFunction<WithProto::Class>(cx, &js_ScriptClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
obj->setPrivate(script);
|
||||
script->u.object = obj;
|
||||
|
||||
/*
|
||||
* Clear the object's proto, to avoid entraining stuff. Once we no longer use the parent
|
||||
* for security checks, then we can clear the parent, too.
|
||||
*/
|
||||
obj->clearProto();
|
||||
|
||||
#ifdef CHECK_SCRIPT_OWNER
|
||||
script->owner = NULL;
|
||||
#endif
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
typedef struct GSNCacheEntry {
|
||||
JSDHashEntryHdr hdr;
|
||||
jsbytecode *pc;
|
||||
|
@ -227,7 +227,23 @@ struct JSScript {
|
||||
uint16 staticLevel;/* static level for display maintenance */
|
||||
JSPrincipals *principals;/* principals for this script */
|
||||
union {
|
||||
JSObject *object; /* optional Script-class object wrapper */
|
||||
/*
|
||||
* A script object of class js_ScriptClass, to ensure the script is GC'd.
|
||||
* - All scripts returned by JSAPI functions (JS_CompileScript,
|
||||
* JS_CompileFile, etc.) have these objects.
|
||||
* - Function scripts never have script objects; such scripts are owned
|
||||
* by their function objects.
|
||||
* - Temporary scripts created by obj_eval, JS_EvaluateScript, and
|
||||
* similar functions never have these objects; such scripts are
|
||||
* explicitly destroyed by the code that created them.
|
||||
* Debugging API functions (JSDebugHooks::newScriptHook;
|
||||
* JS_GetFunctionScript) may reveal sans-script-object Function and
|
||||
* temporary scripts to clients, but clients must never call
|
||||
* JS_NewScriptObject on such scripts: doing so would double-free them,
|
||||
* once from the explicit call to js_DestroyScript, and once when the
|
||||
* script object is garbage collected.
|
||||
*/
|
||||
JSObject *object;
|
||||
JSScript *nextToGC; /* next to GC in rt->scriptsToGC list */
|
||||
} u;
|
||||
#ifdef CHECK_SCRIPT_OWNER
|
||||
@ -479,6 +495,9 @@ js_DestroyScript(JSContext *cx, JSScript *script);
|
||||
extern void
|
||||
js_TraceScript(JSTracer *trc, JSScript *script);
|
||||
|
||||
extern JSBool
|
||||
js_NewScriptObject(JSContext *cx, JSScript *script);
|
||||
|
||||
/*
|
||||
* To perturb as little code as possible, we introduce a js_GetSrcNote lookup
|
||||
* cache without adding an explicit cx parameter. Thus js_GetSrcNote becomes
|
||||
|
@ -1095,7 +1095,13 @@ Tracker::set(const void* v, LIns* i)
|
||||
static inline jsuint
|
||||
argSlots(JSStackFrame* fp)
|
||||
{
|
||||
return JS_MAX(fp->numActualArgs(), fp->numFormalArgs());
|
||||
return fp->isEvalFrame() ? 0 : JS_MAX(fp->numActualArgs(), fp->numFormalArgs());
|
||||
}
|
||||
|
||||
static inline jsuint
|
||||
numEntryFrameArgs(JSStackFrame* fp)
|
||||
{
|
||||
return fp->isEvalFrame() ? 0 : fp->numActualArgs();
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@ -6104,7 +6110,7 @@ AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom, j
|
||||
}
|
||||
JS_ASSERT(ngslots >= anchor->numGlobalSlots);
|
||||
bool rv = TraceRecorder::startRecorder(cx, anchor, c, stackSlots, ngslots, typeMap,
|
||||
exitedFrom, outer, cx->fp->numActualArgs(),
|
||||
exitedFrom, outer, numEntryFrameArgs(cx->fp),
|
||||
Record_Branch, hits < maxHits);
|
||||
#ifdef MOZ_TRACEVIS
|
||||
if (!rv && tvso)
|
||||
@ -6153,7 +6159,7 @@ TraceRecorder::recordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCall
|
||||
JS_ASSERT(r->fragment && !r->fragment->lastIns);
|
||||
TreeFragment* root = r->fragment->root;
|
||||
TreeFragment* first = LookupOrAddLoop(tm, cx->regs->pc, root->globalObj,
|
||||
root->globalShape, cx->fp->numActualArgs());
|
||||
root->globalShape, numEntryFrameArgs(cx->fp));
|
||||
|
||||
/*
|
||||
* Make sure the shape of the global object still matches (this might flush
|
||||
@ -6181,7 +6187,7 @@ TraceRecorder::recordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCall
|
||||
TreeFragment* outerFragment = root;
|
||||
jsbytecode* outer = (jsbytecode*) outerFragment->ip;
|
||||
uint32 outerArgc = outerFragment->argc;
|
||||
JS_ASSERT(cx->fp->numActualArgs() == first->argc);
|
||||
JS_ASSERT(numEntryFrameArgs(cx->fp) == first->argc);
|
||||
AbortRecording(cx, "No compatible inner tree");
|
||||
|
||||
return RecordingIfTrue(RecordTree(cx, first, outer, outerArgc, globalSlots, Record_Branch));
|
||||
@ -7205,7 +7211,7 @@ MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount, RecordReason reason)
|
||||
}
|
||||
|
||||
jsbytecode* pc = cx->regs->pc;
|
||||
uint32 argc = cx->fp->numActualArgs();
|
||||
uint32 argc = numEntryFrameArgs(cx->fp);
|
||||
|
||||
TreeFragment* f = LookupOrAddLoop(tm, pc, globalObj, globalShape, argc);
|
||||
|
||||
@ -8247,19 +8253,16 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp,
|
||||
uintN slot = uint16(sprop->shortid);
|
||||
|
||||
vp = NULL;
|
||||
uintN upvar_slot = SPROP_INVALID_SLOT;
|
||||
JSStackFrame* cfp = (JSStackFrame*) obj->getPrivate();
|
||||
if (cfp) {
|
||||
if (sprop->getterOp() == js_GetCallArg) {
|
||||
JS_ASSERT(slot < cfp->numFormalArgs());
|
||||
vp = &cfp->argv[slot];
|
||||
upvar_slot = slot;
|
||||
nr.v = *vp;
|
||||
} else if (sprop->getterOp() == js_GetCallVar ||
|
||||
sprop->getterOp() == js_GetCallVarChecked) {
|
||||
JS_ASSERT(slot < cfp->getSlotCount());
|
||||
vp = &cfp->slots()[slot];
|
||||
upvar_slot = cx->fp->numFormalArgs() + slot;
|
||||
nr.v = *vp;
|
||||
} else {
|
||||
RETURN_STOP("dynamic property of Call object");
|
||||
|
@ -671,8 +671,17 @@ JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
||||
{
|
||||
if (!js_XDRScript(xdr, scriptp, true, NULL))
|
||||
return JS_FALSE;
|
||||
if (xdr->mode == JSXDR_DECODE)
|
||||
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
js_CallNewScriptHook(xdr->cx, *scriptp, NULL);
|
||||
if (*scriptp != JSScript::emptyScript() &&
|
||||
!js_NewScriptObject(xdr->cx, *scriptp)) {
|
||||
js_DestroyScript(xdr->cx, *scriptp);
|
||||
*scriptp = NULL;
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ class BaseAssembler : public JSC::MacroAssembler
|
||||
Vector<CallPatch, 64, SystemAllocPolicy> callPatches;
|
||||
|
||||
public:
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
|
||||
// If there is no fast call, we need to add esp by 8 after the call.
|
||||
// This callLabel is to record the Label exactly after the call.
|
||||
Label callLabel;
|
||||
@ -267,12 +267,19 @@ static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::ARMRegister
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
push(Registers::ArgReg1);
|
||||
push(Registers::ArgReg0);
|
||||
#elif defined(_WIN64)
|
||||
subPtr(JSC::MacroAssembler::Imm32(32),
|
||||
JSC::MacroAssembler::stackPointerRegister);
|
||||
#endif
|
||||
Call cl = call(pfun);
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
callLabel = label();
|
||||
addPtr(JSC::MacroAssembler::Imm32(8),
|
||||
JSC::MacroAssembler::stackPointerRegister);
|
||||
#elif defined(_WIN64)
|
||||
callLabel = label();
|
||||
addPtr(JSC::MacroAssembler::Imm32(32),
|
||||
JSC::MacroAssembler::stackPointerRegister);
|
||||
#endif
|
||||
return cl;
|
||||
}
|
||||
@ -293,18 +300,8 @@ static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::ARMRegister
|
||||
}
|
||||
|
||||
Call call(void *fun) {
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
subPtr(JSC::MacroAssembler::Imm32(32),
|
||||
JSC::MacroAssembler::stackPointerRegister);
|
||||
#endif
|
||||
|
||||
Call cl = JSC::MacroAssembler::call();
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
addPtr(JSC::MacroAssembler::Imm32(32),
|
||||
JSC::MacroAssembler::stackPointerRegister);
|
||||
#endif
|
||||
|
||||
callPatches.append(CallPatch(differenceBetween(startLabel, cl), fun));
|
||||
return cl;
|
||||
}
|
||||
|
@ -494,6 +494,13 @@ mjit::Compiler::generateMethod()
|
||||
masm.callLabel = masm.label();
|
||||
masm.addPtr(Imm32(8), Registers::StackPointer);
|
||||
}
|
||||
#elif defined(_WIN64)
|
||||
// In case of Win64 ABI, stub caller make 32-bytes spcae on stack
|
||||
else {
|
||||
masm.subPtr(Imm32(32), Registers::StackPointer);
|
||||
masm.callLabel = masm.label();
|
||||
masm.addPtr(Imm32(32), Registers::StackPointer);
|
||||
}
|
||||
#endif
|
||||
ADD_CALLSITE(false);
|
||||
|
||||
@ -1826,7 +1833,7 @@ mjit::Compiler::inlineCallHelper(uint32 argc, bool callingNew)
|
||||
|
||||
/* Fast-path: return address contains scripted call. */
|
||||
masm.call(Registers::ReturnReg);
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
|
||||
masm.callLabel = masm.label();
|
||||
#endif
|
||||
ADD_CALLSITE(false);
|
||||
@ -1870,11 +1877,12 @@ mjit::Compiler::addCallSite(uint32 id, bool stub)
|
||||
{
|
||||
InternalCallSite site;
|
||||
site.stub = stub;
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
|
||||
site.location = stub ? stubcc.masm.callLabel : masm.callLabel;
|
||||
#else
|
||||
site.location = stub ? stubcc.masm.label() : masm.label();
|
||||
#endif
|
||||
|
||||
site.pc = PC;
|
||||
site.id = id;
|
||||
callSites.append(site);
|
||||
|
@ -675,8 +675,11 @@ extern "C" {
|
||||
* If these assertions break, update the constants below.
|
||||
* *** DANGER ***
|
||||
*/
|
||||
JS_STATIC_ASSERT(offsetof(VMFrame, savedRBX) == 0x48);
|
||||
JS_STATIC_ASSERT(offsetof(VMFrame, fp) == 0x30);
|
||||
JS_STATIC_ASSERT(offsetof(VMFrame, savedRBX) == 0x58);
|
||||
JS_STATIC_ASSERT(offsetof(VMFrame, fp) == 0x38);
|
||||
JS_STATIC_ASSERT(offsetof(JSStackFrame, ncode) == 0x60);
|
||||
JS_STATIC_ASSERT(JSVAL_TAG_MASK == 0xFFFF800000000000LL);
|
||||
JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL);
|
||||
|
||||
// Windows x64 uses assembler version since compiler doesn't support
|
||||
// inline assembler
|
||||
|
@ -91,7 +91,7 @@ struct VMFrame
|
||||
# endif
|
||||
#elif defined(JS_CPU_X64)
|
||||
void *savedRBX;
|
||||
# ifdef _MSC_VER
|
||||
# ifdef _WIN64
|
||||
void *savedRSI;
|
||||
void *savedRDI;
|
||||
# endif
|
||||
@ -102,7 +102,7 @@ struct VMFrame
|
||||
void *savedRBP;
|
||||
void *savedRIP;
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# ifdef _WIN64
|
||||
inline void** returnAddressLocation() {
|
||||
return reinterpret_cast<void**>(this) - 5;
|
||||
}
|
||||
|
@ -1364,12 +1364,12 @@ stubs::Debugger(VMFrame &f, jsbytecode *pc)
|
||||
case JSTRAP_RETURN:
|
||||
f.cx->throwing = JS_FALSE;
|
||||
f.cx->fp->setReturnValue(rval);
|
||||
*f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *,
|
||||
JS_METHODJIT_DATA(f.cx).trampolines.forceReturn);
|
||||
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#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);
|
||||
#else
|
||||
*f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *,
|
||||
JS_METHODJIT_DATA(f.cx).trampolines.forceReturn);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@ -1404,12 +1404,12 @@ stubs::Trap(VMFrame &f, jsbytecode *pc)
|
||||
case JSTRAP_RETURN:
|
||||
f.cx->throwing = JS_FALSE;
|
||||
f.cx->fp->setReturnValue(rval);
|
||||
*f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *,
|
||||
JS_METHODJIT_DATA(f.cx).trampolines.forceReturn);
|
||||
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#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);
|
||||
#else
|
||||
*f.returnAddressLocation() = JS_FUNC_TO_DATA_PTR(void *,
|
||||
JS_METHODJIT_DATA(f.cx).trampolines.forceReturn);
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -62,7 +62,7 @@ TrampolineCompiler::compile()
|
||||
#endif
|
||||
|
||||
COMPILE(trampolines->forceReturn, trampolines->forceReturnPool, generateForceReturn);
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
|
||||
COMPILE(trampolines->forceReturnFast, trampolines->forceReturnFastPool, generateForceReturnFast);
|
||||
#endif
|
||||
|
||||
@ -73,7 +73,7 @@ void
|
||||
TrampolineCompiler::release(Trampolines *tramps)
|
||||
{
|
||||
RELEASE(tramps->forceReturn, tramps->forceReturnPool);
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
|
||||
RELEASE(tramps->forceReturnFast, tramps->forceReturnFastPool);
|
||||
#endif
|
||||
}
|
||||
@ -151,13 +151,17 @@ TrampolineCompiler::generateForceReturn(Assembler &masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
|
||||
bool
|
||||
TrampolineCompiler::generateForceReturnFast(Assembler &masm)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
masm.addPtr(Imm32(32), Registers::StackPointer);
|
||||
#else
|
||||
// In case of no fast call, when we change the return address,
|
||||
// we need to make sure add esp by 8.
|
||||
masm.addPtr(Imm32(8), Registers::StackPointer);
|
||||
#endif
|
||||
return generateForceReturn(masm);
|
||||
}
|
||||
#endif
|
||||
|
@ -71,7 +71,7 @@ private:
|
||||
/* Generators for trampolines. */
|
||||
static bool generateForceReturn(Assembler &masm);
|
||||
|
||||
#if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
|
||||
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
|
||||
static bool generateForceReturnFast(Assembler &masm);
|
||||
#endif
|
||||
|
||||
|
180
js/src/methodjit/TrampolineMasmX64.asm
Normal file
180
js/src/methodjit/TrampolineMasmX64.asm
Normal file
@ -0,0 +1,180 @@
|
||||
; -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public License Version
|
||||
; 1.1 (the "License"); you may not use this file except in compliance with
|
||||
; the License. You may obtain a copy of the License at
|
||||
; http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
; for the specific language governing rights and limitations under the
|
||||
; License.
|
||||
;
|
||||
; The Original Code is mozilla.org code.
|
||||
;
|
||||
; The Initial Developer of the Original Code is Mozilla Japan.
|
||||
; Portions created by the Initial Developer are Copyright (C) 2010
|
||||
; the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
; Makoto Kato <m_kato@ga2.so-net.ne.jp>
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
extern js_InternalThrow:PROC
|
||||
extern SetVMFrameRegs:PROC
|
||||
extern UnsetVMFrameRegs:PROC
|
||||
extern PushActiveVMFrame:PROC
|
||||
extern PopActiveVMFrame:PROC
|
||||
|
||||
.CODE
|
||||
|
||||
; JSBool JaegerTrampoline(JSContext *cx, JSStackFrame *fp, void *code,
|
||||
; Value *stackLimit, void *safePoint);
|
||||
JaegerTrampoline PROC FRAME
|
||||
push rbp
|
||||
.PUSHREG rbp
|
||||
mov rbp, rsp
|
||||
.SETFRAME rbp, 0
|
||||
push r12
|
||||
.PUSHREG r12
|
||||
push r13
|
||||
.PUSHREG r13
|
||||
push r14
|
||||
.PUSHREG r14
|
||||
push r15
|
||||
.PUSHREG r15
|
||||
push rdi
|
||||
.PUSHREG rdi
|
||||
push rsi
|
||||
.PUSHREG rsi
|
||||
push rbx
|
||||
.PUSHREG rbx
|
||||
.ENDPROLOG
|
||||
|
||||
; Load mask registers
|
||||
mov r13, 0ffff800000000000h
|
||||
mov r14, 7fffffffffffh
|
||||
|
||||
; Build the JIT frame.
|
||||
; rcx = cx
|
||||
; rdx = fp
|
||||
; r9 = inlineCallCount
|
||||
; fp must go into rbx
|
||||
push rdx ; entryFp
|
||||
push r9 ; inlineCallCount
|
||||
push rcx ; cx
|
||||
push rdx ; fp
|
||||
mov rbx, rdx
|
||||
|
||||
; Space for the rest of the VMFrame.
|
||||
sub rsp, 28h
|
||||
|
||||
; This is actually part of VMFrame, but we need to save 5th param for
|
||||
; SafePointTrampoline
|
||||
mov r10, [rbp+8*5+8]
|
||||
push r10
|
||||
|
||||
; Set cx->regs and set the active frame. Save r8 and align frame in one
|
||||
push r8
|
||||
mov rcx, rsp
|
||||
sub rsp, 20h
|
||||
call SetVMFrameRegs
|
||||
lea rcx, [rsp+20h]
|
||||
call PushActiveVMFrame
|
||||
add rsp, 20h
|
||||
|
||||
; Jump into the JIT code.
|
||||
call qword ptr [rsp]
|
||||
sub rsp, 20h
|
||||
lea rcx, [rsp+20h]
|
||||
call PopActiveVMFrame
|
||||
lea rcx, [rsp+20h]
|
||||
call UnsetVMFrameRegs
|
||||
|
||||
add rsp, 58h+20h
|
||||
pop rbx
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbp
|
||||
mov rax, 1
|
||||
ret
|
||||
JaegerTrampoline ENDP
|
||||
|
||||
|
||||
; void JaegerThrowpoline()
|
||||
JaegerThrowpoline PROC FRAME
|
||||
.ENDPROLOG
|
||||
; For Windows x64 stub calls, we pad the stack by 32 before
|
||||
; calling, so we must account for that here. See doStubCall.
|
||||
lea rcx, [rsp+20h]
|
||||
call js_InternalThrow
|
||||
test rax, rax
|
||||
je throwpoline_exit
|
||||
add rsp, 20h
|
||||
jmp rax
|
||||
|
||||
throwpoline_exit:
|
||||
lea rcx, [rsp+20h]
|
||||
call PopActiveVMFrame
|
||||
add rsp, 58h+20h
|
||||
pop rbx
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbp
|
||||
xor rax, rax
|
||||
ret
|
||||
JaegerThrowpoline ENDP
|
||||
|
||||
|
||||
; void SafePointTrampoline();
|
||||
SafePointTrampoline PROC FRAME
|
||||
.ENDPROLOG
|
||||
pop rax
|
||||
mov qword ptr [rbx+60h], rax
|
||||
jmp qword ptr [rsp+8]
|
||||
SafePointTrampoline ENDP
|
||||
|
||||
|
||||
; void InjectJaegerReturn();
|
||||
InjectJaegerReturn PROC FRAME
|
||||
.ENDPROLOG
|
||||
mov rcx, qword ptr [rbx+40h] ; load value into typeReg
|
||||
mov rax, qword ptr [rbx+60h] ; fp->ncode
|
||||
|
||||
; Reimplementation of PunboxAssembler::loadValueAsComponents()
|
||||
mov rdx, r14
|
||||
and rdx, rcx
|
||||
xor rcx, rdx
|
||||
|
||||
; For Windows x64 stub calls, we pad the stack by 32 before
|
||||
; calling, so we must account for that here. See doStubCall.
|
||||
mov rbx, qword ptr [rsp+38h+20h] ; f.fp
|
||||
add rsp, 20h
|
||||
jmp rax ; return
|
||||
InjectJaegerReturn ENDP
|
||||
|
||||
END
|
@ -49,7 +49,7 @@ skip script regress-335700.js # bug xxx - reftest hang, BigO
|
||||
skip-if(!xulRuntime.shell) script regress-336409-1.js # no results reported.
|
||||
skip-if(!xulRuntime.shell&&xulRuntime.XPCOMABI.match(/x86_64/)) script regress-336409-2.js # fails on 64 bit systems for some reason
|
||||
skip-if(!xulRuntime.shell) script regress-336410-1.js # slow
|
||||
skip-if(!xulRuntime.shell&&xulRuntime.XPCOMABI.match(/x86_64/)) script regress-336410-2.js # fails on 64 bit systems for some reason
|
||||
skip-if(!xulRuntime.shell&&(xulRuntime.XPCOMABI.match(/x86_64/)||xulRuntime.OS=="WINNT")) script regress-336410-2.js # fails in browser on 64 bit systems or Windows.
|
||||
script regress-338804-01.js
|
||||
script regress-338804-02.js
|
||||
script regress-338804-03.js
|
||||
|
Loading…
Reference in New Issue
Block a user