// Generate method entries address CppInterpreterGenerator::generate_method_entry( AbstractInterpreter::MethodKind kind) { // determine code generation flags bool native = false; bool synchronized = false; address entry_point = NULL; switch (kind) { case Interpreter::zerolocals : break; case Interpreter::zerolocals_synchronized: synchronized = true; break; case Interpreter::native : native = true; break; case Interpreter::native_synchronized : native = true; synchronized = true; break; case Interpreter::empty : entry_point = generate_empty_entry(); break; case Interpreter::accessor : entry_point = generate_accessor_entry(); break; case Interpreter::abstract : entry_point = generate_abstract_entry(); break; case Interpreter::java_lang_math_sin : // fall thru case Interpreter::java_lang_math_cos : // fall thru 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 : // fall thru case Interpreter::java_lang_math_pow : // fall thru case Interpreter::java_lang_math_exp : // fall thru case Interpreter::java_lang_math_fmaD : // fall thru case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break; case Interpreter::java_lang_ref_reference_get : entry_point = generate_Reference_get_entry(); break; default: fatal("unexpected method kind: %d", kind); break; } if (entry_point) { return entry_point; } // We expect the normal and native entry points to be generated first so we can reuse them. if (native) { entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::native_synchronized : Interpreter::native); if (entry_point == NULL) { entry_point = generate_native_entry(synchronized); } } else { entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::zerolocals_synchronized : Interpreter::zerolocals); if (entry_point == NULL) { entry_point = generate_normal_entry(synchronized); } } return entry_point; }
// Generate method entries address InterpreterGenerator::generate_method_entry( AbstractInterpreter::MethodKind kind) { // determine code generation flags bool synchronized = false; address entry_point = NULL; switch (kind) { case Interpreter::zerolocals : break; case Interpreter::zerolocals_synchronized: synchronized = true; break; case Interpreter::native : entry_point = generate_native_entry(false); break; case Interpreter::native_synchronized : entry_point = generate_native_entry(true); break; case Interpreter::empty : entry_point = generate_empty_entry(); break; case Interpreter::accessor : entry_point = generate_accessor_entry(); break; case Interpreter::abstract : entry_point = generate_abstract_entry(); break; case Interpreter::java_lang_math_sin : // fall thru case Interpreter::java_lang_math_cos : // fall thru 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 : // fall thru case Interpreter::java_lang_math_pow : // fall thru case Interpreter::java_lang_math_exp : entry_point = generate_math_entry(kind); break; case Interpreter::java_lang_ref_reference_get : entry_point = generate_Reference_get_entry(); break; #ifndef CC_INTERP case Interpreter::java_util_zip_CRC32_update : entry_point = generate_CRC32_update_entry(); break; case Interpreter::java_util_zip_CRC32_updateBytes : // fall thru case Interpreter::java_util_zip_CRC32_updateByteBuffer : entry_point = generate_CRC32_updateBytes_entry(kind); break; #endif // CC_INTERP default: fatal(err_msg("unexpected method kind: %d", kind)); break; } if (entry_point) { return entry_point; } return generate_normal_entry(synchronized); }
address InterpreterGenerator::generate_Reference_get_entry(void) { #if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field // * passes that value to the pre-barrier. // // In the case of G1 this will record the value of the // referent in an SATB buffer if marking is active. // This will cause concurrent marking to mark the referent // field as live. Unimplemented(); } #endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor return generate_accessor_entry(); }
// Interpreter intrinsic for WeakReference.get(). // 1. Don't push a full blown frame and go on dispatching, but fetch the value // into R8 and return quickly // 2. If G1 is active we *must* execute this intrinsic for corrrectness: // It contains a GC barrier which puts the reference into the satb buffer // to indicate that someone holds a strong reference to the object the // weak ref points to! address InterpreterGenerator::generate_Reference_get_entry(void) { // 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; // Debugging not possible, so can't use __ skip_if_jvmti_mode(slow_path, GR31_SCRATCH); // 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. // If the receiver is null then it is OK to jump to the slow path. __ ld(R3_RET, Interpreter::stackElementSize, CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp)); // get receiver // Check if receiver == NULL and go the slow path. __ cmpdi(CCR0, R3_RET, 0); __ beq(CCR0, slow_path); // Load the value of the referent field. __ load_heap_oop(R3_RET, referent_offset, R3_RET); // 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. // Restore caller sp for c2i case. #ifdef ASSERT __ ld(R9_ARG7, 0, R1_SP); __ ld(R10_ARG8, 0, R21_sender_SP); __ cmpd(CCR0, R9_ARG7, R10_ARG8); __ asm_assert_eq("backlink", 0x544); #endif // ASSERT __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. __ g1_write_barrier_pre(noreg, // obj noreg, // offset R3_RET, // pre_val R11_scratch1, // tmp R12_scratch2, // tmp true); // needs_frame __ blr(); // Generate regular method entry. __ bind(slow_path); __ branch_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), R11_scratch1); __ flush(); return entry; } else { return generate_accessor_entry(); } }
// Generate method entries address InterpreterGenerator::generate_method_entry( AbstractInterpreter::MethodKind kind) { // determine code generation flags bool native = false; bool synchronized = false; address entry_point = NULL; switch (kind) { case Interpreter::zerolocals : break; case Interpreter::zerolocals_synchronized: synchronized = true; break; case Interpreter::native : native = true; break; case Interpreter::native_synchronized : native = true; synchronized = true; break; case Interpreter::empty : entry_point = generate_empty_entry(); break; case Interpreter::accessor : entry_point = generate_accessor_entry(); break; case Interpreter::abstract : entry_point = generate_abstract_entry(); break; case Interpreter::java_lang_math_sin : // fall thru case Interpreter::java_lang_math_cos : // fall thru 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 : // fall thru case Interpreter::java_lang_math_pow : // fall thru case Interpreter::java_lang_math_exp : entry_point = generate_math_entry(kind); break; case Interpreter::java_lang_ref_reference_get : entry_point = generate_Reference_get_entry(); break; #ifndef CC_INTERP case Interpreter::java_util_zip_CRC32_update : native = true; entry_point = generate_CRC32_update_entry(); break; case Interpreter::java_util_zip_CRC32_updateBytes : // fall thru case Interpreter::java_util_zip_CRC32_updateByteBuffer : native = true; entry_point = generate_CRC32_updateBytes_entry(kind); break; case Interpreter::java_util_zip_CRC32C_updateBytes : // fall thru case Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer : entry_point = generate_CRC32C_updateBytes_entry(kind); break; #if defined(TARGET_ARCH_x86) && !defined(_LP64) // On x86_32 platforms, a special entry is generated for the following four methods. // On other platforms the normal entry is used to enter these methods. case Interpreter::java_lang_Float_intBitsToFloat : native = true; entry_point = generate_Float_intBitsToFloat_entry(); break; case Interpreter::java_lang_Float_floatToRawIntBits : native = true; entry_point = generate_Float_floatToRawIntBits_entry(); break; case Interpreter::java_lang_Double_longBitsToDouble : native = true; entry_point = generate_Double_longBitsToDouble_entry(); break; case Interpreter::java_lang_Double_doubleToRawLongBits : native = true; entry_point = generate_Double_doubleToRawLongBits_entry(); break; #else case Interpreter::java_lang_Float_intBitsToFloat: case Interpreter::java_lang_Float_floatToRawIntBits: case Interpreter::java_lang_Double_longBitsToDouble: case Interpreter::java_lang_Double_doubleToRawLongBits: native = true; break; #endif // defined(TARGET_ARCH_x86) && !defined(_LP64) #endif // CC_INTERP default: fatal("unexpected method kind: %d", kind); break; } if (entry_point) { return entry_point; } // We expect the normal and native entry points to be generated first so we can reuse them. if (native) { entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::native_synchronized : Interpreter::native); if (entry_point == NULL) { entry_point = generate_native_entry(synchronized); } } else { entry_point = Interpreter::entry_for_kind(synchronized ? Interpreter::zerolocals_synchronized : Interpreter::zerolocals); if (entry_point == NULL) { entry_point = generate_normal_entry(synchronized); } } return entry_point; }