+2012-02-11 Aleksey Demakov <ademakov@gmail.com>
+
+ * jit/jit-cache.h, jit/jit-cache.c (_jit_cache_end_method): add
+ result argument that indicates if the code genration will need
+ to be restarted.
+ * jit/jit-cache.h, jit/jit-cache.c (jit_cache_mark_full): remove
+ macro and replace it with direct jit_cache_posn access where
+ appropriate.
+ * jit/jit-cache.h, jit/jit-cache.c (jit_cache_get_posn): likewise.
+ * jit/jit-cache.h, jit/jit-rules-interp.c (jit_cache_native): move
+ macro to where it only used.
+ * jit/jit-cache.h, jit/jit-cache.c: remove other unused stuff.
+
2012-01-21 Aleksey Demakov <ademakov@gmail.com>
* jit/jit-rules.h (struct jit_gencode): add offset_encoder field
void
_jit_cache_check_space(jit_cache_posn *posn, int space)
{
- if(!jit_cache_check_for_n(posn, space))
+ if((posn->ptr + space) >= posn->limit)
{
/* No space left on the current cache page. */
- jit_cache_mark_full(posn);
+ posn->ptr = posn->limit;
jit_exception_builtin(JIT_RESULT_CACHE_FULL);
}
}
return JIT_CACHE_OK;
}
-int _jit_cache_end_method(jit_cache_posn *posn)
+int
+_jit_cache_end_method(jit_cache_posn *posn, int result)
{
jit_cache_t cache = posn->cache;
jit_cache_method_t method;
jit_cache_method_t next;
+ if (result != JIT_CACHE_OK)
+ {
+ /* mark cache page full */
+ posn->ptr = posn->limit;
+ }
+
/* Determine if we ran out of space while writing the method */
if(posn->ptr >= posn->limit)
{
return (void *)ptr;
}
-void _jit_cache_align(jit_cache_posn *posn, int align, int diff, int nop)
-{
- jit_nuint current;
- jit_nuint next;
-
- /* Determine the location of the next alignment boundary */
- if(align <= 1)
- {
- align = 1;
- }
- current = (jit_nuint)(posn->ptr);
- next = (current + ((jit_nuint)align) - 1) &
- ~(((jit_nuint)align) - 1);
- if(current == next || (next - current) >= (jit_nuint)diff)
- {
- return;
- }
-
- /* Detect overflow of the free memory region */
- if(next > ((jit_nuint)(posn->limit)))
- {
- posn->ptr = posn->limit;
- return;
- }
-
-#ifndef jit_should_pad
- /* Fill from "current" to "next" with nop bytes */
- while(current < next)
- {
- *((posn->ptr)++) = (unsigned char)nop;
- ++current;
- }
-#else
- /* Use CPU-specific padding, because it may be more efficient */
- _jit_pad_buffer((unsigned char *)current, (int)(next - current));
-#endif
-}
-
jit_function_t
_jit_cache_get_method(jit_cache_t cache, void *pc)
{
for allocation. In this case a restart
won't help.
-To write code to the method, use the following:
-
- jit_cache_byte(&posn, value);
- jit_cache_word16(&posn, value);
- jit_cache_word32(&posn, value);
- jit_cache_native(&posn, value);
- jit_cache_word64(&posn, value);
-
-These macros write the value to cache and then update the current
-position. If the macros detect the end of the avaialable space,
-they will flag overflow, but otherwise do nothing (overflow is
-flagged when posn->ptr == posn->limit). The current position
-in the method can be obtained using "jit_cache_get_posn".
-
Some CPU optimization guides recommend that labels should be aligned.
This can be achieved using _jit_cache_align.
/*
* End output of a method. Returns zero if a restart.
*/
-int _jit_cache_end_method(jit_cache_posn *posn);
+int _jit_cache_end_method(jit_cache_posn *posn, int result);
/*
* Allocate "size" bytes of storage in the method cache's
void *_jit_cache_alloc_no_method
(jit_cache_t cache, unsigned long size, unsigned long align);
-/*
- * Align the method code on a particular boundary if the
- * difference between the current position and the aligned
- * boundary is less than "diff". The "nop" value is used
- * to pad unused bytes.
- */
-void _jit_cache_align(jit_cache_posn *posn, int align, int diff, int nop);
-
/*
* Find the method that is associated with a particular
* program counter. Returns NULL if the PC is not associated
*/
jit_function_t _jit_cache_get_method(jit_cache_t cache, void *pc);
-/*
- * Convert a return address into a program counter value
- * that can be used with "_jit_cache_get_method". Normally
- * return addresses point to the next instruction after
- * an instruction that falls within a method region. This
- * macro corrects for the "off by 1" address.
- */
-#define jit_cache_return_to_pc(addr) \
- ((void *)(((unsigned char *)(addr)) - 1))
-
-/*
- * Output a single byte to the current method.
- */
-#define jit_cache_byte(posn,value) \
- do { \
- if((posn)->ptr < (posn)->limit) \
- { \
- *(((posn)->ptr)++) = (unsigned char)(value); \
- } \
- } while (0)
-
-/*
- * Output a 16-bit word to the current method.
- */
-#define jit_cache_word16(posn,value) \
- do { \
- _jit_cache_check_space((posn), 2); \
- *((jit_ushort *)((posn)->ptr)) = (jit_ushort)(value); \
- (posn)->ptr += 2; \
- } while (0)
-
-/*
- * Output a 32-bit word to the current method.
- */
-#define jit_cache_word32(posn,value) \
- do { \
- _jit_cache_check_space((posn), 4); \
- *((jit_uint *)((posn)->ptr)) = (jit_uint)(value); \
- (posn)->ptr += 4; \
- } while (0)
-
-/*
- * Output a native word to the current method.
- */
-#define jit_cache_native(posn,value) \
- do { \
- _jit_cache_check_space((posn), sizeof(jit_nuint)); \
- *((jit_nuint *)((posn)->ptr)) = (jit_nuint)(value); \
- (posn)->ptr += sizeof(jit_nuint); \
- } while (0)
-
-/*
- * Output a 64-bit word to the current method.
- */
-#define jit_cache_word64(posn,value) \
- do { \
- _jit_cache_check_space((posn), 8); \
- *((jit_ulong *)((posn)->ptr)) = (jit_ulong)(value); \
- (posn)->ptr += 8; \
- } while (0)
-
-/*
- * Get the output position within the current method.
- */
-#define jit_cache_get_posn(posn) ((posn)->ptr)
-
-/*
- * Determine if there is sufficient space for N bytes in the current method.
- */
-#define jit_cache_check_for_n(posn,n) \
- (((posn)->ptr + (n)) <= (posn)->limit)
-
-/*
- * Mark the cache as full.
- */
-#define jit_cache_mark_full(posn) \
- do { \
- (posn)->ptr = (posn)->limit; \
- } while (0)
#ifdef __cplusplus
};
void
mark_offset(jit_gencode_t gen, jit_function_t func, unsigned long offset)
{
- unsigned char *ptr = jit_cache_get_posn(&gen->posn);
- unsigned long native_offset = ptr - func->start;
+ unsigned long native_offset = gen->posn.ptr - func->start;
if(!_jit_varint_encode_uint(&gen->offset_encoder, (jit_uint) offset))
{
jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
state->cache_started = 1;
}
+#if NOT_USED
+/*
+ * Align the method code on a particular boundary if the
+ * difference between the current position and the aligned
+ * boundary is less than "diff". The "nop" value is used
+ * to pad unused bytes.
+ */
+static void
+cache_align(jit_cache_posn *posn, int align, int diff, int nop)
+{
+ jit_nuint current;
+ jit_nuint next;
+
+ /* Determine the location of the next alignment boundary */
+ if(align <= 1)
+ {
+ align = 1;
+ }
+ current = (jit_nuint)(posn->ptr);
+ next = (current + ((jit_nuint)align) - 1) &
+ ~(((jit_nuint)align) - 1);
+ if(current == next || (next - current) >= (jit_nuint)diff)
+ {
+ return;
+ }
+
+ /* Detect overflow of the free memory region */
+ if(next > ((jit_nuint)(posn->limit)))
+ {
+ posn->ptr = posn->limit;
+ return;
+ }
+
+#ifndef jit_should_pad
+ /* Fill from "current" to "next" with nop bytes */
+ while(current < next)
+ {
+ *((posn->ptr)++) = (unsigned char)nop;
+ ++current;
+ }
+#else
+ /* Use CPU-specific padding, because it may be more efficient */
+ _jit_pad_buffer((unsigned char *)current, (int)(next - current));
+#endif
+}
+#endif
+
+
/*
* End function output to the cache.
*/
state->cache_started = 0;
/* End the function's output process */
- result = _jit_cache_end_method(&state->gen.posn);
+ result = _jit_cache_end_method(&state->gen.posn, JIT_CACHE_OK);
if(result != JIT_CACHE_OK)
{
if(result == JIT_CACHE_RESTART)
{
state->cache_started = 0;
- /* Make sure that the _jit_cache_end_method() call below will
- release the currently held cache space rather than make it
- allocated permanently */
- jit_cache_mark_full(&state->gen.posn);
-
- /* Actually release the cache space */
- _jit_cache_end_method(&state->gen.posn);
+ /* Release the cache space */
+ _jit_cache_end_method(&state->gen.posn, JIT_CACHE_RESTART);
/* Free encoded bytecode offset data */
_jit_varint_free_data(_jit_varint_get_data(&state->gen.offset_encoder));
@*/
+/*
+ * Output a native word to the current method.
+ */
+#define jit_cache_native(posn,value) \
+ do { \
+ _jit_cache_check_space((posn), sizeof(jit_nuint)); \
+ *((jit_nuint *)((posn)->ptr)) = (jit_nuint)(value); \
+ (posn)->ptr += sizeof(jit_nuint); \
+ } while (0)
+
/*
* Write an interpreter opcode to the cache.
*/