--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Apr 05 19:14:03 2011 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Apr 07 09:53:20 2011 -0700
@@ -763,6 +763,87 @@
return NULL;
}
+// Method entry for java.lang.ref.Reference.get.
+address InterpreterGenerator::generate_Reference_get_entry(void) {
+#ifndef SERIALGC
+ // Code: _aload_0, _getfield, _areturn
+ // parameter size = 1
+ //
+ // The code that gets generated by this routine is split into 2 parts:
+ // 1. The "intrinsified" code for G1 (or any SATB based GC),
+ // 2. The slow path - which is an expansion of the regular method entry.
+ //
+ // Notes:-
+ // * In the G1 code we do not check whether we need to block for
+ // a safepoint. If G1 is enabled then we must execute the specialized
+ // code for Reference.get (except when the Reference object is null)
+ // so that we can log the value in the referent field with an SATB
+ // update buffer.
+ // If the code for the getfield template is modified so that the
+ // G1 pre-barrier code is executed when the current method is
+ // Reference.get() then going through the normal method entry
+ // will be fine.
+ // * The G1 code can, however, check the receiver object (the instance
+ // of java.lang.Reference) and jump to the slow path if null. If the
+ // Reference object is null then we obviously cannot fetch the referent
+ // and so we don't need to call the G1 pre-barrier. Thus we can use the
+ // regular method entry code to generate the NPE.
+ //
+ // This code is based on generate_accessor_enty.
+
+ address entry = __ pc();
+
+ const int referent_offset = java_lang_ref_Reference::referent_offset;
+ guarantee(referent_offset > 0, "referent offset not initialized");
+
+ if (UseG1GC) {
+ Label slow_path;
+
+ // In the G1 code we don't check if we need to reach a safepoint. We
+ // continue and the thread will safepoint at the next bytecode dispatch.
+
+ // Check if local 0 != NULL
+ // If the receiver is null then it is OK to jump to the slow path.
+ __ ld_ptr(Gargs, G0, Otos_i ); // get local 0
+ __ tst(Otos_i); // check if local 0 == NULL and go the slow path
+ __ brx(Assembler::zero, false, Assembler::pn, slow_path);
+ __ delayed()->nop();
+
+
+ // Load the value of the referent field.
+ if (Assembler::is_simm13(referent_offset)) {
+ __ load_heap_oop(Otos_i, referent_offset, Otos_i);
+ } else {
+ __ set(referent_offset, G3_scratch);
+ __ load_heap_oop(Otos_i, G3_scratch, Otos_i);
+ }
+
+ // Generate the G1 pre-barrier code to log the value of
+ // the referent field in an SATB buffer. Note with
+ // these parameters the pre-barrier does not generate
+ // the load of the previous value
+
+ __ g1_write_barrier_pre(noreg /* obj */, noreg /* index */, 0 /* offset */,
+ Otos_i /* pre_val */,
+ G3_scratch /* tmp */,
+ true /* preserve_o_regs */);
+
+ // _areturn
+ __ retl(); // return from leaf routine
+ __ delayed()->mov(O5_savedSP, SP);
+
+ // Generate regular method entry
+ __ bind(slow_path);
+ (void) generate_normal_entry(false);
+ return entry;
+ }
+#endif // SERIALGC
+
+ // If G1 is not enabled then attempt to go through the accessor entry point
+ // Reference.get is an accessor
+ return generate_accessor_entry();
+}
+
//
// Interpreter stub for calling a native method. (asm interpreter)
// This sets up a somewhat different looking stack for calling the native method