src/cpu/x86/vm/templateInterpreter_x86_32.cpp
Print this page
rev 2161 : [mq]: initial-intrinsification-changes
rev 2162 : [mq]: code-review-comments-vladimir
@@ -774,10 +774,102 @@
}
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 below 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.
+
+ // rbx,: methodOop
+ // rcx: receiver (preserve for slow entry into asm interpreter)
+
+ // rsi: senderSP must preserved for slow path, set SP to it on fast path
+
+ 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;
+
+ // Check if local 0 != NULL
+ // If the receiver is null then it is OK to jump to the slow path.
+ __ movptr(rax, Address(rsp, wordSize));
+ __ testptr(rax, rax);
+ __ jcc(Assembler::zero, slow_path);
+
+ // rax: local 0 (must be preserved across the G1 barrier call)
+ //
+ // rbx: method (at this point it's scratch)
+ // rcx: receiver (at this point it's scratch)
+ // rdx: scratch
+ // rdi: scratch
+ //
+ // rsi: sender sp
+
+ // Preserve the sender sp in case the pre-barrier
+ // calls the runtime
+ __ push(rsi);
+
+ // Load the value of the referent field.
+ const Address field_address(rax, referent_offset);
+ __ movptr(rax, field_address);
+
+ // Generate the G1 pre-barrier code to log the value of
+ // the referent field in an SATB buffer.
+ __ get_thread(rcx);
+ __ g1_write_barrier_pre(noreg /* obj */,
+ rax /* pre_val */,
+ rcx /* thread */,
+ rbx /* tmp */,
+ true /* tosca_save */,
+ true /* expand_call */);
+
+ // _areturn
+ __ pop(rsi); // get sender sp
+ __ pop(rdi); // get return address
+ __ mov(rsp, rsi); // set sp to sender sp
+ __ jmp(rdi);
+
+ __ 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
// than the typical interpreter frame setup.
//
@@ -1442,10 +1534,12 @@
case Interpreter::java_lang_math_tan : // fall thru
case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*)this)->generate_math_entry(kind); break;
+ case Interpreter::java_lang_ref_reference_get
+ : entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break;
default : ShouldNotReachHere(); break;
}
if (entry_point) return entry_point;