Signal error from the boxing/unboxing using magic cookies since gcc seems to very seriously object to the use of uint64 return values during a fastcall (horribly inefficient code).

This commit is contained in:
Andreas Gal 2008-07-05 16:28:03 -07:00
parent 05c4c4bb27
commit 19152ffb1f
5 changed files with 42 additions and 66 deletions

View File

@ -83,12 +83,16 @@ endif
DEFINES += -DFEATURE_NANOJIT -DAVMPLUS_IA32 -DTRACEMONKEY
INTERP_OPTIMIZER = -O3 -fstrict-aliasing
BUILTINS_OPTIMIZER = -O9 -fstrict-aliasing -momit-leaf-frame-pointer
#
# XCFLAGS may be set in the environment or on the gmake command line
#
#CFLAGS += -DDEBUG -DDEBUG_brendan -DJS_ARENAMETER -DJS_HASHMETER -DJS_DUMP_PROPTREE_STATS -DJS_DUMP_SCOPE_METERS -DJS_SCOPE_DEPTH_METER -DJS_BASIC_STATS
CFLAGS += $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS)
INTERP_CFLAGS += $(INTERP_OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS) $(INTERP_XCFLAGS)
BUILTINS_CFLAGS += $(BUILTINS_OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS) $(BUILTINS_XCFLAGS)
LDFLAGS = $(XLDFLAGS)
LDFLAGS += $(OS_LDFLAGS)
@ -271,6 +275,7 @@ JS_CPPFILES = \
nanojit/avmplus.cpp \
nanojit/Tests.cpp \
nanojit/TraceTreeDrawer.cpp \
jsbuiltins.cpp \
$(NULL)
ifdef JS_LIVECONNECT
@ -383,8 +388,6 @@ else
OBJ=o
endif
$(OBJDIR)/jsinterp.$(OBJ): jsinterpinlines.h
$(OBJDIR)/jstracer.$(OBJ): jsinterpinlines.h jstracerinlines.h
$(OBJDIR)/jsinvoke.$(OBJ): jsinterp.h jsinterp.cpp
$(OBJDIR)/jsinvoke.obj : jsinterp.h jsinterp.cpp

View File

@ -36,7 +36,7 @@
*
* ***** END LICENSE BLOCK ***** */
BUILTIN2(BoxDouble, LO, F, Q, uint64, JSContext*, jsdouble, 1, 1)
BUILTIN2(BoxInt32, LO, LO, Q, uint64, JSContext*, jsint, 1, 1)
BUILTIN1(UnboxInt32, LO, Q, uint64, jsval*, 1, 1)
BUILTIN2(BoxDouble, LO, F, LO, jsval, JSContext*, jsdouble, 1, 1)
BUILTIN2(BoxInt32, LO, LO, LO, jsval, JSContext*, jsint, 1, 1)
BUILTIN1(UnboxInt32, LO, LO, int32, jsval, 1, 1)
BUILTIN2(dmod, F, F, F, jsdouble, jsdouble, jsdouble, 1, 1)

View File

