stack space in functions with more than one native function call.
+2004-08-13 Rhys Weatherley <rweather@southern-storm.com.au>
+
+ * include/jit/jit-insn.h, include/jit/jit-opcode.h,
+ include/jit/jit-plus.h, jit/jit-insn.c, jit/jit-internal.h,
+ jit/jit-interp.h, jit/jit-opcode.c, jit/jit-rules-interp.c,
+ jitplus/jit-plus-function.cpp: re-implement the "push_return_area_ptr"
+ patch so as to avoid wasting stack space in functions with more
+ than one native function call.
+
2004-08-12 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-rules-interp.c: account for the extra value that is
int jit_insn_set_param_ptr
(jit_function_t func, jit_value_t value, jit_type_t type,
jit_nint offset) JIT_NOTHROW;
+int jit_insn_push_return_area_ptr(jit_function_t func) JIT_NOTHROW;
int jit_insn_pop_stack(jit_function_t func, jit_nint num_items) JIT_NOTHROW;
int jit_insn_defer_pop_stack
(jit_function_t func, jit_nint num_items) JIT_NOTHROW;
#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
/*
* Pointer-relative loads and stores.
*/
-#define JIT_OP_LOAD_RELATIVE_SBYTE 0x0178
-#define JIT_OP_LOAD_RELATIVE_UBYTE 0x0179
-#define JIT_OP_LOAD_RELATIVE_SHORT 0x017A
-#define JIT_OP_LOAD_RELATIVE_USHORT 0x017B
-#define JIT_OP_LOAD_RELATIVE_INT 0x017C
-#define JIT_OP_LOAD_RELATIVE_LONG 0x017D
-#define JIT_OP_LOAD_RELATIVE_FLOAT32 0x017E
-#define JIT_OP_LOAD_RELATIVE_FLOAT64 0x017F
-#define JIT_OP_LOAD_RELATIVE_NFLOAT 0x0180
-#define JIT_OP_LOAD_RELATIVE_STRUCT 0x0181
-#define JIT_OP_STORE_RELATIVE_BYTE 0x0182
-#define JIT_OP_STORE_RELATIVE_SHORT 0x0183
-#define JIT_OP_STORE_RELATIVE_INT 0x0184
-#define JIT_OP_STORE_RELATIVE_LONG 0x0185
-#define JIT_OP_STORE_RELATIVE_FLOAT32 0x0186
-#define JIT_OP_STORE_RELATIVE_FLOAT64 0x0187
-#define JIT_OP_STORE_RELATIVE_NFLOAT 0x0188
-#define JIT_OP_STORE_RELATIVE_STRUCT 0x0189
-#define JIT_OP_ADD_RELATIVE 0x018A
+#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
/*
* Array element loads and stores.
*/
-#define JIT_OP_LOAD_ELEMENT_SBYTE 0x018B
-#define JIT_OP_LOAD_ELEMENT_UBYTE 0x018C
-#define JIT_OP_LOAD_ELEMENT_SHORT 0x018D
-#define JIT_OP_LOAD_ELEMENT_USHORT 0x018E
-#define JIT_OP_LOAD_ELEMENT_INT 0x018F
-#define JIT_OP_LOAD_ELEMENT_LONG 0x0190
-#define JIT_OP_LOAD_ELEMENT_FLOAT32 0x0191
-#define JIT_OP_LOAD_ELEMENT_FLOAT64 0x0192
-#define JIT_OP_LOAD_ELEMENT_NFLOAT 0x0193
-#define JIT_OP_STORE_ELEMENT_BYTE 0x0194
-#define JIT_OP_STORE_ELEMENT_SHORT 0x0195
-#define JIT_OP_STORE_ELEMENT_INT 0x0196
-#define JIT_OP_STORE_ELEMENT_LONG 0x0197
-#define JIT_OP_STORE_ELEMENT_FLOAT32 0x0198
-#define JIT_OP_STORE_ELEMENT_FLOAT64 0x0199
-#define JIT_OP_STORE_ELEMENT_NFLOAT 0x019A
+#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
/*
* Block operations.
*/
-#define JIT_OP_MEMCPY 0x019B
-#define JIT_OP_MEMMOVE 0x019C
-#define JIT_OP_MEMSET 0x019D
+#define JIT_OP_MEMCPY 0x019C
+#define JIT_OP_MEMMOVE 0x019D
+#define JIT_OP_MEMSET 0x019E
/*
* Allocate memory from the stack.
*/
-#define JIT_OP_ALLOCA 0x019E
+#define JIT_OP_ALLOCA 0x019F
/*
* The number of opcodes in the above list.
*/
-#define JIT_OP_NUM_OPCODES 0x019F
+#define JIT_OP_NUM_OPCODES 0x01A0
/*
* Opcode information.
void insn_set_param(const jit_value& value, jit_nint offset);
void insn_set_param_ptr
(const jit_value& value, jit_type_t type, jit_nint offset);
+ void insn_push_return_area_ptr();
void insn_return(const jit_value& value);
void insn_return();
void insn_return_ptr(const jit_value& value, jit_type_t type);
}
}
+ /* We are making a native call */
+ flags |= JIT_CALL_NATIVE;
+
/* Convert the arguments to the actual parameter types */
if(num_args > 0)
{
}
}
+ /* We are making a native call */
+ flags |= JIT_CALL_NATIVE;
+
/* Convert the arguments to the actual parameter types */
if(num_args > 0)
{
}
}
+/*@
+ * @deftypefun int jit_insn_push_return_area_ptr (jit_function_t func)
+ * Push the interpreter's return area pointer onto the stack.
+ * You normally wouldn't call this yourself - it is used internally
+ * by the CPU back ends to set up the stack for a subroutine call.
+ * @end deftypefun
+@*/
+int jit_insn_push_return_area_ptr(jit_function_t func)
+{
+ return create_noarg_note(func, JIT_OP_PUSH_RETURN_AREA_PTR);
+}
+
/*@
* @deftypefun int jit_insn_pop_stack (jit_function_t func, jit_nint num_items)
* Pop @code{num_items} items from the function call stack. You normally
extern struct _jit_type const _jit_type_nfloat_def;
extern struct _jit_type const _jit_type_void_ptr_def;
+/*
+ * Extra call flags for internal use.
+ */
+#define JIT_CALL_NATIVE (1 << 14)
+
#ifdef __cplusplus
};
#endif
#define JIT_OP_PUSH_RETURN_FLOAT64 (JIT_OP_NUM_OPCODES + 0x002D)
#define JIT_OP_PUSH_RETURN_NFLOAT (JIT_OP_NUM_OPCODES + 0x002E)
#define JIT_OP_PUSH_RETURN_SMALL_STRUCT (JIT_OP_NUM_OPCODES + 0x002F)
-#define JIT_OP_PUSH_RETURN_AREA_PTR (JIT_OP_NUM_OPCODES + 0x0030)
/*
* Nested function call handling.
*/
-#define JIT_OP_IMPORT_LOCAL (JIT_OP_NUM_OPCODES + 0x0031)
-#define JIT_OP_IMPORT_ARG (JIT_OP_NUM_OPCODES + 0x0032)
+#define JIT_OP_IMPORT_LOCAL (JIT_OP_NUM_OPCODES + 0x0030)
+#define JIT_OP_IMPORT_ARG (JIT_OP_NUM_OPCODES + 0x0031)
/*
* Push constant values onto the stack.
*/
-#define JIT_OP_PUSH_CONST_INT (JIT_OP_NUM_OPCODES + 0x0033)
-#define JIT_OP_PUSH_CONST_LONG (JIT_OP_NUM_OPCODES + 0x0034)
-#define JIT_OP_PUSH_CONST_FLOAT32 (JIT_OP_NUM_OPCODES + 0x0035)
-#define JIT_OP_PUSH_CONST_FLOAT64 (JIT_OP_NUM_OPCODES + 0x0036)
-#define JIT_OP_PUSH_CONST_NFLOAT (JIT_OP_NUM_OPCODES + 0x0037)
+#define JIT_OP_PUSH_CONST_INT (JIT_OP_NUM_OPCODES + 0x0032)
+#define JIT_OP_PUSH_CONST_LONG (JIT_OP_NUM_OPCODES + 0x0033)
+#define JIT_OP_PUSH_CONST_FLOAT32 (JIT_OP_NUM_OPCODES + 0x0034)
+#define JIT_OP_PUSH_CONST_FLOAT64 (JIT_OP_NUM_OPCODES + 0x0035)
+#define JIT_OP_PUSH_CONST_NFLOAT (JIT_OP_NUM_OPCODES + 0x0036)
/*
* Marker opcode for the end of the interpreter-specific opcodes.
*/
-#define JIT_OP_END_MARKER (JIT_OP_NUM_OPCODES + 0x003B)
+#define JIT_OP_END_MARKER (JIT_OP_NUM_OPCODES + 0x0037)
/*
* Number of interpreter-specific opcodes.
{"set_param_float64", F_(EMPTY, FLOAT64, PTR)},
{"set_param_nfloat", F_(EMPTY, NFLOAT, PTR)},
{"set_param_struct", F_(PTR, PTR, PTR)},
+ {"push_return_area_ptr", F_(EMPTY, EMPTY, EMPTY)},
/*
* Pointer-relative loads and stores.
{"push_return_float64", 0},
{"push_return_nfloat", 0},
{"push_return_small_struct", JIT_OPCODE_NINT_ARG},
- {"push_return_area_ptr", 0},
/*
* Nested function call handling.
return 0;
}
}
+ else if((flags & JIT_CALL_NATIVE) != 0)
+ {
+ /* Native calls always return a return area pointer */
+ if(!jit_insn_push_return_area_ptr(func))
+ {
+ return 0;
+ }
+ *struct_return = 0;
+ }
else
{
*struct_return = 0;
case JIT_OP_CALL_INDIRECT:
{
/* Call a function, whose pointer is supplied on the stack */
- if(!jit_type_return_via_pointer
- (jit_type_get_return((jit_type_t)(insn->value2))))
- {
- jit_cache_opcode(&(gen->posn), JIT_OP_PUSH_RETURN_AREA_PTR);
- ++(gen->max_working_area); /* Account for extra value */
- }
reg = _jit_regs_load_to_top(gen, insn->value1, 0, 0);
jit_cache_opcode(&(gen->posn), insn->opcode);
jit_cache_native(&(gen->posn), (jit_nint)(insn->value2));
case JIT_OP_CALL_EXTERNAL:
{
/* Call a native function, whose pointer is supplied explicitly */
- if(!jit_type_return_via_pointer
- (jit_type_get_return((jit_type_t)(insn->value2))))
- {
- jit_cache_opcode(&(gen->posn), JIT_OP_PUSH_RETURN_AREA_PTR);
- ++(gen->max_working_area); /* Account for extra value */
- }
jit_cache_opcode(&(gen->posn), insn->opcode);
jit_cache_native(&(gen->posn), (jit_nint)(insn->value2));
jit_cache_native(&(gen->posn), (jit_nint)(insn->dest));
}
break;
+ case JIT_OP_PUSH_RETURN_AREA_PTR:
+ {
+ /* Push the address of the interpreter's return area */
+ _jit_regs_spill_all(gen);
+ jit_cache_opcode(&(gen->posn), insn->opcode);
+ adjust_working(gen, 1);
+ }
+ break;
+
case JIT_OP_POP_STACK:
{
/* Pop parameter values from the stack after a function returns */
* @deftypemethodx jit_function void insn_push_ptr ({const jit_value&} value, jit_type_t type)
* @deftypemethodx jit_function void insn_set_param ({const jit_value&} value, jit_nint offset)
* @deftypemethodx jit_function void insn_set_param_ptr ({const jit_value&} value, jit_type_t type, jit_nint offset)
+ * @deftypemethodx jit_function void insn_push_return_area_ptr ()
* @deftypemethodx jit_function void insn_return ({const jit_value&} value)
* @deftypemethodx jit_function void insn_return ()
* @deftypemethodx jit_function void insn_return_ptr ({const jit_value&} value, jit_type_t type)
}
}
+void jit_function::insn_push_return_area_ptr()
+{
+ if(!jit_insn_push_return_area_ptr(func))
+ {
+ out_of_memory();
+ }
+}
+
void jit_function::insn_return(const jit_value& value)
{
if(!jit_insn_return(func, value.raw()))