#define JIT_OP_CALL 0x013D
#define JIT_OP_CALL_TAIL 0x013E
#define JIT_OP_CALL_INDIRECT 0x013F
-#define JIT_OP_CALL_VTABLE_PTR 0x0140
-#define JIT_OP_CALL_EXTERNAL 0x0141
-#define JIT_OP_RETURN 0x0142
-#define JIT_OP_RETURN_INT 0x0143
-#define JIT_OP_RETURN_LONG 0x0144
-#define JIT_OP_RETURN_FLOAT32 0x0145
-#define JIT_OP_RETURN_FLOAT64 0x0146
-#define JIT_OP_RETURN_NFLOAT 0x0147
-#define JIT_OP_RETURN_SMALL_STRUCT 0x0148
-#define JIT_OP_SETUP_FOR_NESTED 0x0149
-#define JIT_OP_SETUP_FOR_SIBLING 0x014A
-#define JIT_OP_IMPORT 0x014B
+#define JIT_OP_CALL_INDIRECT_TAIL 0x0140
+#define JIT_OP_CALL_VTABLE_PTR 0x0141
+#define JIT_OP_CALL_VTABLE_PTR_TAIL 0x0142
+#define JIT_OP_CALL_EXTERNAL 0x0143
+#define JIT_OP_CALL_EXTERNAL_TAIL 0x0144
+#define JIT_OP_RETURN 0x0145
+#define JIT_OP_RETURN_INT 0x0146
+#define JIT_OP_RETURN_LONG 0x0147
+#define JIT_OP_RETURN_FLOAT32 0x0148
+#define JIT_OP_RETURN_FLOAT64 0x0149
+#define JIT_OP_RETURN_NFLOAT 0x014A
+#define JIT_OP_RETURN_SMALL_STRUCT 0x014B
+#define JIT_OP_SETUP_FOR_NESTED 0x014C
+#define JIT_OP_SETUP_FOR_SIBLING 0x014D
+#define JIT_OP_IMPORT 0x014E
/*
* Exception handling.
*/
-#define JIT_OP_THROW 0x014C
-#define JIT_OP_RETHROW 0x014D
-#define JIT_OP_LOAD_PC 0x014E
-#define JIT_OP_LOAD_EXCEPTION_PC 0x014F
-#define JIT_OP_ENTER_FINALLY 0x0150
-#define JIT_OP_LEAVE_FINALLY 0x0151
-#define JIT_OP_CALL_FINALLY 0x0152
-#define JIT_OP_ENTER_FILTER 0x0153
-#define JIT_OP_LEAVE_FILTER 0x0154
-#define JIT_OP_CALL_FILTER 0x0155
-#define JIT_OP_CALL_FILTER_RETURN 0x0156
-#define JIT_OP_ADDRESS_OF_LABEL 0x0157
+#define JIT_OP_THROW 0x014F
+#define JIT_OP_RETHROW 0x0150
+#define JIT_OP_LOAD_PC 0x0151
+#define JIT_OP_LOAD_EXCEPTION_PC 0x0152
+#define JIT_OP_ENTER_FINALLY 0x0153
+#define JIT_OP_LEAVE_FINALLY 0x0154
+#define JIT_OP_CALL_FINALLY 0x0155
+#define JIT_OP_ENTER_FILTER 0x0156
+#define JIT_OP_LEAVE_FILTER 0x0157
+#define JIT_OP_CALL_FILTER 0x0158
+#define JIT_OP_CALL_FILTER_RETURN 0x0159
+#define JIT_OP_ADDRESS_OF_LABEL 0x015A
/*
* Data manipulation.
*/
-#define JIT_OP_COPY_LOAD_SBYTE 0x0158
-#define JIT_OP_COPY_LOAD_UBYTE 0x0159
-#define JIT_OP_COPY_LOAD_SHORT 0x015A
-#define JIT_OP_COPY_LOAD_USHORT 0x015B
-#define JIT_OP_COPY_INT 0x015C
-#define JIT_OP_COPY_LONG 0x015D
-#define JIT_OP_COPY_FLOAT32 0x015E
-#define JIT_OP_COPY_FLOAT64 0x015F
-#define JIT_OP_COPY_NFLOAT 0x0160
-#define JIT_OP_COPY_STRUCT 0x0161
-#define JIT_OP_COPY_STORE_BYTE 0x0162
-#define JIT_OP_COPY_STORE_SHORT 0x0163
-#define JIT_OP_ADDRESS_OF 0x0164
+#define JIT_OP_COPY_LOAD_SBYTE 0x015B
+#define JIT_OP_COPY_LOAD_UBYTE 0x015C
+#define JIT_OP_COPY_LOAD_SHORT 0x015D
+#define JIT_OP_COPY_LOAD_USHORT 0x015E
+#define JIT_OP_COPY_INT 0x015F
+#define JIT_OP_COPY_LONG 0x0160
+#define JIT_OP_COPY_FLOAT32 0x0161
+#define JIT_OP_COPY_FLOAT64 0x0162
+#define JIT_OP_COPY_NFLOAT 0x0163
+#define JIT_OP_COPY_STRUCT 0x0164
+#define JIT_OP_COPY_STORE_BYTE 0x0165
+#define JIT_OP_COPY_STORE_SHORT 0x0166
+#define JIT_OP_ADDRESS_OF 0x0167
/*
* Incoming registers, outgoing registers, and stack pushes.
*/
-#define JIT_OP_INCOMING_REG 0x0165
-#define JIT_OP_INCOMING_FRAME_POSN 0x0166
-#define JIT_OP_OUTGOING_REG 0x0167
-#define JIT_OP_OUTGOING_FRAME_POSN 0x0168
-#define JIT_OP_RETURN_REG 0x0169
-#define JIT_OP_PUSH_INT 0x016A
-#define JIT_OP_PUSH_LONG 0x016B
-#define JIT_OP_PUSH_FLOAT32 0x016C
-#define JIT_OP_PUSH_FLOAT64 0x016D
-#define JIT_OP_PUSH_NFLOAT 0x016E
-#define JIT_OP_PUSH_STRUCT 0x016F
-#define JIT_OP_POP_STACK 0x0170
-#define JIT_OP_FLUSH_SMALL_STRUCT 0x0171
-#define JIT_OP_SET_PARAM_INT 0x0172
-#define JIT_OP_SET_PARAM_LONG 0x0173
-#define JIT_OP_SET_PARAM_FLOAT32 0x0174
-#define JIT_OP_SET_PARAM_FLOAT64 0x0175
-#define JIT_OP_SET_PARAM_NFLOAT 0x0176
-#define JIT_OP_SET_PARAM_STRUCT 0x0177
-#define JIT_OP_PUSH_RETURN_AREA_PTR 0x0178
+#define JIT_OP_INCOMING_REG 0x0168
+#define JIT_OP_INCOMING_FRAME_POSN 0x0169
+#define JIT_OP_OUTGOING_REG 0x016A
+#define JIT_OP_OUTGOING_FRAME_POSN 0x016B
+#define JIT_OP_RETURN_REG 0x016C
+#define JIT_OP_PUSH_INT 0x016D
+#define JIT_OP_PUSH_LONG 0x016E
+#define JIT_OP_PUSH_FLOAT32 0x016F
+#define JIT_OP_PUSH_FLOAT64 0x0170
+#define JIT_OP_PUSH_NFLOAT 0x0171
+#define JIT_OP_PUSH_STRUCT 0x0172
+#define JIT_OP_POP_STACK 0x0173
+#define JIT_OP_FLUSH_SMALL_STRUCT 0x0174
+#define JIT_OP_SET_PARAM_INT 0x0175
+#define JIT_OP_SET_PARAM_LONG 0x0176
+#define JIT_OP_SET_PARAM_FLOAT32 0x0177
+#define JIT_OP_SET_PARAM_FLOAT64 0x0178
+#define JIT_OP_SET_PARAM_NFLOAT 0x0179
+#define JIT_OP_SET_PARAM_STRUCT 0x017A
+#define JIT_OP_PUSH_RETURN_AREA_PTR 0x017B
/*
* Pointer-relative loads and stores.
*/
-#define JIT_OP_LOAD_RELATIVE_SBYTE 0x0179
-#define JIT_OP_LOAD_RELATIVE_UBYTE 0x017A
-#define JIT_OP_LOAD_RELATIVE_SHORT 0x017B
-#define JIT_OP_LOAD_RELATIVE_USHORT 0x017C
-#define JIT_OP_LOAD_RELATIVE_INT 0x017D
-#define JIT_OP_LOAD_RELATIVE_LONG 0x017E
-#define JIT_OP_LOAD_RELATIVE_FLOAT32 0x017F
-#define JIT_OP_LOAD_RELATIVE_FLOAT64 0x0180
-#define JIT_OP_LOAD_RELATIVE_NFLOAT 0x0181
-#define JIT_OP_LOAD_RELATIVE_STRUCT 0x0182
-#define JIT_OP_STORE_RELATIVE_BYTE 0x0183
-#define JIT_OP_STORE_RELATIVE_SHORT 0x0184
-#define JIT_OP_STORE_RELATIVE_INT 0x0185
-#define JIT_OP_STORE_RELATIVE_LONG 0x0186
-#define JIT_OP_STORE_RELATIVE_FLOAT32 0x0187
-#define JIT_OP_STORE_RELATIVE_FLOAT64 0x0188
-#define JIT_OP_STORE_RELATIVE_NFLOAT 0x0189
-#define JIT_OP_STORE_RELATIVE_STRUCT 0x018A
-#define JIT_OP_ADD_RELATIVE 0x018B
+#define JIT_OP_LOAD_RELATIVE_SBYTE 0x017C
+#define JIT_OP_LOAD_RELATIVE_UBYTE 0x017D
+#define JIT_OP_LOAD_RELATIVE_SHORT 0x017E
+#define JIT_OP_LOAD_RELATIVE_USHORT 0x017F
+#define JIT_OP_LOAD_RELATIVE_INT 0x0180
+#define JIT_OP_LOAD_RELATIVE_LONG 0x0181
+#define JIT_OP_LOAD_RELATIVE_FLOAT32 0x0182
+#define JIT_OP_LOAD_RELATIVE_FLOAT64 0x0183
+#define JIT_OP_LOAD_RELATIVE_NFLOAT 0x0184
+#define JIT_OP_LOAD_RELATIVE_STRUCT 0x0185
+#define JIT_OP_STORE_RELATIVE_BYTE 0x0186
+#define JIT_OP_STORE_RELATIVE_SHORT 0x0187
+#define JIT_OP_STORE_RELATIVE_INT 0x0188
+#define JIT_OP_STORE_RELATIVE_LONG 0x0189
+#define JIT_OP_STORE_RELATIVE_FLOAT32 0x018A
+#define JIT_OP_STORE_RELATIVE_FLOAT64 0x018B
+#define JIT_OP_STORE_RELATIVE_NFLOAT 0x018C
+#define JIT_OP_STORE_RELATIVE_STRUCT 0x018D
+#define JIT_OP_ADD_RELATIVE 0x018E
/*
* Array element loads and stores.
*/
-#define JIT_OP_LOAD_ELEMENT_SBYTE 0x018C
-#define JIT_OP_LOAD_ELEMENT_UBYTE 0x018D
-#define JIT_OP_LOAD_ELEMENT_SHORT 0x018E
-#define JIT_OP_LOAD_ELEMENT_USHORT 0x018F
-#define JIT_OP_LOAD_ELEMENT_INT 0x0190
-#define JIT_OP_LOAD_ELEMENT_LONG 0x0191
-#define JIT_OP_LOAD_ELEMENT_FLOAT32 0x0192
-#define JIT_OP_LOAD_ELEMENT_FLOAT64 0x0193
-#define JIT_OP_LOAD_ELEMENT_NFLOAT 0x0194
-#define JIT_OP_STORE_ELEMENT_BYTE 0x0195
-#define JIT_OP_STORE_ELEMENT_SHORT 0x0196
-#define JIT_OP_STORE_ELEMENT_INT 0x0197
-#define JIT_OP_STORE_ELEMENT_LONG 0x0198
-#define JIT_OP_STORE_ELEMENT_FLOAT32 0x0199
-#define JIT_OP_STORE_ELEMENT_FLOAT64 0x019A
-#define JIT_OP_STORE_ELEMENT_NFLOAT 0x019B
+#define JIT_OP_LOAD_ELEMENT_SBYTE 0x018F
+#define JIT_OP_LOAD_ELEMENT_UBYTE 0x0190
+#define JIT_OP_LOAD_ELEMENT_SHORT 0x0191
+#define JIT_OP_LOAD_ELEMENT_USHORT 0x0192
+#define JIT_OP_LOAD_ELEMENT_INT 0x0193
+#define JIT_OP_LOAD_ELEMENT_LONG 0x0194
+#define JIT_OP_LOAD_ELEMENT_FLOAT32 0x0195
+#define JIT_OP_LOAD_ELEMENT_FLOAT64 0x0196
+#define JIT_OP_LOAD_ELEMENT_NFLOAT 0x0197
+#define JIT_OP_STORE_ELEMENT_BYTE 0x0198
+#define JIT_OP_STORE_ELEMENT_SHORT 0x0199
+#define JIT_OP_STORE_ELEMENT_INT 0x019A
+#define JIT_OP_STORE_ELEMENT_LONG 0x019B
+#define JIT_OP_STORE_ELEMENT_FLOAT32 0x019C
+#define JIT_OP_STORE_ELEMENT_FLOAT64 0x019D
+#define JIT_OP_STORE_ELEMENT_NFLOAT 0x019E
/*
* Block operations.
*/
-#define JIT_OP_MEMCPY 0x019C
-#define JIT_OP_MEMMOVE 0x019D
-#define JIT_OP_MEMSET 0x019E
+#define JIT_OP_MEMCPY 0x019F
+#define JIT_OP_MEMMOVE 0x01A0
+#define JIT_OP_MEMSET 0x01A1
/*
* Allocate memory from the stack.
*/
-#define JIT_OP_ALLOCA 0x019F
+#define JIT_OP_ALLOCA 0x01A2
/*
* Debugging support.
*/
-#define JIT_OP_MARK_OFFSET 0x01A0
-#define JIT_OP_MARK_BREAKPOINT 0x01A1
+#define JIT_OP_MARK_OFFSET 0x01A3
+#define JIT_OP_MARK_BREAKPOINT 0x01A4
/*
* The number of opcodes in the above list.
*/
-#define JIT_OP_NUM_OPCODES 0x01A2
+#define JIT_OP_NUM_OPCODES 0x01A5
/*
* Opcode information.
} \
} while (0)
+/*
+ * Perform a tail call to a new function.
+ */
+#define VM_PERFORM_TAIL(newfunc) \
+ { \
+ if(jbuf) \
+ { \
+ _jit_unwind_pop_setjmp(); \
+ } \
+ func = (newfunc); \
+ if(func->frame_size > current_frame_size) \
+ { \
+ current_frame_size = func->frame_size; \
+ frame_base = (jit_item *)alloca(current_frame_size); \
+ } \
+ stacktop = frame_base + func->working_area; \
+ frame = stacktop; \
+ goto restart_tail; \
+ }
+
/*
* Call "jit_apply" from the interpreter, to invoke a native function.
*/
void _jit_run_function(jit_function_interp_t func, jit_item *args,
jit_item *return_area)
{
+ jit_item *frame_base;
jit_item *frame;
jit_item *stacktop;
void **pc;
void *exception_pc = 0;
void *handler;
jit_jmp_buf *jbuf;
+ jit_nint current_frame_size;
/* Define the label table for computed goto dispatch */
#include "jit-interp-labels.h"
/* Set up the stack frame for this function */
- frame = (jit_item *)alloca(func->frame_size);
- stacktop = frame + func->working_area;
+ current_frame_size = func->frame_size;
+ frame_base = (jit_item *)alloca(current_frame_size);
+ stacktop = frame_base + func->working_area;
frame = stacktop;
/* Get the initial program counter */
+restart_tail:
pc = jit_function_interp_entry_pc(func);
/* Create a "setjmp" point if this function has a "try" block.
******************************************************************/
VMCASE(JIT_OP_CALL):
- VMCASE(JIT_OP_CALL_TAIL):
{
/* Call a function that is under the control of the JIT */
call_func = (jit_function_t)VM_NINT_ARG;
}
VMBREAK;
+ VMCASE(JIT_OP_CALL_TAIL):
+ {
+ /* Tail call a function that is under the control of the JIT */
+ call_func = (jit_function_t)VM_NINT_ARG;
+ entry = call_func->entry_point;
+ if(!entry)
+ {
+ entry = _jit_function_compile_on_demand(call_func);
+ }
+ VM_PERFORM_TAIL((jit_function_interp_t)entry);
+ }
+ /* Not reached */
+
VMCASE(JIT_OP_CALL_INDIRECT):
+ VMCASE(JIT_OP_CALL_INDIRECT_TAIL): /* Indirect tail not possible */
{
/* Call a native function via an indirect pointer */
tempptr = (void *)VM_NINT_ARG;
}
VMBREAK;
+ VMCASE(JIT_OP_CALL_VTABLE_PTR_TAIL):
+ {
+ /* Tail call a JIT-managed function via indirect vtable pointer */
+ call_func = (jit_function_t)(VM_STK_PTR0);
+ if(!call_func)
+ {
+ VM_BUILTIN(JIT_RESULT_NULL_FUNCTION);
+ }
+ entry = call_func->entry_point;
+ if(!entry)
+ {
+ entry = _jit_function_compile_on_demand(call_func);
+ }
+ VM_PERFORM_TAIL((jit_function_interp_t)entry);
+ }
+ /* Not reached */
+
VMCASE(JIT_OP_CALL_EXTERNAL):
+ VMCASE(JIT_OP_CALL_EXTERNAL_TAIL): /* External tail not possible */
{
/* Call an external native function */
tempptr = (void *)VM_NINT_ARG;