mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-14 02:31:59 +00:00
[Bug 433382] More efficient interpreter switch when computed goto is not available. r=brendan
This commit is contained in:
parent
7a2a078f0f
commit
79c9e30964
@ -242,6 +242,10 @@ JSJAVA_CFLAGS = \
|
||||
|
||||
HOST_SIMPLE_PROGRAMS += host_jskwgen$(HOST_BIN_SUFFIX)
|
||||
GARBAGE += jsautokw.h host_jskwgen$(HOST_BIN_SUFFIX)
|
||||
|
||||
HOST_SIMPLE_PROGRAMS += host_jsoplengen$(HOST_BIN_SUFFIX)
|
||||
GARBAGE += jsautooplen.h host_jsoplengen$(HOST_BIN_SUFFIX)
|
||||
|
||||
USE_HOST_CXX = 1
|
||||
|
||||
ifdef HAVE_DTRACE
|
||||
@ -445,18 +449,23 @@ jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.cpp Makefile.in
|
||||
endif
|
||||
endif
|
||||
|
||||
# Extra dependancies and rules for keyword switch code
|
||||
jsscan.$(OBJ_SUFFIX): jsautokw.h jskeyword.tbl
|
||||
|
||||
# Extra dependancies and rules for auto-generated headers
|
||||
host_jskwgen.$(OBJ_SUFFIX): jsconfig.h jskeyword.tbl
|
||||
|
||||
jsautokw.h: host_jskwgen$(HOST_BIN_SUFFIX)
|
||||
./host_jskwgen$(HOST_BIN_SUFFIX) $@
|
||||
|
||||
host_jsoplengen.$(OBJ_SUFFIX): jsopcode.tbl
|
||||
|
||||
jsautooplen.h: host_jsoplengen$(HOST_BIN_SUFFIX)
|
||||
./host_jsoplengen$(HOST_BIN_SUFFIX) $@
|
||||
|
||||
# Force auto-header generation before compiling any source that may use them
|
||||
$(CPPSRCS:%.cpp=%.$(OBJ_SUFFIX)): jsautokw.h jsautooplen.h
|
||||
|
||||
ifdef HAVE_DTRACE
|
||||
javascript-trace.h: $(srcdir)/javascript-trace.d
|
||||
dtrace -h -s $(srcdir)/javascript-trace.d -o javascript-trace.h.in
|
||||
sed 's/if _DTRACE_VERSION/ifdef INCLUDE_MOZILLA_DTRACE/' \
|
||||
javascript-trace.h.in > javascript-trace.h
|
||||
endif
|
||||
|
||||
|
@ -277,39 +277,39 @@ nsinstall-target:
|
||||
cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR)
|
||||
|
||||
#
|
||||
# Rules for keyword switch generation
|
||||
# Automatic header generation
|
||||
#
|
||||
|
||||
GARBAGE += $(OBJDIR)/jsautokw.h $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX)
|
||||
GARBAGE += $(OBJDIR)/jskwgen.$(OBJ_SUFFIX)
|
||||
AUTO_HEADERS = $(OBJDIR)/jsautokw.h $(OBJDIR)/jsautooplen.h
|
||||
|
||||
$(OBJDIR)/jsscan.$(OBJ_SUFFIX): $(OBJDIR)/jsautokw.h jskeyword.tbl
|
||||
$(OBJDIR)/jsautokw.h: jskeyword.tbl
|
||||
|
||||
$(OBJDIR)/jskwgen.$(OBJ_SUFFIX): jskwgen.cpp jskeyword.tbl
|
||||
$(OBJDIR)/jsautooplen.h: jsopcode.tbl
|
||||
|
||||
$(OBJDIR)/jsautokw.h: $(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) jskeyword.tbl
|
||||
$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX) $@
|
||||
GARBAGE += $(AUTO_HEADERS)
|
||||
GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen$(HOST_BIN_SUFFIX))
|
||||
|
||||
ifdef USE_MSVC
|
||||
|
||||
$(OBJDIR)/jskwgen.obj: jskwgen.cpp jskeyword.tbl
|
||||
GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.obj)
|
||||
|
||||
$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $<
|
||||
|
||||
$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX)
|
||||
link.exe -out:"$@" $(EXE_LINK_FLAGS) $^
|
||||
|
||||
link.exe -out:"$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX)" $(EXE_LINK_FLAGS) $(OBJDIR)/js$*gen.obj
|
||||
$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@
|
||||
else
|
||||
|
||||
$(OBJDIR)/jskwgen.o: jskwgen.cpp jskeyword.tbl
|
||||
$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CXX) -o $@ -c $(CFLAGS) $<
|
||||
|
||||
$(OBJDIR)/jskwgen$(HOST_BIN_SUFFIX): $(OBJDIR)/jskwgen.$(OBJ_SUFFIX)
|
||||
$(CXX) -o $@ $(CFLAGS) $(LDFLAGS) $^
|
||||
$(CXX) -o $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $(CFLAGS) $(LDFLAGS) $<
|
||||
$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@
|
||||
|
||||
endif
|
||||
|
||||
# force creation of autoheaders before compiling any source that may use them
|
||||
$(LIB_OBJS) : $(AUTO_HEADERS)
|
||||
|
||||
#
|
||||
# JS shell executable
|
||||
#
|
||||
|
@ -62,6 +62,8 @@
|
||||
#include "jsscript.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "jsautooplen.h"
|
||||
|
||||
typedef struct JSTrap {
|
||||
JSCList links;
|
||||
JSScript *script;
|
||||
|
@ -66,6 +66,8 @@
|
||||
#include "jsscope.h"
|
||||
#include "jsscript.h"
|
||||
|
||||
#include "jsautooplen.h"
|
||||
|
||||
/* Allocation chunk counts, must be powers of two in general. */
|
||||
#define BYTECODE_CHUNK 256 /* code allocation increment */
|
||||
#define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */
|
||||
|
@ -77,6 +77,8 @@
|
||||
#include "jsxml.h"
|
||||
#endif
|
||||
|
||||
#include "jsautooplen.h"
|
||||
|
||||
#ifdef js_invoke_c__
|
||||
|
||||
uint32
|
||||
@ -2074,6 +2076,77 @@ js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
js_TraceOpcode(JSContext *cx, jsint len)
|
||||
{
|
||||
FILE *tracefp;
|
||||
JSStackFrame *fp;
|
||||
JSFrameRegs *regs;
|
||||
JSOp prevop;
|
||||
intN ndefs, n, nuses;
|
||||
jsval *siter;
|
||||
JSString *str;
|
||||
JSOp op;
|
||||
|
||||
tracefp = (FILE *) cx->tracefp;
|
||||
JS_ASSERT(tracefp);
|
||||
fp = cx->fp;
|
||||
regs = fp->regs;
|
||||
if (len != 0) {
|
||||
prevop = (JSOp) regs->pc[-len];
|
||||
ndefs = js_CodeSpec[prevop].ndefs;
|
||||
if (ndefs != 0) {
|
||||
if (prevop == JSOP_FORELEM && regs->sp[-1] == JSVAL_FALSE)
|
||||
--ndefs;
|
||||
for (n = -ndefs; n < 0; n++) {
|
||||
char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n],
|
||||
NULL);
|
||||
if (bytes) {
|
||||
fprintf(tracefp, "%s %s",
|
||||
(n == -ndefs) ? " output:" : ",",
|
||||
bytes);
|
||||
JS_free(cx, bytes);
|
||||
}
|
||||
}
|
||||
fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase);
|
||||
}
|
||||
fprintf(tracefp, " stack: ");
|
||||
for (siter = fp->spbase; siter < regs->sp; siter++) {
|
||||
str = js_ValueToString(cx, *siter);
|
||||
if (!str)
|
||||
fputs("<null>", tracefp);
|
||||
else
|
||||
js_FileEscapedString(tracefp, str, 0);
|
||||
fputc(' ', tracefp);
|
||||
}
|
||||
fputc('\n', tracefp);
|
||||
}
|
||||
|
||||
fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, fp->script, regs->pc));
|
||||
js_Disassemble1(cx, fp->script, regs->pc,
|
||||
PTRDIFF(regs->pc, fp->script->code, jsbytecode),
|
||||
JS_FALSE, tracefp);
|
||||
op = (JSOp) *regs->pc;
|
||||
nuses = js_CodeSpec[op].nuses;
|
||||
if (nuses != 0) {
|
||||
for (n = -nuses; n < 0; n++) {
|
||||
char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n],
|
||||
NULL);
|
||||
if (bytes) {
|
||||
fprintf(tracefp, "%s %s",
|
||||
(n == -nuses) ? " inputs:" : ",",
|
||||
bytes);
|
||||
JS_free(cx, bytes);
|
||||
}
|
||||
}
|
||||
fprintf(tracefp, " @ %d\n", regs->sp - fp->spbase);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef JS_OPMETER
|
||||
|
||||
# include <stdlib.h>
|
||||
@ -2425,6 +2498,13 @@ JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MAX)));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Interpreter assumes the following to implement condition-free interrupt
|
||||
* implementation when !JS_THREADED_INTERP.
|
||||
*/
|
||||
JS_STATIC_ASSERT(JSOP_INTERRUPT == 0);
|
||||
|
||||
/*
|
||||
* Ensure that the intrepreter switch can close call-bytecode cases in the
|
||||
* same way as non-call bytecodes.
|
||||
@ -2462,7 +2542,6 @@ js_Interpret(JSContext *cx)
|
||||
JSFrameRegs regs;
|
||||
JSObject *obj, *obj2, *parent;
|
||||
JSBool ok, cond;
|
||||
JSTrapHandler interruptHandler;
|
||||
jsint len;
|
||||
jsbytecode *endpc, *pc2;
|
||||
JSOp op, op2;
|
||||
@ -2481,8 +2560,11 @@ js_Interpret(JSContext *cx)
|
||||
JSClass *clasp;
|
||||
JSFunction *fun;
|
||||
JSType type;
|
||||
#if !JS_THREADED_INTERP && defined DEBUG
|
||||
FILE *tracefp = NULL;
|
||||
#if JS_THREADED_INTERP
|
||||
register const void * const *jumpTable;
|
||||
#else
|
||||
register uint32 switchMask;
|
||||
uintN switchOp;
|
||||
#endif
|
||||
#if JS_HAS_EXPORT_IMPORT
|
||||
JSIdArray *ida;
|
||||
@ -2502,42 +2584,68 @@ js_Interpret(JSContext *cx)
|
||||
#endif
|
||||
|
||||
#if JS_THREADED_INTERP
|
||||
static void *normalJumpTable[] = {
|
||||
static const void *const normalJumpTable[] = {
|
||||
# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
|
||||
JS_EXTENSION &&L_##op,
|
||||
# include "jsopcode.tbl"
|
||||
# undef OPDEF
|
||||
};
|
||||
|
||||
static void *interruptJumpTable[] = {
|
||||
static const void *const interruptJumpTable[] = {
|
||||
# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
|
||||
JS_EXTENSION &&interrupt,
|
||||
JS_EXTENSION &&L_JSOP_INTERRUPT,
|
||||
# include "jsopcode.tbl"
|
||||
# undef OPDEF
|
||||
};
|
||||
|
||||
register void **jumpTable = normalJumpTable;
|
||||
|
||||
METER_OP_INIT(op); /* to nullify first METER_OP_PAIR */
|
||||
|
||||
# define DO_OP() JS_EXTENSION_(goto *jumpTable[op])
|
||||
# define DO_NEXT_OP(n) do { METER_OP_PAIR(op, regs.pc[n]); \
|
||||
op = (JSOp) *(regs.pc += (n)); \
|
||||
DO_OP(); } while (0)
|
||||
# define DO_NEXT_OP(n) JS_BEGIN_MACRO \
|
||||
METER_OP_PAIR(op, regs.pc[n]); \
|
||||
op = (JSOp) *(regs.pc += (n)); \
|
||||
DO_OP(); \
|
||||
JS_END_MACRO
|
||||
|
||||
# define BEGIN_CASE(OP) L_##OP:
|
||||
# define END_CASE(OP) DO_NEXT_OP(OP##_LENGTH);
|
||||
# define END_VARLEN_CASE DO_NEXT_OP(len);
|
||||
# define EMPTY_CASE(OP) BEGIN_CASE(OP) op = (JSOp) *++regs.pc; DO_OP();
|
||||
#else
|
||||
# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) \
|
||||
JS_ASSERT(js_CodeSpec[OP].length == 1); \
|
||||
op = (JSOp) *++regs.pc; \
|
||||
DO_OP();
|
||||
|
||||
# define END_EMPTY_CASES
|
||||
|
||||
#else /* !JS_THREADED_INTERP */
|
||||
|
||||
# define DO_OP() goto do_op
|
||||
# define DO_NEXT_OP(n) goto advance_pc
|
||||
# define DO_NEXT_OP(n) JS_BEGIN_MACRO \
|
||||
JS_ASSERT((n) == len); \
|
||||
goto advance_pc; \
|
||||
JS_END_MACRO
|
||||
|
||||
# define BEGIN_CASE(OP) case OP:
|
||||
# define END_CASE(OP) break;
|
||||
# define END_VARLEN_CASE break;
|
||||
# define EMPTY_CASE(OP) BEGIN_CASE(OP) END_CASE(OP)
|
||||
# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH)
|
||||
# define END_CASE_LEN(n) END_CASE_LENX(n)
|
||||
# define END_CASE_LENX(n) END_CASE_LEN##n
|
||||
|
||||
/*
|
||||
* To share the code for all len == 1 cases we use the specialized label with
|
||||
* code that falls through to advance_pc: .
|
||||
*/
|
||||
# define END_CASE_LEN1 goto advance_pc_by_one;
|
||||
# define END_CASE_LEN2 len = 2; goto advance_pc;
|
||||
# define END_CASE_LEN3 len = 3; goto advance_pc;
|
||||
# define END_CASE_LEN4 len = 4; goto advance_pc;
|
||||
# define END_CASE_LEN5 len = 5; goto advance_pc;
|
||||
# define END_VARLEN_CASE goto advance_pc;
|
||||
# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
|
||||
# define END_EMPTY_CASES goto advance_pc_by_one;
|
||||
|
||||
#endif
|
||||
|
||||
/* Check for too deep a C stack. */
|
||||
/* Check for too deep of a native thread stack. */
|
||||
JS_CHECK_RECURSION(cx, return JS_FALSE);
|
||||
|
||||
rt = cx->runtime;
|
||||
@ -2616,18 +2724,15 @@ js_Interpret(JSContext *cx)
|
||||
* the compiler can keep it in a register when it is non-null.
|
||||
*/
|
||||
#if JS_THREADED_INTERP
|
||||
# define LOAD_JUMP_TABLE() \
|
||||
(jumpTable = interruptHandler ? interruptJumpTable : normalJumpTable)
|
||||
# define LOAD_INTERRUPT_HANDLER(cx) \
|
||||
((void) (jumpTable = (cx)->debugHooks->interruptHandler \
|
||||
? interruptJumpTable \
|
||||
: normalJumpTable))
|
||||
#else
|
||||
# define LOAD_JUMP_TABLE() ((void) 0)
|
||||
# define LOAD_INTERRUPT_HANDLER(cx) \
|
||||
((void) (switchMask = (cx)->debugHooks->interruptHandler ? 0 : 255))
|
||||
#endif
|
||||
|
||||
#define LOAD_INTERRUPT_HANDLER(cx) \
|
||||
JS_BEGIN_MACRO \
|
||||
interruptHandler = (cx)->debugHooks->interruptHandler; \
|
||||
LOAD_JUMP_TABLE(); \
|
||||
JS_END_MACRO
|
||||
|
||||
LOAD_INTERRUPT_HANDLER(cx);
|
||||
|
||||
/*
|
||||
@ -2675,107 +2780,89 @@ js_Interpret(JSContext *cx)
|
||||
}
|
||||
}
|
||||
|
||||
#if JS_THREADED_INTERP
|
||||
|
||||
/*
|
||||
* This is a loop, but it does not look like a loop. The loop-closing
|
||||
* jump is distributed throughout interruptJumpTable, and comes back to
|
||||
* the interrupt label. The dispatch on op is through normalJumpTable.
|
||||
* The trick is LOAD_INTERRUPT_HANDLER setting jumpTable appropriately.
|
||||
*
|
||||
* It is important that "op" be initialized before the interrupt label
|
||||
* because it is possible for "op" to be specially assigned during the
|
||||
* normally processing of an opcode while looping (in particular, this
|
||||
* happens in JSOP_TRAP while debugging). We rely on DO_NEXT_OP to
|
||||
* correctly manage "op" in all other cases.
|
||||
* It is important that "op" be initialized before calling DO_OP because
|
||||
* it is possible for "op" to be specially assigned during the normal
|
||||
* processing of an opcode while looping. We rely on DO_NEXT_OP to manage
|
||||
* "op" correctly in all other cases.
|
||||
*/
|
||||
op = (JSOp) *regs.pc;
|
||||
if (interruptHandler) {
|
||||
interrupt:
|
||||
switch (interruptHandler(cx, script, regs.pc, &rval,
|
||||
cx->debugHooks->interruptHandlerData)) {
|
||||
case JSTRAP_ERROR:
|
||||
goto error;
|
||||
case JSTRAP_CONTINUE:
|
||||
break;
|
||||
case JSTRAP_RETURN:
|
||||
fp->rval = rval;
|
||||
ok = JS_TRUE;
|
||||
goto forced_return;
|
||||
case JSTRAP_THROW:
|
||||
cx->throwing = JS_TRUE;
|
||||
cx->exception = rval;
|
||||
goto error;
|
||||
default:;
|
||||
}
|
||||
LOAD_INTERRUPT_HANDLER(cx);
|
||||
}
|
||||
|
||||
JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT);
|
||||
JS_EXTENSION_(goto *normalJumpTable[op]);
|
||||
|
||||
#else /* !JS_THREADED_INTERP */
|
||||
len = 0;
|
||||
DO_NEXT_OP(len);
|
||||
|
||||
#if JS_THREADED_INTERP
|
||||
/*
|
||||
* This is a loop, but it does not look like a loop. The loop-closing
|
||||
* jump is distributed throughout goto *jumpTable[op] inside of DO_OP.
|
||||
* When interrupts are enabled, jumpTable is set to interruptJumpTable
|
||||
* where all jumps point to the JSOP_INTERRUPT case. The latter, after
|
||||
* calling the interrupt handler, dispatches through normalJumpTable to
|
||||
* continue the normal bytecode processing.
|
||||
*/
|
||||
#else
|
||||
for (;;) {
|
||||
advance_pc_by_one:
|
||||
JS_ASSERT(js_CodeSpec[op].length == 1);
|
||||
len = 1;
|
||||
advance_pc:
|
||||
regs.pc += len;
|
||||
op = (JSOp) *regs.pc;
|
||||
do_op:
|
||||
len = js_CodeSpec[op].length;
|
||||
|
||||
#ifdef DEBUG
|
||||
tracefp = (FILE *) cx->tracefp;
|
||||
if (tracefp) {
|
||||
intN nuses, n;
|
||||
|
||||
fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, script, regs.pc));
|
||||
js_Disassemble1(cx, script, regs.pc,
|
||||
PTRDIFF(regs.pc, script->code, jsbytecode),
|
||||
JS_FALSE, tracefp);
|
||||
nuses = js_CodeSpec[op].nuses;
|
||||
if (nuses) {
|
||||
for (n = -nuses; n < 0; n++) {
|
||||
char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n],
|
||||
NULL);
|
||||
if (bytes) {
|
||||
fprintf(tracefp, "%s %s",
|
||||
(n == -nuses) ? " inputs:" : ",",
|
||||
bytes);
|
||||
JS_free(cx, bytes);
|
||||
}
|
||||
}
|
||||
fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase);
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
if (interruptHandler) {
|
||||
switch (interruptHandler(cx, script, regs.pc, &rval,
|
||||
cx->debugHooks->interruptHandlerData)) {
|
||||
case JSTRAP_ERROR:
|
||||
goto error;
|
||||
case JSTRAP_CONTINUE:
|
||||
break;
|
||||
case JSTRAP_RETURN:
|
||||
fp->rval = rval;
|
||||
ok = JS_TRUE;
|
||||
goto forced_return;
|
||||
case JSTRAP_THROW:
|
||||
cx->throwing = JS_TRUE;
|
||||
cx->exception = rval;
|
||||
goto error;
|
||||
default:;
|
||||
}
|
||||
LOAD_INTERRUPT_HANDLER(cx);
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
if (cx->tracefp)
|
||||
js_TraceOpcode(cx, len);
|
||||
#endif
|
||||
|
||||
do_op:
|
||||
switchOp = op & switchMask;
|
||||
do_switch:
|
||||
switch (switchOp) {
|
||||
#endif /* !JS_THREADED_INTERP */
|
||||
|
||||
EMPTY_CASE(JSOP_NOP)
|
||||
BEGIN_CASE(JSOP_INTERRUPT)
|
||||
{
|
||||
JSTrapHandler handler;
|
||||
|
||||
EMPTY_CASE(JSOP_GROUP)
|
||||
handler = cx->debugHooks->interruptHandler;
|
||||
if (handler) {
|
||||
switch (handler(cx, script, regs.pc, &rval,
|
||||
cx->debugHooks->interruptHandlerData)) {
|
||||
case JSTRAP_ERROR:
|
||||
goto error;
|
||||
case JSTRAP_CONTINUE:
|
||||
break;
|
||||
case JSTRAP_RETURN:
|
||||
fp->rval = rval;
|
||||
ok = JS_TRUE;
|
||||
goto forced_return;
|
||||
case JSTRAP_THROW:
|
||||
cx->throwing = JS_TRUE;
|
||||
cx->exception = rval;
|
||||
goto error;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
LOAD_INTERRUPT_HANDLER(cx);
|
||||
|
||||
/* EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */
|
||||
#if JS_THREADED_INTERP
|
||||
JS_EXTENSION_(goto *normalJumpTable[op]);
|
||||
#else
|
||||
switchOp = op;
|
||||
goto do_switch;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* No-ops for ease of decompilation. */
|
||||
ADD_EMPTY_CASE(JSOP_NOP)
|
||||
ADD_EMPTY_CASE(JSOP_GROUP)
|
||||
ADD_EMPTY_CASE(JSOP_CONDSWITCH)
|
||||
ADD_EMPTY_CASE(JSOP_TRY)
|
||||
ADD_EMPTY_CASE(JSOP_FINALLY)
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
ADD_EMPTY_CASE(JSOP_STARTXML)
|
||||
ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)
|
||||
#endif
|
||||
END_EMPTY_CASES
|
||||
|
||||
/* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */
|
||||
BEGIN_CASE(JSOP_LINENO)
|
||||
END_CASE(JSOP_LINENO)
|
||||
|
||||
@ -2810,12 +2897,6 @@ interrupt:
|
||||
#endif
|
||||
END_CASE(JSOP_POPN)
|
||||
|
||||
BEGIN_CASE(JSOP_SWAP)
|
||||
rtmp = regs.sp[-1];
|
||||
regs.sp[-1] = regs.sp[-2];
|
||||
regs.sp[-2] = rtmp;
|
||||
END_CASE(JSOP_SWAP)
|
||||
|
||||
BEGIN_CASE(JSOP_SETRVAL)
|
||||
BEGIN_CASE(JSOP_POPV)
|
||||
ASSERT_NOT_THROWING(cx);
|
||||
@ -4139,7 +4220,6 @@ interrupt:
|
||||
i = 0;
|
||||
COMPUTE_THIS(cx, fp, obj);
|
||||
PUSH(JSVAL_NULL);
|
||||
len = JSOP_GETTHISPROP_LENGTH;
|
||||
goto do_getprop_with_obj;
|
||||
|
||||
#undef COMPUTE_THIS
|
||||
@ -4149,7 +4229,6 @@ interrupt:
|
||||
slot = GET_ARGNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->nargs);
|
||||
PUSH_OPND(fp->argv[slot]);
|
||||
len = JSOP_GETARGPROP_LENGTH;
|
||||
goto do_getprop_body;
|
||||
|
||||
BEGIN_CASE(JSOP_GETVARPROP)
|
||||
@ -4157,7 +4236,6 @@ interrupt:
|
||||
slot = GET_VARNO(regs.pc);
|
||||
JS_ASSERT(slot < fp->fun->u.i.nvars);
|
||||
PUSH_OPND(fp->vars[slot]);
|
||||
len = JSOP_GETVARPROP_LENGTH;
|
||||
goto do_getprop_body;
|
||||
|
||||
BEGIN_CASE(JSOP_GETLOCALPROP)
|
||||
@ -4165,13 +4243,11 @@ interrupt:
|
||||
slot = GET_UINT16(regs.pc);
|
||||
JS_ASSERT(slot < script->depth);
|
||||
PUSH_OPND(fp->spbase[slot]);
|
||||
len = JSOP_GETLOCALPROP_LENGTH;
|
||||
goto do_getprop_body;
|
||||
|
||||
BEGIN_CASE(JSOP_GETPROP)
|
||||
BEGIN_CASE(JSOP_GETXPROP)
|
||||
i = 0;
|
||||
len = JSOP_GETPROP_LENGTH;
|
||||
|
||||
do_getprop_body:
|
||||
lval = FETCH_OPND(-1);
|
||||
@ -4217,6 +4293,8 @@ interrupt:
|
||||
} while (0);
|
||||
|
||||
STORE_OPND(-1, rval);
|
||||
JS_ASSERT(JSOP_GETPROP_LENGTH + i == js_CodeSpec[op].length);
|
||||
len = JSOP_GETPROP_LENGTH + i;
|
||||
END_VARLEN_CASE
|
||||
|
||||
BEGIN_CASE(JSOP_LENGTH)
|
||||
@ -4241,8 +4319,7 @@ interrupt:
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
i = -1;
|
||||
len = JSOP_LENGTH_LENGTH;
|
||||
i = -2;
|
||||
goto do_getprop_with_lval;
|
||||
}
|
||||
END_CASE(JSOP_LENGTH)
|
||||
@ -4996,12 +5073,12 @@ interrupt:
|
||||
goto error;
|
||||
if (!prop) {
|
||||
/* Kludge to allow (typeof foo == "undefined") tests. */
|
||||
len = JSOP_NAME_LENGTH;
|
||||
endpc = script->code + script->length;
|
||||
for (pc2 = regs.pc + len; pc2 < endpc; pc2++) {
|
||||
for (pc2 = regs.pc + JSOP_NAME_LENGTH; pc2 < endpc; pc2++) {
|
||||
op2 = (JSOp)*pc2;
|
||||
if (op2 == JSOP_TYPEOF) {
|
||||
PUSH_OPND(JSVAL_VOID);
|
||||
len = JSOP_NAME_LENGTH;
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
if (op2 != JSOP_GROUP)
|
||||
@ -5338,8 +5415,6 @@ interrupt:
|
||||
: GET_JUMPX_OFFSET(pc2);
|
||||
END_VARLEN_CASE
|
||||
|
||||
EMPTY_CASE(JSOP_CONDSWITCH)
|
||||
|
||||
#if JS_HAS_EXPORT_IMPORT
|
||||
BEGIN_CASE(JSOP_EXPORTALL)
|
||||
obj = fp->varobj;
|
||||
@ -5414,15 +5489,13 @@ interrupt:
|
||||
#endif /* JS_HAS_EXPORT_IMPORT */
|
||||
|
||||
BEGIN_CASE(JSOP_TRAP)
|
||||
switch (JS_HandleTrap(cx, script, regs.pc, &rval)) {
|
||||
{
|
||||
JSTrapStatus status;
|
||||
|
||||
status = JS_HandleTrap(cx, script, regs.pc, &rval);
|
||||
switch (status) {
|
||||
case JSTRAP_ERROR:
|
||||
goto error;
|
||||
case JSTRAP_CONTINUE:
|
||||
JS_ASSERT(JSVAL_IS_INT(rval));
|
||||
op = (JSOp) JSVAL_TO_INT(rval);
|
||||
JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT);
|
||||
LOAD_INTERRUPT_HANDLER(cx);
|
||||
DO_OP();
|
||||
case JSTRAP_RETURN:
|
||||
fp->rval = rval;
|
||||
ok = JS_TRUE;
|
||||
@ -5432,9 +5505,15 @@ interrupt:
|
||||
cx->exception = rval;
|
||||
goto error;
|
||||
default:;
|
||||
break;
|
||||
}
|
||||
JS_ASSERT(status == JSTRAP_CONTINUE);
|
||||
LOAD_INTERRUPT_HANDLER(cx);
|
||||
END_CASE(JSOP_TRAP)
|
||||
JS_ASSERT(JSVAL_IS_INT(rval));
|
||||
op = (JSOp) JSVAL_TO_INT(rval);
|
||||
JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT);
|
||||
DO_OP();
|
||||
}
|
||||
|
||||
BEGIN_CASE(JSOP_ARGUMENTS)
|
||||
if (!js_GetArgsValue(cx, fp, &rval))
|
||||
@ -6172,7 +6251,7 @@ interrupt:
|
||||
goto error;
|
||||
}
|
||||
regs.sp -= 2;
|
||||
END_CASE(JSOP_INITELEM);
|
||||
END_CASE(JSOP_INITELEM)
|
||||
|
||||
#if JS_HAS_SHARP_VARS
|
||||
BEGIN_CASE(JSOP_DEFSHARP)
|
||||
@ -6219,15 +6298,11 @@ interrupt:
|
||||
END_CASE(JSOP_USESHARP)
|
||||
#endif /* JS_HAS_SHARP_VARS */
|
||||
|
||||
/* No-ops for ease of decompilation and jit'ing. */
|
||||
EMPTY_CASE(JSOP_TRY)
|
||||
EMPTY_CASE(JSOP_FINALLY)
|
||||
|
||||
BEGIN_CASE(JSOP_GOSUB)
|
||||
PUSH(JSVAL_FALSE);
|
||||
i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH;
|
||||
len = GET_JUMP_OFFSET(regs.pc);
|
||||
PUSH(INT_TO_JSVAL(i));
|
||||
len = GET_JUMP_OFFSET(regs.pc);
|
||||
END_VARLEN_CASE
|
||||
|
||||
BEGIN_CASE(JSOP_GOSUBX)
|
||||
@ -6482,9 +6557,6 @@ interrupt:
|
||||
regs.sp--;
|
||||
END_CASE(JSOP_ENDFILTER);
|
||||
|
||||
EMPTY_CASE(JSOP_STARTXML)
|
||||
EMPTY_CASE(JSOP_STARTXMLEXPR)
|
||||
|
||||
BEGIN_CASE(JSOP_TOXML)
|
||||
rval = FETCH_OPND(-1);
|
||||
obj = js_ValueToXMLObject(cx, rval);
|
||||
@ -6784,48 +6856,6 @@ interrupt:
|
||||
#if !JS_THREADED_INTERP
|
||||
|
||||
} /* switch (op) */
|
||||
|
||||
advance_pc:
|
||||
regs.pc += len;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (tracefp) {
|
||||
intN ndefs, n;
|
||||
jsval *siter;
|
||||
|
||||
/*
|
||||
* op may be invalid here when a catch or finally handler jumps to
|
||||
* advance_pc.
|
||||
*/
|
||||
op = (JSOp) regs.pc[-len];
|
||||
ndefs = js_CodeSpec[op].ndefs;
|
||||
if (ndefs) {
|
||||
if (op == JSOP_FORELEM && regs.sp[-1] == JSVAL_FALSE)
|
||||
--ndefs;
|
||||
for (n = -ndefs; n < 0; n++) {
|
||||
char *bytes = js_DecompileValueGenerator(cx, n, regs.sp[n],
|
||||
NULL);
|
||||
if (bytes) {
|
||||
fprintf(tracefp, "%s %s",
|
||||
(n == -ndefs) ? " output:" : ",",
|
||||
bytes);
|
||||
JS_free(cx, bytes);
|
||||
}
|
||||
}
|
||||
fprintf(tracefp, " @ %d\n", regs.sp - fp->spbase);
|
||||
}
|
||||
fprintf(tracefp, " stack: ");
|
||||
for (siter = fp->spbase; siter < regs.sp; siter++) {
|
||||
str = js_ValueToString(cx, *siter);
|
||||
if (!str)
|
||||
fputs("<null>", tracefp);
|
||||
else
|
||||
js_FileEscapedString(tracefp, str, 0);
|
||||
fputc(' ', tracefp);
|
||||
}
|
||||
fputc('\n', tracefp);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
#endif /* !JS_THREADED_INTERP */
|
||||
|
||||
|
@ -507,6 +507,13 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp);
|
||||
extern JSBool
|
||||
js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2);
|
||||
|
||||
/*
|
||||
* Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the
|
||||
* previous opcode.
|
||||
*/
|
||||
extern void
|
||||
js_TraceOpcode(JSContext *cx, jsint len);
|
||||
|
||||
/*
|
||||
* JS_OPMETER helper functions.
|
||||
*/
|
||||
|
@ -88,6 +88,8 @@
|
||||
#include "jsdtracef.h"
|
||||
#endif
|
||||
|
||||
#include "jsautooplen.h"
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
#define NATIVE_DROP_PROPERTY js_DropProperty
|
||||
|
||||
|
@ -75,6 +75,14 @@
|
||||
# include "jsnum.h"
|
||||
#endif
|
||||
|
||||
#include "jsautooplen.h"
|
||||
|
||||
/* Verify JSOP_XXX_LENGTH constant definitions. */
|
||||
#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
|
||||
JS_STATIC_ASSERT(op##_LENGTH == length);
|
||||
#include "jsopcode.tbl"
|
||||
#undef OPDEF
|
||||
|
||||
static const char js_incop_strs[][3] = {"++", "--"};
|
||||
|
||||
const JSCodeSpec js_CodeSpec[] = {
|
||||
@ -2152,14 +2160,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||
todo = -2;
|
||||
break;
|
||||
|
||||
case JSOP_SWAP:
|
||||
/*
|
||||
* We don't generate this opcode currently, and previously we
|
||||
* did not need to decompile it. If old, serialized bytecode
|
||||
* uses it still, we should fall through and set todo = -2.
|
||||
*/
|
||||
/* FALL THROUGH */
|
||||
|
||||
case JSOP_GOSUB:
|
||||
case JSOP_GOSUBX:
|
||||
/*
|
||||
@ -4993,8 +4993,7 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
|
||||
|
||||
/* None of these stack-writing ops generates novel values. */
|
||||
JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX &&
|
||||
op != JSOP_DUP && op != JSOP_DUP2 &&
|
||||
op != JSOP_SWAP);
|
||||
op != JSOP_DUP && op != JSOP_DUP2);
|
||||
|
||||
/*
|
||||
* |this| could convert to a very long object initialiser, so cite it by
|
||||
@ -5274,13 +5273,6 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
pcstack[pcdepth + 3] = pcstack[pcdepth + 1];
|
||||
break;
|
||||
|
||||
case JSOP_SWAP:
|
||||
JS_ASSERT(ndefs == 2);
|
||||
pc2 = pcstack[pcdepth];
|
||||
pcstack[pcdepth] = pcstack[pcdepth + 1];
|
||||
pcstack[pcdepth + 1] = pc2;
|
||||
break;
|
||||
|
||||
case JSOP_LEAVEBLOCKEXPR:
|
||||
/*
|
||||
* The decompiler wants to see [leaveblockexpr] on pcstack, not
|
||||
|
@ -60,14 +60,6 @@ typedef enum JSOp {
|
||||
JSOP_LIMIT
|
||||
} JSOp;
|
||||
|
||||
typedef enum JSOpLength {
|
||||
#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
|
||||
op##_LENGTH = length,
|
||||
#include "jsopcode.tbl"
|
||||
#undef OPDEF
|
||||
JSOP_LIMIT_LENGTH
|
||||
} JSOpLength;
|
||||
|
||||
/*
|
||||
* JS bytecode formats.
|
||||
*/
|
||||
|
@ -97,7 +97,7 @@
|
||||
/* legend: op val name image len use def prec format */
|
||||
|
||||
/* Longstanding JavaScript bytecodes. */
|
||||
OPDEF(JSOP_NOP, 0, "nop", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_INTERRUPT, 0, "interrupt", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_PUSH, 1, "push", NULL, 1, 0, 1, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_POPV, 2, "popv", NULL, 1, 1, 0, 2, JOF_BYTE)
|
||||
OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD)
|
||||
@ -331,9 +331,9 @@ OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Swap the top two stack elements.
|
||||
* Generic nop for the decompiler.
|
||||
*/
|
||||
OPDEF(JSOP_SWAP, 135,"swap", NULL, 1, 2, 2, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_NOP, 135,"nop", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Bytecodes that avoid making an arguments object in most cases:
|
||||
|
121
js/src/jsoplengen.cpp
Normal file
121
js/src/jsoplengen.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set sw=4 ts=8 et tw=80:
|
||||
*
|
||||
* ***** 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 String Switch Generator for JavaScript Keywords,
|
||||
* released 2005-12-09.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Igor Bukanov.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005-2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
int length;
|
||||
} pairs[] = {
|
||||
#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
|
||||
{ #op, length } ,
|
||||
#include "jsopcode.tbl"
|
||||
#undef OPDEF
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
size_t maxNameWidth, i, nameWidth, tabStop;
|
||||
int lengthGap;
|
||||
|
||||
static const char prefix[] = "#define ";
|
||||
static const char suffix[] = "_LENGTH";
|
||||
static const size_t tabWidth = 8;
|
||||
static const size_t prefixWidth = sizeof(prefix) - 1;
|
||||
static const size_t suffixWidth = sizeof(suffix) - 1;
|
||||
|
||||
if (argc != 2) {
|
||||
fputs("Bad usage\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fp = fopen(argv[1], "w");
|
||||
if (!fp) {
|
||||
perror("fopen");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
fputs("/*\n"
|
||||
" * Automatically generated header with JS opcode length constants.\n"
|
||||
" *\n"
|
||||
" * Do not edit it, alter jsopcode.tbl instead.\n"
|
||||
" */\n",
|
||||
fp);
|
||||
|
||||
/*
|
||||
* Print
|
||||
*
|
||||
* #define name_LENGTH length
|
||||
*
|
||||
* with all length values aligned on the same column. The column is at the
|
||||
* second character position after a tab-stop with the first position
|
||||
* reserved for the minus sign of variable-length opcodes.
|
||||
*/
|
||||
maxNameWidth = 0;
|
||||
for (i = 0; i != sizeof pairs / sizeof pairs[0]; ++i) {
|
||||
nameWidth = strlen(pairs[i].name);
|
||||
if (maxNameWidth < nameWidth)
|
||||
maxNameWidth = nameWidth;
|
||||
}
|
||||
|
||||
tabStop = prefixWidth + maxNameWidth + suffixWidth + 1;
|
||||
tabStop = (tabStop + tabWidth - 1) / tabWidth * tabWidth;
|
||||
for (i = 0; i != sizeof pairs / sizeof pairs[0]; ++i) {
|
||||
lengthGap = (int) (tabStop - prefixWidth - strlen(pairs[i].name) -
|
||||
suffixWidth);
|
||||
fprintf(fp, "%s%s%s%*c%2d\n",
|
||||
prefix, pairs[i].name, suffix, lengthGap, ' ',
|
||||
pairs[i].length);
|
||||
if (ferror(fp)) {
|
||||
perror("fclose");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (fclose(fp)) {
|
||||
perror("fclose");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -202,7 +202,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
|
||||
* before deserialization of bytecode. If the saved version does not match
|
||||
* the current version, abort deserialization and invalidate the file.
|
||||
*/
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 25)
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 26)
|
||||
|
||||
/*
|
||||
* Library-private functions.
|
||||
|
@ -192,8 +192,8 @@ AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports,
|
||||
mFrame.callee = JS_GetFunctionObject(fun);
|
||||
mFrame.scopeChain = JS_GetParent(cx, mFrame.callee);
|
||||
mFrame.down = cx->fp;
|
||||
mRegs.pc = script->code + script->length
|
||||
- JSOP_STOP_LENGTH;
|
||||
mRegs.pc = script->code + script->length - 1;
|
||||
JS_ASSERT(static_cast<JSOp>(*mRegs.pc) == JSOP_STOP);
|
||||
mRegs.sp = NULL;
|
||||
mFrame.regs = &mRegs;
|
||||
cx->fp = &mFrame;
|
||||
|
@ -185,11 +185,9 @@ endif
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJS) $(GARBAGE)
|
||||
@cd fdlibm; $(MAKE) -f Makefile.ref clean
|
||||
|
||||
clobber:
|
||||
rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES)
|
||||
@cd fdlibm; $(MAKE) -f Makefile.ref clobber
|
||||
|
||||
tar:
|
||||
tar cvf $(TARNAME) $(TARFILES)
|
||||
|
Loading…
Reference in New Issue
Block a user