src/cpu/x86/vm/templateInterpreter_x86_32.cpp

Print this page
rev 2237 : [mq]: initial-intrinsification-changes
rev 2238 : [mq]: code-review-comments-vladimir

*** 774,783 **** --- 774,875 ---- } 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,1451 **** --- 1534,1545 ---- 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;