fast-path emitter. At the moment we have lock fast-path on x86_64.
* src/vm/jit/builtin.cpp: Builtin table now needs emit-common.hpp included.
* src/vm/jit/builtintable.inc: Adapted to above change.
* src/threads/lock.hpp: Moved builtin function defines to where they belong.
* src/vm/jit/codegen-common.cpp (codegen_emit): Added preliminary fast-path
generation implementation. Yet to be fully optimized.
* src/vm/jit/emit-common.hpp: Added prototypes for lock fast-path emitters.
* src/vm/jit/x86_64/emit.c: Added stubs for lock fast-path emitters.
bool lock_monitor_enter(java_handle_t *);
bool lock_monitor_exit(java_handle_t *);
-#define LOCK_monitor_enter (functionptr) lock_monitor_enter
-#define LOCK_monitor_exit (functionptr) lock_monitor_exit
-
bool lock_is_held_by_current_thread(java_handle_t *o);
void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos);
#include "vm/string.hpp"
#include "vm/jit/asmpart.h"
+#include "vm/jit/emit-common.hpp"
#include "vm/jit/stubs.hpp"
#include "vm/jit/trace.hpp"
utf *name; /* name of the function */
utf *descriptor; /* descriptor of the function */
methoddesc *md;
+ functionptr emit_fastpath; /* emitter for fast-path code */
};
bool fast_subtype_check(struct _vftbl *, struct _vftbl *);
#endif
+/* From lock.hpp: bool lock_monitor_enter(java_handle_t *); */
+#define LOCK_monitor_enter (functionptr) lock_monitor_enter
+#if defined(__X86_64__)
+# define EMIT_FASTPATH_monitor_enter (functionptr) emit_fastpath_monitor_enter
+#else
+# define EMIT_FASTPATH_monitor_enter (functionptr) NULL
+#endif
+
+/* From lock.hpp: bool lock_monitor_exit(java_handle_t *); */
+#define LOCK_monitor_exit (functionptr) lock_monitor_exit
+#if defined(__X86_64__)
+# define EMIT_FASTPATH_monitor_exit (functionptr) emit_fastpath_monitor_exit
+#else
+# define EMIT_FASTPATH_monitor_exit (functionptr) NULL
+#endif
+
bool builtin_instanceof(java_handle_t *obj, classinfo *c);
/* NOT AN OP */
bool builtin_checkcast(java_handle_t *obj, classinfo *c);
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
NULL,
NULL,
NULL,
+ NULL,
NULL
},
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
NULL,
NULL,
NULL,
- NULL
+ NULL,
+ EMIT_FASTPATH_monitor_enter
},
{
ICMD_MONITOREXIT,
NULL,
NULL,
NULL,
- NULL
+ NULL,
+ EMIT_FASTPATH_monitor_exit
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
};
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif /* !SUPPORT_FLOAT */
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP */
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif /* !SUPPORT_DOUBLE */
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP */
NULL,
NULL,
NULL,
+ NULL,
NULL
},
{
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
NULL,
NULL,
NULL,
+ NULL,
NULL
},
};
NULL,
NULL,
NULL,
+ NULL,
NULL
},
NULL,
NULL,
NULL,
+ NULL,
NULL
},
#endif
NULL,
NULL,
NULL,
+ NULL,
NULL
},
NULL,
NULL,
NULL,
+ NULL,
NULL
},
NULL,
NULL,
NULL,
+ NULL,
NULL
},
};
}
#endif
+ // Emit the fast-path if available.
+ if (bte->emit_fastpath != NULL) {
+ void (*emit_fastpath)(jitdata* jd, instruction* iptr, int d);
+ emit_fastpath = (void (*)(jitdata* jd, instruction* iptr, int d)) bte->emit_fastpath;
+
+ assert(md->returntype.type == TYPE_VOID);
+ d = REG_ITMP1;
+
+ // Actually call the fast-path emitter.
+ emit_fastpath(jd, iptr, d);
+
+ // If fast-path succeeded, jump to the end of the builtin
+ // invocation.
+ // XXX Actually the slow-path block below should be moved
+ // out of the instruction stream and the jump below should be
+ // inverted.
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+ os::abort("codegen_emit: Implement jump over slow-path for this configuration.");
+#elif SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+ M_TEST(d);
+ emit_label_bne(cd, BRANCH_LABEL_10);
+#else
+# error Unable to generate code for this configuration!
+#endif
+ }
+
goto gen_method;
case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
break;
}
+ // If we are emitting a fast-path block, this is the label for
+ // successful fast-path execution.
+ if ((iptr->opc == ICMD_BUILTIN) && (bte->emit_fastpath != NULL)) {
+ emit_label(cd, BRANCH_LABEL_10);
+ }
+
break;
case ICMD_TABLESWITCH: /* ..., index ==> ... */
void emit_recompute_pv(codegendata* cd);
+/* machine dependent faspath-emitting functions */
+void emit_fastpath_monitor_enter(jitdata* jd, instruction* iptr, int d);
+void emit_fastpath_monitor_exit(jitdata* jd, instruction* iptr, int d);
+
#if defined(ENABLE_THREADS)
void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset);
void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset);
}
+/**
+ * Generates fast-path code for the below builtin.
+ * Function: LOCK_monitor_enter
+ * Signature: (Ljava/lang/Object;)V
+ * Slow-path: bool lock_monitor_enter(java_handle_t*);
+ */
+void emit_fastpath_monitor_enter(jitdata* jd, instruction* iptr, int d)
+{
+ // Get required compiler data.
+ codegendata* cd = jd->cd;
+
+ // XXX Currently the fast-path always fails. Implement me!
+ M_CLR(d);
+}
+
+
+/**
+ * Generates fast-path code for the below builtin.
+ * Function: LOCK_monitor_exit
+ * Signature: (Ljava/lang/Object;)V
+ * Slow-path: bool lock_monitor_exit(java_handle_t*);
+ */
+void emit_fastpath_monitor_exit(jitdata* jd, instruction* iptr, int d)
+{
+ // Get required compiler data.
+ codegendata* cd = jd->cd;
+
+ // XXX Currently the fast-path always fails. Implement me!
+ M_CLR(d);
+}
+
+
/**
* Generates synchronization code to enter a monitor.
*/