#define SET_FIELD(o,type,f,value) \
*((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
+ #define GET_FIELDINFO(f) ((fieldinfo*) (f))
+
#define JNI_SET_FIELD(name, type, intern) \
void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID, \
type value) \
\
SET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID, value); \
\
- LLNI_CRITICAL_START; \
+ LLNI_CRITICAL_END; \
+ \
+ if (GET_FIELDINFO(fieldID)->flags & ACC_VOLATILE) \
+ Atomic::memory_barrier(); \
}
JNI_SET_FIELD(Boolean, jboolean, s4)
SET_FIELD(obj, java_handle_t*, fieldID, LLNI_UNWRAP((java_handle_t*) value));
LLNI_CRITICAL_END;
+
+ if (GET_FIELDINFO(fieldID)->flags & ACC_VOLATILE)
+ Atomic::memory_barrier();
}
return; \
\
f->value->field = value; \
+ \
+ if (f->flags & ACC_VOLATILE) \
+ Atomic::memory_barrier(); \
}
JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
return;
f->value->a = LLNI_UNWRAP((java_handle_t *) value);
+
+ if (f->flags & ACC_VOLATILE)
+ Atomic::memory_barrier();
}
}
JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
-JNI_RELEASE_ARRAY_ELEMENTS(Byte, jbyte, byte, int8_t)
+JNI_RELEASE_ARRAY_ELEMENTS(Byte, jbyte, byte, s1)
JNI_RELEASE_ARRAY_ELEMENTS(Char, jchar, char, u2)
JNI_RELEASE_ARRAY_ELEMENTS(Short, jshort, short, s2)
JNI_RELEASE_ARRAY_ELEMENTS(Int, jint, int, s4)
}
JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
-JNI_GET_ARRAY_REGION(Byte, jbyte, byte, int8_t)
+JNI_GET_ARRAY_REGION(Byte, jbyte, byte, s1)
JNI_GET_ARRAY_REGION(Char, jchar, char, u2)
JNI_GET_ARRAY_REGION(Short, jshort, short, s2)
JNI_GET_ARRAY_REGION(Int, jint, int, s4)
}
JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
-JNI_SET_ARRAY_REGION(Byte, jbyte, byte, int8_t)
+JNI_SET_ARRAY_REGION(Byte, jbyte, byte, s1)
JNI_SET_ARRAY_REGION(Char, jchar, char, u2)
JNI_SET_ARRAY_REGION(Short, jshort, short, s2)
JNI_SET_ARRAY_REGION(Int, jint, int, s4)
classinfo* c = LLNI_classinfo_unwrap(clazz);
- /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
- if (jvmti) jvmti_NativeMethodBind(method, address, new_address_ptr);
- */
-
NativeMethods& nm = VM::get_current()->get_nativemethods();
nm.register_methods(c->name, methods, nMethods);
- return 0;
+ return 0;
}
case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
/* sx.val.i = constant */
+ case ICMD_IMULPOW2: /* ..., value ==> ..., value * (2 ^ constant) */
+ /* sx.val.i = constant */
case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
/* sx.val.l = constant */
+ case ICMD_LMULPOW2: /* ..., value ==> ..., value * (2 ^ constant) */
+ /* sx.val.l = constant */
case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
#if defined(__I386__)
// Generate architecture specific instructions.
codegen_emit_instruction(jd, iptr);
+ break;
#else
+ {
+ fieldinfo* fi;
+ patchref_t* pr;
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_field* uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = dseg_add_unique_address(cd, 0);
- patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
+ pr = patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
}
else {
- fieldinfo* fi = iptr->sx.s23.s3.fmiref->p.field;
+ fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
}
}
+ #if defined(USES_PATCHABLE_MEMORY_BARRIER)
+ codegen_emit_patchable_barrier(iptr, cd, pr, fi);
+ #endif
+
// XXX X86_64: Here We had this:
/* This approach is much faster than moving the field
address inline into a register. */
- // XXX ARM: M_DSEG_LOAD(REG_ITMP3, disp);
M_ALD_DSEG(REG_ITMP1, disp);
switch (fieldtype) {
break;
}
emit_store_dst(jd, iptr, d);
- #endif
break;
+ }
+ #endif
case ICMD_PUTSTATIC: /* ..., value ==> ... */
#if defined(__I386__)
// Generate architecture specific instructions.
codegen_emit_instruction(jd, iptr);
+ break;
#else
+ {
+ fieldinfo* fi;
+ patchref_t* pr;
+
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_field* uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = dseg_add_unique_address(cd, 0);
- patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
+ pr = patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
}
else {
- fieldinfo* fi = iptr->sx.s23.s3.fmiref->p.field;
+ fi = iptr->sx.s23.s3.fmiref->p.field;
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
/* This approach is much faster than moving the field
address inline into a register. */
- // XXX ARM: M_DSEG_LOAD(REG_ITMP3, disp);
M_ALD_DSEG(REG_ITMP1, disp);
switch (fieldtype) {
M_DST(s1, REG_ITMP1, 0);
break;
}
+ #if defined(USES_PATCHABLE_MEMORY_BARRIER)
+ codegen_emit_patchable_barrier(iptr, cd, pr, fi);
#endif
break;
+ }
+ #endif
/* branch operations **********************************************/
REPLACEMENT_POINT_RETURN(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_FRESULT);
- // XXX ARM: Here this was M_CAST_F2I(s1, REG_RESULT);
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
emit_fmove(cd, s1, REG_FRESULT);
+#else
+ M_CAST_F2I(s1, REG_RESULT);
+#endif
goto nowperformreturn;
case ICMD_DRETURN: /* ..., retvalue ==> ... */
REPLACEMENT_POINT_RETURN(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_FRESULT);
- // XXX ARM: Here this was M_CAST_D2L(s1, REG_RESULT_PACKED);
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
emit_dmove(cd, s1, REG_FRESULT);
+#else
+ M_CAST_D2L(s1, REG_LRESULT);
+#endif
goto nowperformreturn;
nowperformreturn:
continue;
if (!md->params[i].inmemory) {
- assert(ARG_CNT > 0);
- s1 = emit_load(jd, iptr, var, d);
-
switch (var->type) {
case TYPE_ADR:
case TYPE_INT:
- assert(INT_ARG_CNT > 0);
+ s1 = emit_load(jd, iptr, var, d);
emit_imove(cd, s1, d);
break;
-#if 0 //XXX For ARM:
-if (!md->params[s3].inmemory) {
- s1 = emit_load(jd, iptr, var, REG_FTMP1);
- if (IS_2_WORD_TYPE(var->type))
- M_CAST_D2L(s1, d);
- else
- M_CAST_F2I(s1, d);
-}
-#endif //XXX End of ARM!
-
case TYPE_LNG:
+ s1 = emit_load(jd, iptr, var, d);
emit_lmove(cd, s1, d);
break;
case TYPE_FLT:
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+ s1 = emit_load(jd, iptr, var, d);
emit_fmove(cd, s1, d);
+#else
+ s1 = emit_load(jd, iptr, var, REG_FTMP1);
+ M_CAST_F2I(s1, d);
+#endif
break;
case TYPE_DBL:
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+ s1 = emit_load(jd, iptr, var, d);
emit_dmove(cd, s1, d);
+#else
+ s1 = emit_load(jd, iptr, var, REG_FTMP1);
+ M_CAST_D2L(s1, d);
+#endif
break;
}
}
emit_store_dst(jd, iptr, s1);
break;
-#if 0 //XXX For ARM!!!
-#if !defined(ENABLE_SOFTFLOAT)
- } else {
- s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- if (IS_2_WORD_TYPE(d))
- M_CAST_L2D(REG_RESULT_PACKED, s1);
- else
- M_CAST_I2F(REG_RESULT, s1);
- }
-#endif /* !defined(ENABLE_SOFTFLOAT) */
-#endif //XXX End of ARM
-
case TYPE_FLT:
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
emit_fmove(cd, REG_FRESULT, s1);
+#else
+ s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+ M_CAST_I2F(REG_RESULT, s1);
+#endif
emit_store_dst(jd, iptr, s1);
break;
case TYPE_DBL:
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
emit_dmove(cd, REG_FRESULT, s1);
+#else
+ s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+ M_CAST_L2D(REG_LRESULT, s1);
+#endif
emit_store_dst(jd, iptr, s1);
break;
#include "vm/breakpoint.hpp"
#include "vm/exceptions.hpp"
+#include "vm/hook.hpp"
#include "vm/initialize.hpp"
#include "vm/options.h"
#include "vm/os.hpp"
Appends a new patcher reference to the list of patching positions.
+ Returns a pointer to the newly created patchref_t.
+
*******************************************************************************/
- void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
+ patchref_t *patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
{
- codegendata *cd;
- codeinfo *code;
- s4 patchmpc;
-
- cd = jd->cd;
- code = jd->code;
- patchmpc = cd->mcodeptr - cd->mcodebase;
+ codegendata *cd = jd->cd;
+ codeinfo *code = jd->code;
#if defined(ALIGN_PATCHER_TRAP)
emit_patcher_alignment(cd);
- patchmpc = cd->mcodeptr - cd->mcodebase;
#endif
+ int32_t patchmpc = cd->mcodeptr - cd->mcodebase;
+
#if !defined(NDEBUG)
if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
os::abort("patcher_add_patch_ref: different patchers at same position.");
#endif
+ #if defined(USES_PATCHABLE_MEMORY_BARRIER)
+ PATCHER_NOPS;
+ #endif
+
// Set patcher information (mpc is resolved later).
patchref_t pr;
pr.mpc = patchmpc;
pr.datap = 0;
pr.disp = disp;
+ pr.disp_mb = 0;
pr.patcher = patcher;
pr.ref = ref;
pr.mcode = 0;
cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
#endif
+
+ return &code->patchers->back();
}
#define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
#endif /* !defined(NDEBUG) */
-java_handle_t *patcher_handler(u1 *pc)
+bool patcher_handler(u1 *pc)
{
codeinfo *code;
patchref_t *pr;
}
#endif
code->patchers->unlock();
- return NULL;
+ return true;
}
#if !defined(NDEBUG)
}
#endif
- // Check for return value and exit accordingly.
- if (result == false) {
- // Mangle the pending exception.
+ // Check return value and mangle the pending exception.
+ if (result == false)
resolve_handle_pending_exception(true);
- // Get the exception and return it.
- java_handle_t* e = exceptions_get_and_clear_exception();
-
- code->patchers->unlock();
-
- return e;
- }
-
- pr->done = true; /* XXX this is only preliminary to prevent double-patching */
+ // XXX This is only preliminary to prevent double-patching.
+ else
+ pr->done = true;
code->patchers->unlock();
- return NULL;
+ return result;
}
// Get stuff from the patcher reference.
Breakpoint* breakp = (Breakpoint*) pr->ref;
-#if defined(ENABLE_JVMTI)
- methodinfo* m = breakp->method;
- int32_t l = breakp->location;
-
- log_message_method("JVMTI: Reached breakpoint in method ", m);
- log_println("JVMTI: Reached breakpoint at location %d", l);
-#endif
+ // Hook point when a breakpoint was triggered.
+ Hook::breakpoint(breakp);
// In case the breakpoint wants to be kept active, we simply
// fail to "patch" at this point.
*******************************************************************************/
struct patchref_t {
- ptrint mpc; /* absolute position in code segment */
- ptrint datap; /* absolute position in data segment */
- s4 disp; /* displacement of ref in the data segment */
+ uintptr_t mpc; /* absolute position in code segment */
+ uintptr_t datap; /* absolute position in data segment */
+ int32_t disp; /* displacement of ref in the data segment */
+ int32_t disp_mb; /* auxiliary code displacement (for membar) */
functionptr patcher; /* patcher function to call */
void* ref; /* reference passed */
uint32_t mcode; /* machine code to be patched back in */
void patcher_list_show(codeinfo *code);
#endif
- void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
+ patchref_t *patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
void patcher_resolve(jitdata* jd);
// MD function.
bool patcher_is_valid_trap_instruction_at(void* pc);
-java_handle_t *patcher_handler(u1 *pc);
+bool patcher_handler(u1 *pc);
/* empty patcher (just patches back original mcode) ***************************/
#define STACKFRMAE_RA_BETWEEN_FRAMES 1
#define STACKFRAME_RA_TOP_OF_FRAME 0
+#define STACKFRAME_RA_LINKAGE_AREA 0
#define STACKFRAME_LEAFMETHODS_RA_REGISTER 0
#define STACKFRAME_SYNC_NEEDS_TWO_SLOTS 0
#define CAS_PROVIDES_FULL_BARRIER 1
+ #define USES_PATCHABLE_MEMORY_BARRIER 1
+
#endif /* _ARCH_H */
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/