Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp
32285 views
/*1* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.2* Copyright 2012, 2014 SAP AG. All rights reserved.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#include "precompiled.hpp"26#include "asm/macroAssembler.inline.hpp"27#include "interpreter/interpreter.hpp"28#include "memory/allocation.inline.hpp"29#include "prims/methodHandles.hpp"3031#define __ _masm->3233#ifdef CC_INTERP34#define EXCEPTION_ENTRY StubRoutines::throw_NullPointerException_at_call_entry()35#else36#define EXCEPTION_ENTRY Interpreter::throw_NullPointerException_entry()37#endif3839#ifdef PRODUCT40#define BLOCK_COMMENT(str) // nothing41#else42#define BLOCK_COMMENT(str) __ block_comment(str)43#endif4445#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")4647// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant.48inline static RegisterOrConstant constant(int value) {49return RegisterOrConstant(value);50}5152void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg, Register temp_reg, Register temp2_reg) {53if (VerifyMethodHandles)54verify_klass(_masm, klass_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_Class), temp_reg, temp2_reg,55"MH argument is a Class");56__ ld(klass_reg, java_lang_Class::klass_offset_in_bytes(), klass_reg);57}5859#ifdef ASSERT60static int check_nonzero(const char* xname, int x) {61assert(x != 0, err_msg("%s should be nonzero", xname));62return x;63}64#define NONZERO(x) check_nonzero(#x, x)65#else //ASSERT66#define NONZERO(x) (x)67#endif //ASSERT6869#ifdef ASSERT70void MethodHandles::verify_klass(MacroAssembler* _masm,71Register obj_reg, SystemDictionary::WKID klass_id,72Register temp_reg, Register temp2_reg,73const char* error_message) {74Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);75KlassHandle klass = SystemDictionary::well_known_klass(klass_id);76Label L_ok, L_bad;77BLOCK_COMMENT("verify_klass {");78__ verify_oop(obj_reg);79__ cmpdi(CCR0, obj_reg, 0);80__ beq(CCR0, L_bad);81__ load_klass(temp_reg, obj_reg);82__ load_const_optimized(temp2_reg, (address) klass_addr);83__ ld(temp2_reg, 0, temp2_reg);84__ cmpd(CCR0, temp_reg, temp2_reg);85__ beq(CCR0, L_ok);86__ ld(temp_reg, klass->super_check_offset(), temp_reg);87__ cmpd(CCR0, temp_reg, temp2_reg);88__ beq(CCR0, L_ok);89__ BIND(L_bad);90__ stop(error_message);91__ BIND(L_ok);92BLOCK_COMMENT("} verify_klass");93}9495void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Register member_reg, Register temp) {96Label L;97BLOCK_COMMENT("verify_ref_kind {");98__ load_sized_value(temp, NONZERO(java_lang_invoke_MemberName::flags_offset_in_bytes()), member_reg,99sizeof(u4), /*is_signed*/ false);100// assert(sizeof(u4) == sizeof(java.lang.invoke.MemberName.flags), "");101__ srwi( temp, temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT);102__ andi(temp, temp, java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK);103__ cmpwi(CCR1, temp, ref_kind);104__ beq(CCR1, L);105{ char* buf = NEW_C_HEAP_ARRAY(char, 100, mtInternal);106jio_snprintf(buf, 100, "verify_ref_kind expected %x", ref_kind);107if (ref_kind == JVM_REF_invokeVirtual ||108ref_kind == JVM_REF_invokeSpecial)109// could do this for all ref_kinds, but would explode assembly code size110trace_method_handle(_masm, buf);111__ stop(buf);112}113BLOCK_COMMENT("} verify_ref_kind");114__ BIND(L);115}116117#endif // ASSERT118119void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp,120bool for_compiler_entry) {121Label L_no_such_method;122assert(method == R19_method, "interpreter calling convention");123assert_different_registers(method, target, temp);124125if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) {126Label run_compiled_code;127// JVMTI events, such as single-stepping, are implemented partly by avoiding running128// compiled code in threads for which the event is enabled. Check here for129// interp_only_mode if these events CAN be enabled.130__ verify_thread();131__ lwz(temp, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread);132__ cmplwi(CCR0, temp, 0);133__ beq(CCR0, run_compiled_code);134// Null method test is replicated below in compiled case,135// it might be able to address across the verify_thread()136__ cmplwi(CCR0, R19_method, 0);137__ beq(CCR0, L_no_such_method);138__ ld(target, in_bytes(Method::interpreter_entry_offset()), R19_method);139__ mtctr(target);140__ bctr();141__ BIND(run_compiled_code);142}143144// Compiled case, either static or fall-through from runtime conditional145__ cmplwi(CCR0, R19_method, 0);146__ beq(CCR0, L_no_such_method);147148const ByteSize entry_offset = for_compiler_entry ? Method::from_compiled_offset() :149Method::from_interpreted_offset();150__ ld(target, in_bytes(entry_offset), R19_method);151__ mtctr(target);152__ bctr();153154__ bind(L_no_such_method);155assert(StubRoutines::throw_AbstractMethodError_entry() != NULL, "not yet generated!");156__ load_const_optimized(target, StubRoutines::throw_AbstractMethodError_entry());157__ mtctr(target);158__ bctr();159}160161162void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm,163Register recv, Register method_temp,164Register temp2, Register temp3,165bool for_compiler_entry) {166BLOCK_COMMENT("jump_to_lambda_form {");167// This is the initial entry point of a lazy method handle.168// After type checking, it picks up the invoker from the LambdaForm.169assert_different_registers(recv, method_temp, temp2); // temp3 is only passed on170assert(method_temp == R19_method, "required register for loading method");171172// Load the invoker, as MH -> MH.form -> LF.vmentry173__ verify_oop(recv);174__ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv);175__ verify_oop(method_temp);176__ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp);177__ verify_oop(method_temp);178// the following assumes that a Method* is normally compressed in the vmtarget field:179__ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp);180181if (VerifyMethodHandles && !for_compiler_entry) {182// make sure recv is already on stack183__ ld(temp2, in_bytes(Method::const_offset()), method_temp);184__ load_sized_value(temp2, in_bytes(ConstMethod::size_of_parameters_offset()), temp2,185sizeof(u2), /*is_signed*/ false);186// assert(sizeof(u2) == sizeof(ConstMethod::_size_of_parameters), "");187Label L;188__ ld(temp2, __ argument_offset(temp2, temp2, 0), CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp));189__ cmpd(CCR1, temp2, recv);190__ beq(CCR1, L);191__ stop("receiver not on stack");192__ BIND(L);193}194195jump_from_method_handle(_masm, method_temp, temp2, temp3, for_compiler_entry);196BLOCK_COMMENT("} jump_to_lambda_form");197}198199200201// Code generation202address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm,203vmIntrinsics::ID iid) {204const bool not_for_compiler_entry = false; // this is the interpreter entry205assert(is_signature_polymorphic(iid), "expected invoke iid");206if (iid == vmIntrinsics::_invokeGeneric ||207iid == vmIntrinsics::_compiledLambdaForm) {208// Perhaps surprisingly, the symbolic references visible to Java are not directly used.209// They are linked to Java-generated adapters via MethodHandleNatives.linkMethod.210// They all allow an appendix argument.211__ stop("Should not reach here"); // empty stubs make SG sick212return NULL;213}214215Register argbase = CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp); // parameter (preserved)216Register argslot = R3;217Register temp1 = R6;218Register param_size = R7;219220// here's where control starts out:221__ align(CodeEntryAlignment);222address entry_point = __ pc();223224if (VerifyMethodHandles) {225Label L;226BLOCK_COMMENT("verify_intrinsic_id {");227__ load_sized_value(temp1, Method::intrinsic_id_offset_in_bytes(), R19_method,228sizeof(u1), /*is_signed*/ false);229// assert(sizeof(u1) == sizeof(Method::_intrinsic_id), "");230__ cmpwi(CCR1, temp1, (int) iid);231__ beq(CCR1, L);232if (iid == vmIntrinsics::_linkToVirtual ||233iid == vmIntrinsics::_linkToSpecial) {234// could do this for all kinds, but would explode assembly code size235trace_method_handle(_masm, "bad Method*:intrinsic_id");236}237__ stop("bad Method*::intrinsic_id");238__ BIND(L);239BLOCK_COMMENT("} verify_intrinsic_id");240}241242// First task: Find out how big the argument list is.243int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid);244assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic");245if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) {246__ ld(param_size, in_bytes(Method::const_offset()), R19_method);247__ load_sized_value(param_size, in_bytes(ConstMethod::size_of_parameters_offset()), param_size,248sizeof(u2), /*is_signed*/ false);249// assert(sizeof(u2) == sizeof(ConstMethod::_size_of_parameters), "");250} else {251DEBUG_ONLY(param_size = noreg);252}253254Register tmp_mh = noreg;255if (!is_signature_polymorphic_static(iid)) {256__ ld(tmp_mh = temp1, __ argument_offset(param_size, param_size, 0), argbase);257DEBUG_ONLY(param_size = noreg);258}259260if (TraceMethodHandles) {261if (tmp_mh != noreg)262__ mr(R23_method_handle, tmp_mh); // make stub happy263trace_method_handle_interpreter_entry(_masm, iid);264}265266if (iid == vmIntrinsics::_invokeBasic) {267generate_method_handle_dispatch(_masm, iid, tmp_mh, noreg, not_for_compiler_entry);268269} else {270// Adjust argument list by popping the trailing MemberName argument.271Register tmp_recv = noreg;272if (MethodHandles::ref_kind_has_receiver(ref_kind)) {273// Load the receiver (not the MH; the actual MemberName's receiver) up from the interpreter stack.274__ ld(tmp_recv = temp1, __ argument_offset(param_size, param_size, 0), argbase);275DEBUG_ONLY(param_size = noreg);276}277Register R19_member = R19_method; // MemberName ptr; incoming method ptr is dead now278__ ld(R19_member, RegisterOrConstant((intptr_t)8), argbase);279__ add(argbase, Interpreter::stackElementSize, argbase);280generate_method_handle_dispatch(_masm, iid, tmp_recv, R19_member, not_for_compiler_entry);281}282283return entry_point;284}285286void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,287vmIntrinsics::ID iid,288Register receiver_reg,289Register member_reg,290bool for_compiler_entry) {291assert(is_signature_polymorphic(iid), "expected invoke iid");292Register temp1 = (for_compiler_entry ? R25_tmp5 : R7);293Register temp2 = (for_compiler_entry ? R22_tmp2 : R8);294Register temp3 = (for_compiler_entry ? R23_tmp3 : R9);295Register temp4 = (for_compiler_entry ? R24_tmp4 : R10);296if (receiver_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, receiver_reg);297if (member_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, member_reg);298299if (iid == vmIntrinsics::_invokeBasic) {300// indirect through MH.form.vmentry.vmtarget301jump_to_lambda_form(_masm, receiver_reg, R19_method, temp1, temp2, for_compiler_entry);302} else {303// The method is a member invoker used by direct method handles.304if (VerifyMethodHandles) {305// make sure the trailing argument really is a MemberName (caller responsibility)306verify_klass(_masm, member_reg, SystemDictionary::WK_KLASS_ENUM_NAME(MemberName_klass),307temp1, temp2,308"MemberName required for invokeVirtual etc.");309}310311Register temp1_recv_klass = temp1;312if (iid != vmIntrinsics::_linkToStatic) {313__ verify_oop(receiver_reg);314if (iid == vmIntrinsics::_linkToSpecial) {315// Don't actually load the klass; just null-check the receiver.316__ null_check_throw(receiver_reg, -1, temp1, EXCEPTION_ENTRY);317} else {318// load receiver klass itself319__ null_check_throw(receiver_reg, oopDesc::klass_offset_in_bytes(), temp1, EXCEPTION_ENTRY);320__ load_klass(temp1_recv_klass, receiver_reg);321__ verify_klass_ptr(temp1_recv_klass);322}323BLOCK_COMMENT("check_receiver {");324// The receiver for the MemberName must be in receiver_reg.325// Check the receiver against the MemberName.clazz326if (VerifyMethodHandles && iid == vmIntrinsics::_linkToSpecial) {327// Did not load it above...328__ load_klass(temp1_recv_klass, receiver_reg);329__ verify_klass_ptr(temp1_recv_klass);330}331if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) {332Label L_ok;333Register temp2_defc = temp2;334__ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);335load_klass_from_Class(_masm, temp2_defc, temp3, temp4);336__ verify_klass_ptr(temp2_defc);337__ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);338// If we get here, the type check failed!339__ stop("receiver class disagrees with MemberName.clazz");340__ BIND(L_ok);341}342BLOCK_COMMENT("} check_receiver");343}344if (iid == vmIntrinsics::_linkToSpecial ||345iid == vmIntrinsics::_linkToStatic) {346DEBUG_ONLY(temp1_recv_klass = noreg); // these guys didn't load the recv_klass347}348349// Live registers at this point:350// member_reg - MemberName that was the trailing argument351// temp1_recv_klass - klass of stacked receiver, if needed352// O5_savedSP - interpreter linkage (if interpreted)353// O0..O5 - compiler arguments (if compiled)354355Label L_incompatible_class_change_error;356switch (iid) {357case vmIntrinsics::_linkToSpecial:358if (VerifyMethodHandles) {359verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2);360}361__ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg);362break;363364case vmIntrinsics::_linkToStatic:365if (VerifyMethodHandles) {366verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2);367}368__ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg);369break;370371case vmIntrinsics::_linkToVirtual:372{373// same as TemplateTable::invokevirtual,374// minus the CP setup and profiling:375376if (VerifyMethodHandles) {377verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp2);378}379380// pick out the vtable index from the MemberName, and then we can discard it:381Register temp2_index = temp2;382__ ld(temp2_index, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()), member_reg);383384if (VerifyMethodHandles) {385Label L_index_ok;386__ cmpdi(CCR1, temp2_index, 0);387__ bge(CCR1, L_index_ok);388__ stop("no virtual index");389__ BIND(L_index_ok);390}391392// Note: The verifier invariants allow us to ignore MemberName.clazz and vmtarget393// at this point. And VerifyMethodHandles has already checked clazz, if needed.394395// get target Method* & entry point396__ lookup_virtual_method(temp1_recv_klass, temp2_index, R19_method);397break;398}399400case vmIntrinsics::_linkToInterface:401{402// same as TemplateTable::invokeinterface403// (minus the CP setup and profiling, with different argument motion)404if (VerifyMethodHandles) {405verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp2);406}407408Register temp2_intf = temp2;409__ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);410load_klass_from_Class(_masm, temp2_intf, temp3, temp4);411__ verify_klass_ptr(temp2_intf);412413Register vtable_index = R19_method;414__ ld(vtable_index, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes()), member_reg);415if (VerifyMethodHandles) {416Label L_index_ok;417__ cmpdi(CCR1, vtable_index, 0);418__ bge(CCR1, L_index_ok);419__ stop("invalid vtable index for MH.invokeInterface");420__ BIND(L_index_ok);421}422423// given intf, index, and recv klass, dispatch to the implementation method424__ lookup_interface_method(temp1_recv_klass, temp2_intf,425// note: next two args must be the same:426vtable_index, R19_method,427temp3, temp4,428L_incompatible_class_change_error);429break;430}431432default:433fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)));434break;435}436437// Live at this point:438// R19_method439// O5_savedSP (if interpreted)440441// After figuring out which concrete method to call, jump into it.442// Note that this works in the interpreter with no data motion.443// But the compiled version will require that rcx_recv be shifted out.444__ verify_method_ptr(R19_method);445jump_from_method_handle(_masm, R19_method, temp1, temp2, for_compiler_entry);446447if (iid == vmIntrinsics::_linkToInterface) {448__ BIND(L_incompatible_class_change_error);449__ load_const_optimized(temp1, StubRoutines::throw_IncompatibleClassChangeError_entry());450__ mtctr(temp1);451__ bctr();452}453}454}455456#ifndef PRODUCT457void trace_method_handle_stub(const char* adaptername,458oopDesc* mh,459intptr_t* entry_sp,460intptr_t* saved_regs) {461462bool has_mh = (strstr(adaptername, "/static") == NULL &&463strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH464const char* mh_reg_name = has_mh ? "R23_method_handle" : "G23";465tty->print_cr("MH %s %s=" INTPTR_FORMAT " sp=" INTPTR_FORMAT,466adaptername, mh_reg_name, (intptr_t) mh, (intptr_t) entry_sp);467468if (Verbose) {469tty->print_cr("Registers:");470const int abi_offset = frame::abi_reg_args_size / 8;471for (int i = R3->encoding(); i <= R12->encoding(); i++) {472Register r = as_Register(i);473int count = i - R3->encoding();474// The registers are stored in reverse order on the stack (by save_volatile_gprs(R1_SP, abi_reg_args_size)).475tty->print("%3s=" PTR_FORMAT, r->name(), saved_regs[abi_offset + count]);476if ((count + 1) % 4 == 0) {477tty->cr();478} else {479tty->print(", ");480}481}482tty->cr();483484{485// dumping last frame with frame::describe486487JavaThread* p = JavaThread::active();488489ResourceMark rm;490PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here491FrameValues values;492493// Note: We want to allow trace_method_handle from any call site.494// While trace_method_handle creates a frame, it may be entered495// without a PC on the stack top (e.g. not just after a call).496// Walking that frame could lead to failures due to that invalid PC.497// => carefully detect that frame when doing the stack walking498499// Current C frame500frame cur_frame = os::current_frame();501502// Robust search of trace_calling_frame (independant of inlining).503// Assumes saved_regs comes from a pusha in the trace_calling_frame.504assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?");505frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame);506while (trace_calling_frame.fp() < saved_regs) {507trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame);508}509510// Safely create a frame and call frame::describe.511intptr_t *dump_sp = trace_calling_frame.sender_sp();512513frame dump_frame = frame(dump_sp);514dump_frame.describe(values, 1);515516values.describe(-1, saved_regs, "raw top of stack");517518tty->print_cr("Stack layout:");519values.print(p);520}521522if (has_mh && mh->is_oop()) {523mh->print();524if (java_lang_invoke_MethodHandle::is_instance(mh)) {525if (java_lang_invoke_MethodHandle::form_offset_in_bytes() != 0)526java_lang_invoke_MethodHandle::form(mh)->print();527}528}529}530}531532void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {533if (!TraceMethodHandles) return;534535BLOCK_COMMENT("trace_method_handle {");536537int nbytes_save = 10 * 8; // 10 volatile gprs538__ save_LR_CR(R0);539__ mr(R0, R1_SP); // saved_sp540assert(Assembler::is_simm(-nbytes_save, 16), "Overwriting R0");541// Push_frame_reg_args only uses R0 if nbytes_save is wider than 16 bit.542__ push_frame_reg_args(nbytes_save, R0);543__ save_volatile_gprs(R1_SP, frame::abi_reg_args_size); // Except R0.544545__ load_const(R3_ARG1, (address)adaptername);546__ mr(R4_ARG2, R23_method_handle);547__ mr(R5_ARG3, R0); // saved_sp548__ mr(R6_ARG4, R1_SP);549__ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub));550551__ restore_volatile_gprs(R1_SP, 112); // Except R0.552__ pop_frame();553__ restore_LR_CR(R0);554555BLOCK_COMMENT("} trace_method_handle");556}557#endif // PRODUCT558559560