Mercurial > hg > truffle
comparison src/cpu/sparc/vm/methodHandles_sparc.cpp @ 1926:a1e319b5b13a
Merge
author | trims |
---|---|
date | Thu, 11 Nov 2010 23:29:32 -0800 |
parents | e62345fd6a46 |
children | f95d63e2154a |
comparison
equal
deleted
inserted
replaced
1895:d4681dc64964 | 1926:a1e319b5b13a |
---|---|
68 } | 68 } |
69 | 69 |
70 | 70 |
71 // Code generation | 71 // Code generation |
72 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) { | 72 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) { |
73 // I5_savedSP: sender SP (must preserve) | 73 // I5_savedSP/O5_savedSP: sender SP (must preserve) |
74 // G4 (Gargs): incoming argument list (must preserve) | 74 // G4 (Gargs): incoming argument list (must preserve) |
75 // G5_method: invoke methodOop; becomes method type. | 75 // G5_method: invoke methodOop |
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, O2, O3, O4: garbage temps, blown away |
78 Register O0_argslot = O0; | 78 Register O0_mtype = O0; |
79 Register O1_scratch = O1; | 79 Register O1_scratch = O1; |
80 Register O2_scratch = O2; | |
81 Register O3_scratch = O3; | |
82 Register O4_argslot = O4; | |
83 Register O4_argbase = O4; | |
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(O0_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), O0_mtype); |
108 tem = O0_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(O0_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O4_argslot); |
102 __ ldsw( Address(O0_argslot, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O0_argslot); | 114 __ ldsw( Address(O4_argslot, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O4_argslot); |
103 __ ld_ptr(__ argument_address(O0_argslot), G3_method_handle); | 115 __ add(Gargs, __ argument_offset(O4_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(O0_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, O4_argbase, O1_scratch, O2_scratch, O3_scratch); | |
139 // load up an adapter from the calling type (Java weaves this) | |
140 Register O2_form = O2_scratch; | |
141 Register O3_adapter = O3_scratch; | |
142 __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O2_form); | |
143 // load_heap_oop(Address(O2_form, __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); | |
144 // deal with old JDK versions: | |
145 __ add( Address(O2_form, __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); | |
146 __ cmp(O3_adapter, O2_form); | |
147 Label sorry_no_invoke_generic; | |
148 __ brx(Assembler::lessUnsigned, false, Assembler::pn, sorry_no_invoke_generic); | |
149 __ delayed()->nop(); | |
150 | |
151 __ load_heap_oop(Address(O3_adapter, 0), O3_adapter); | |
152 __ tst(O3_adapter); | |
153 __ brx(Assembler::zero, false, Assembler::pn, sorry_no_invoke_generic); | |
154 __ delayed()->nop(); | |
155 __ st_ptr(O3_adapter, Address(O4_argbase, 1 * Interpreter::stackElementSize)); | |
156 // As a trusted first argument, pass the type being called, so the adapter knows | |
157 // the actual types of the arguments and return values. | |
158 // (Generic invokers are shared among form-families of method-type.) | |
159 __ st_ptr(O0_mtype, Address(O4_argbase, 0 * Interpreter::stackElementSize)); | |
160 // FIXME: assert that O3_adapter is of the right method-type. | |
161 __ mov(O3_adapter, G3_method_handle); | |
162 trace_method_handle(_masm, "invokeGeneric"); | |
163 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); | |
164 | |
165 __ bind(sorry_no_invoke_generic); // no invokeGeneric implementation available! | |
166 __ mov(O0_mtype, G5_method_type); // required by throw_WrongMethodType | |
167 // mov(G3_method_handle, G3_method_handle); // already in this register | |
168 __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch); | |
169 __ delayed()->nop(); | |
107 | 170 |
108 return entry_point; | 171 return entry_point; |
109 } | 172 } |
110 | 173 |
111 | 174 |
628 Address value; | 691 Address value; |
629 bool value_left_justified = false; | 692 bool value_left_justified = false; |
630 | 693 |
631 switch (ek) { | 694 switch (ek) { |
632 case _adapter_opt_i2i: | 695 case _adapter_opt_i2i: |
696 value = vmarg; | |
697 break; | |
633 case _adapter_opt_l2i: | 698 case _adapter_opt_l2i: |
634 __ unimplemented(entry_name(ek)); | 699 { |
635 value = vmarg; | 700 // just delete the extra slot |
701 __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot); | |
702 remove_arg_slots(_masm, -stack_move_unit(), O0_argslot, O1_scratch, O2_scratch, O3_scratch); | |
703 value = vmarg = Address(O0_argslot, 0); | |
704 } | |
636 break; | 705 break; |
637 case _adapter_opt_unboxi: | 706 case _adapter_opt_unboxi: |
638 { | 707 { |
639 // Load the value up from the heap. | 708 // Load the value up from the heap. |
640 __ ld_ptr(vmarg, O1_scratch); | 709 __ ld_ptr(vmarg, O1_scratch); |