@ -136,61 +136,6 @@ Tracker::set(const void* v, LIns* ins)
#define NAME(op)
#endif
FASTCALL jsdouble builtin_dmod(jsdouble a, jsdouble b)
{
if (b == 0.0) {
jsdpun u;
u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
u.s.lo = 0xffffffff;
return u.d;
}
jsdouble r;
#ifdef XP_WIN
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
if (!(JSDOUBLE_IS_FINITE(a) && JSDOUBLE_IS_INFINITE(b)))
r = a;
else
#endif
r = fmod(a, b);
return r;
}
/* The following boxing/unboxing primitives we can't emit inline because
they either interact with the GC and depend on Spidermonkey's 32-bit
integer representation. */
inline FASTCALL uint64 builtin_BoxDouble(JSContext* cx, jsdouble d)
{
if (!cx->doubleFreeList) /* we must be certain the GC won't kick in */
return 1LL << 32;
jsval v; /* not rooted but ok here because we know GC won't run */
#ifdef DEBUG
bool ok =
#endif
js_NewDoubleInRootedValue(cx, d, &v);
#ifdef DEBUG
JS_ASSERT(ok);
#endif
return v & 0xffffffffLL;
}
inline FASTCALL uint64 builtin_BoxInt32(JSContext* cx, jsint i)
{
if (JS_LIKELY(INT_FITS_IN_JSVAL(i)))
return INT_TO_JSVAL(i) & 0xffffffffLL;
return builtin_BoxDouble(cx, (jsdouble)i);
}
inline FASTCALL uint64 builtin_UnboxInt32(JSContext* cx, jsval v)
{
if (JS_LIKELY(JSVAL_IS_INT(v)))
return JSVAL_TO_INT(v);
jsint i;
if (JSVAL_IS_DOUBLE(v) && JSDOUBLE_IS_INT(*JSVAL_TO_DOUBLE(v), i))
return i;
return 1LL << 32;
}
#define BUILTIN1(op, at0, atr, tr, t0, cse, fold) \
{ (intptr_t)&builtin_##op, (at0 << 2) | atr, cse, fold NAME(op) },
#define BUILTIN2(op, at0, at1, atr, tr, t0, t1, cse, fold) \
@ -218,8 +163,10 @@ TraceRecorder::TraceRecorder(JSContext* cx, Fragmento* fragmento, Fragment* _fra
entryRegs.pc = entryFrame->regs->pc;
entryRegs.sp = entryFrame->regs->sp;
#ifdef DEBUG
printf("entryRegs.pc=%p opcode=%d\n", entryRegs.pc, *entryRegs.pc);
#endif
fragment->calldepth = 0;
lirbuf = new (&gc) LirBuffer(fragmento, builtins);
fragment->lirbuf = lirbuf;
@ -674,8 +621,6 @@ js_AbortRecording(JSContext* cx, const char* reason)
#ifdef DEBUG
printf("Abort recording: %s.\n", reason);
#endif
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
JS_ASSERT(tm->recorder != NULL);
js_DeleteRecorder(cx);
}
@ -901,7 +846,7 @@ TraceRecorder::int32_to_jsval(LIns* i_ins)
{
LIns* args[] = { cx_ins, i_ins };
LIns* ret = lir->insCall(F_BoxInt32, args);
guard(false, lir->ins_eq0(lir->ins1(LIR_callh, ret)));
guard(false, lir->ins2(LIR_eq, ret, lir->insImmPtr((void*)JSVAL_ERROR_COOKIE)));
return ret;
}
@ -910,7 +855,7 @@ TraceRecorder::double_to_jsval(LIns* d_ins)
{
LIns* args[] = { cx_ins, d_ins };
LIns* ret = lir->insCall(F_BoxDouble, args);
guard(false, lir->ins_eq0(lir->ins1(LIR_callh, ret)));
guard(false, lir->ins2(LIR_eq, ret, lir->insImmPtr((void*)JSVAL_ERROR_COOKIE)));
return ret;
}
@ -918,7 +863,7 @@ LIns*
TraceRecorder::jsval_to_int32(LIns* v_ins)
{
LIns* ret = lir->insCall(F_UnboxInt32, &v_ins);
guard(true, lir->ins_eq0(lir->ins1(LIR_callh, ret)));
guard(false, lir->ins2i(LIR_eq, ret, INT32_ERROR_COOKIE));
return ret;
}

View File

@ -47,6 +47,21 @@
#include "nanojit/nanojit.h"
/*
* We use a magic boxed pointer value to represent error conditions that
* trigger a side exit. The address is so low that it should never be
* actually in use. If it is, a performance regression occurs, not an
* actual runtime error.
*/
#define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((void*)0x10)
/*
* We also need a magic unboxed 32-bit integer that signals an error.
* Again if this number is hit we experience a performance regression,
* not a runtime error.
*/
#define INT32_ERROR_COOKIE 0xffffabcd
/*
* Tracker is used to keep track of values being manipulated by the
* interpreter during trace recording.
@ -396,6 +411,11 @@ public:
bool JSOP_HOLE();
};
FASTCALL jsdouble builtin_dmod(jsdouble a, jsdouble b);
FASTCALL jsval builtin_BoxDouble(JSContext* cx, jsdouble d);
FASTCALL jsval builtin_BoxInt32(JSContext* cx, jsint i);
FASTCALL jsint builtin_UnboxInt32(JSContext* cx, jsval v);
/*
* Trace monitor. Every runtime is associated with a trace monitor that keeps
* track of loop frequencies for all JavaScript code loaded into that runtime.

View File

@ -81,6 +81,10 @@ $(OBJDIR)/jsinterp.o: jsinterp.cpp jsinterp.h
@$(MAKE_OBJDIR)
$(CXX) -o $@ -c $(INTERP_CFLAGS) jsinterp.cpp
$(OBJDIR)/jsbuiltins.o: jsbuiltins.cpp jsinterp.h
@$(MAKE_OBJDIR)
$(CXX) -o $@ -c $(BUILTINS_CFLAGS) jsbuiltins.cpp
$(OBJDIR)/%.o: %.cpp
@$(MAKE_OBJDIR)
$(CXX) -o $@ -c $(CFLAGS) $*.cpp
@ -98,6 +102,10 @@ $(OBJDIR)/jsinterp.obj: jsinterp.cpp jsinterp.h
@$(MAKE_OBJDIR)
$(CXX) -Fo$(OBJDIR)/ -c $(INTERP_CFLAGS) $(JSDLL_CFLAGS) jsinterp.c
$(OBJDIR)/jsbuiltins.obj: jsbuiltins.cpp jsinterp.h
@$(MAKE_OBJDIR)
$(CXX) -Fo$(OBJDIR)/ -c $(BUILTINS_CFLAGS) $(JSDLL_CFLAGS) jsbuiltins.c
$(OBJDIR)/%.obj: %.cpp
@$(MAKE_OBJDIR)
$(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $*.cpp