75 // G5_method: invoke methodOop; becomes method type. |
75 // G5_method: invoke methodOop; becomes method type. |
76 // G3_method_handle: receiver method handle (must load from sp[MethodTypeForm.vmslots]) |
76 // G3_method_handle: receiver method handle (must load from sp[MethodTypeForm.vmslots]) |
77 // O0, O1: garbage temps, blown away |
77 // O0, O1: garbage temps, blown away |
78 Register O0_argslot = O0; |
78 Register O0_argslot = O0; |
79 Register O1_scratch = O1; |
79 Register O1_scratch = O1; |
|
80 Register O2_scratch = O2; |
|
81 Register O3_scratch = O3; |
|
82 Register O4_argbase = O4; |
|
83 Register O5_mtype = O5; |
80 |
84 |
81 // emit WrongMethodType path first, to enable back-branch from main path |
85 // emit WrongMethodType path first, to enable back-branch from main path |
82 Label wrong_method_type; |
86 Label wrong_method_type; |
83 __ bind(wrong_method_type); |
87 __ bind(wrong_method_type); |
|
88 Label invoke_generic_slow_path; |
|
89 assert(methodOopDesc::intrinsic_id_size_in_bytes() == sizeof(u1), "");; |
|
90 __ ldub(Address(G5_method, methodOopDesc::intrinsic_id_offset_in_bytes()), O1_scratch); |
|
91 __ cmp(O1_scratch, (int) vmIntrinsics::_invokeExact); |
|
92 __ brx(Assembler::notEqual, false, Assembler::pt, invoke_generic_slow_path); |
|
93 __ delayed()->nop(); |
|
94 __ mov(O5_mtype, G5_method_type); // required by throw_WrongMethodType |
|
95 // mov(G3_method_handle, G3_method_handle); // already in this register |
84 __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch); |
96 __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch); |
85 __ delayed()->nop(); |
97 __ delayed()->nop(); |
86 |
98 |
87 // here's where control starts out: |
99 // here's where control starts out: |
88 __ align(CodeEntryAlignment); |
100 __ align(CodeEntryAlignment); |
89 address entry_point = __ pc(); |
101 address entry_point = __ pc(); |
90 |
102 |
91 // fetch the MethodType from the method handle into G5_method_type |
103 // fetch the MethodType from the method handle |
92 { |
104 { |
93 Register tem = G5_method; |
105 Register tem = G5_method; |
94 assert(tem == G5_method_type, "yes, it's the same register"); |
|
95 for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) { |
106 for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) { |
96 __ ld_ptr(Address(tem, *pchase), G5_method_type); |
107 __ ld_ptr(Address(tem, *pchase), O5_mtype); |
|
108 tem = O5_mtype; // in case there is another indirection |
97 } |
109 } |
98 } |
110 } |
99 |
111 |
100 // given the MethodType, find out where the MH argument is buried |
112 // given the MethodType, find out where the MH argument is buried |
101 __ load_heap_oop(Address(G5_method_type, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O0_argslot); |
113 __ load_heap_oop(Address(O5_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O0_argslot); |
102 __ ldsw( Address(O0_argslot, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O0_argslot); |
114 __ ldsw( Address(O0_argslot, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O0_argslot); |
103 __ ld_ptr(__ argument_address(O0_argslot), G3_method_handle); |
115 __ add(Gargs, __ argument_offset(O0_argslot, 1), O4_argbase); |
104 |
116 // Note: argument_address uses its input as a scratch register! |
105 __ check_method_handle_type(G5_method_type, G3_method_handle, O1_scratch, wrong_method_type); |
117 __ ld_ptr(Address(O4_argbase, -Interpreter::stackElementSize), G3_method_handle); |
|
118 |
|
119 trace_method_handle(_masm, "invokeExact"); |
|
120 |
|
121 __ check_method_handle_type(O5_mtype, G3_method_handle, O1_scratch, wrong_method_type); |
106 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); |
122 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); |
|
123 |
|
124 // for invokeGeneric (only), apply argument and result conversions on the fly |
|
125 __ bind(invoke_generic_slow_path); |
|
126 #ifdef ASSERT |
|
127 { Label L; |
|
128 __ ldub(Address(G5_method, methodOopDesc::intrinsic_id_offset_in_bytes()), O1_scratch); |
|
129 __ cmp(O1_scratch, (int) vmIntrinsics::_invokeGeneric); |
|
130 __ brx(Assembler::equal, false, Assembler::pt, L); |
|
131 __ delayed()->nop(); |
|
132 __ stop("bad methodOop::intrinsic_id"); |
|
133 __ bind(L); |
|
134 } |
|
135 #endif //ASSERT |
|
136 |
|
137 // make room on the stack for another pointer: |
|
138 insert_arg_slots(_masm, 2 * stack_move_unit(), _INSERT_REF_MASK, |
|
139 O4_argbase, O1_scratch, O2_scratch, O3_scratch); |
|
140 // load up an adapter from the calling type (Java weaves this) |
|
141 Register O2_form = O2_scratch; |
|
142 Register O3_adapter = O3_scratch; |
|
143 __ load_heap_oop(Address(O5_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O2_form); |
|
144 // load_heap_oop(Address(O2_form, __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); |
|
145 // deal with old JDK versions: |
|
146 __ add( Address(O2_form, __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); |
|
147 __ cmp(O3_adapter, O2_form); |
|
148 Label sorry_no_invoke_generic; |
|
149 __ brx(Assembler::lessUnsigned, false, Assembler::pn, sorry_no_invoke_generic); |
|
150 __ delayed()->nop(); |
|
151 |
|
152 __ load_heap_oop(Address(O3_adapter, 0), O3_adapter); |
|
153 __ tst(O3_adapter); |
|
154 __ brx(Assembler::zero, false, Assembler::pn, sorry_no_invoke_generic); |
|
155 __ delayed()->nop(); |
|
156 __ st_ptr(O3_adapter, Address(O4_argbase, 1 * Interpreter::stackElementSize)); |
|
157 // As a trusted first argument, pass the type being called, so the adapter knows |
|
158 // the actual types of the arguments and return values. |
|
159 // (Generic invokers are shared among form-families of method-type.) |
|
160 __ st_ptr(O5_mtype, Address(O4_argbase, 0 * Interpreter::stackElementSize)); |
|
161 // FIXME: assert that O3_adapter is of the right method-type. |
|
162 __ mov(O3_adapter, G3_method_handle); |
|
163 trace_method_handle(_masm, "invokeGeneric"); |
|
164 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); |
|
165 |
|
166 __ bind(sorry_no_invoke_generic); // no invokeGeneric implementation available! |
|
167 __ mov(O5_mtype, G5_method_type); // required by throw_WrongMethodType |
|
168 // mov(G3_method_handle, G3_method_handle); // already in this register |
|
169 __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch); |
|
170 __ delayed()->nop(); |
107 |
171 |
108 return entry_point; |
172 return entry_point; |
109 } |
173 } |
110 |
174 |
111 |
175 |