src/share/vm/opto/generateOptoStub.cpp

Thu, 24 May 2018 17:06:56 +0800

author
aoqi
date
Thu, 24 May 2018 17:06:56 +0800
changeset 8604
04d83ba48607
parent 8316
626f594dffa6
parent 6876
710a3c8b516e
permissions
-rw-r--r--

Merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "opto/addnode.hpp"
aoqi@0 27 #include "opto/callnode.hpp"
aoqi@0 28 #include "opto/cfgnode.hpp"
aoqi@0 29 #include "opto/compile.hpp"
aoqi@0 30 #include "opto/connode.hpp"
aoqi@0 31 #include "opto/locknode.hpp"
aoqi@0 32 #include "opto/memnode.hpp"
aoqi@0 33 #include "opto/mulnode.hpp"
aoqi@0 34 #include "opto/node.hpp"
aoqi@0 35 #include "opto/parse.hpp"
aoqi@0 36 #include "opto/phaseX.hpp"
aoqi@0 37 #include "opto/rootnode.hpp"
aoqi@0 38 #include "opto/runtime.hpp"
aoqi@0 39 #include "opto/type.hpp"
aoqi@0 40
aoqi@0 41 //--------------------gen_stub-------------------------------
aoqi@0 42 void GraphKit::gen_stub(address C_function,
aoqi@0 43 const char *name,
aoqi@0 44 int is_fancy_jump,
aoqi@0 45 bool pass_tls,
aoqi@0 46 bool return_pc) {
aoqi@0 47 ResourceMark rm;
aoqi@0 48
aoqi@0 49 const TypeTuple *jdomain = C->tf()->domain();
aoqi@0 50 const TypeTuple *jrange = C->tf()->range();
aoqi@0 51
aoqi@0 52 // The procedure start
aoqi@0 53 StartNode* start = new (C) StartNode(root(), jdomain);
aoqi@0 54 _gvn.set_type_bottom(start);
aoqi@0 55
aoqi@0 56 // Make a map, with JVM state
aoqi@0 57 uint parm_cnt = jdomain->cnt();
aoqi@0 58 uint max_map = MAX2(2*parm_cnt+1, jrange->cnt());
aoqi@0 59 // %%% SynchronizationEntryBCI is redundant; use InvocationEntryBci in interfaces
aoqi@0 60 assert(SynchronizationEntryBCI == InvocationEntryBci, "");
aoqi@0 61 JVMState* jvms = new (C) JVMState(0);
aoqi@0 62 jvms->set_bci(InvocationEntryBci);
aoqi@0 63 jvms->set_monoff(max_map);
aoqi@0 64 jvms->set_scloff(max_map);
aoqi@0 65 jvms->set_endoff(max_map);
aoqi@0 66 {
aoqi@0 67 SafePointNode *map = new (C) SafePointNode( max_map, jvms );
aoqi@0 68 jvms->set_map(map);
aoqi@0 69 set_jvms(jvms);
aoqi@0 70 assert(map == this->map(), "kit.map is set");
aoqi@0 71 }
aoqi@0 72
aoqi@0 73 // Make up the parameters
aoqi@0 74 uint i;
aoqi@0 75 for( i = 0; i < parm_cnt; i++ )
aoqi@0 76 map()->init_req(i, _gvn.transform(new (C) ParmNode(start, i)));
aoqi@0 77 for( ; i<map()->req(); i++ )
aoqi@0 78 map()->init_req(i, top()); // For nicer debugging
aoqi@0 79
aoqi@0 80 // GraphKit requires memory to be a MergeMemNode:
aoqi@0 81 set_all_memory(map()->memory());
aoqi@0 82
aoqi@0 83 // Get base of thread-local storage area
aoqi@0 84 Node* thread = _gvn.transform( new (C) ThreadLocalNode() );
aoqi@0 85
aoqi@0 86 const int NoAlias = Compile::AliasIdxBot;
aoqi@0 87
aoqi@0 88 Node* adr_last_Java_pc = basic_plus_adr(top(),
aoqi@0 89 thread,
aoqi@0 90 in_bytes(JavaThread::frame_anchor_offset()) +
aoqi@0 91 in_bytes(JavaFrameAnchor::last_Java_pc_offset()));
aoqi@0 92 #if defined(SPARC)
aoqi@0 93 Node* adr_flags = basic_plus_adr(top(),
aoqi@0 94 thread,
aoqi@0 95 in_bytes(JavaThread::frame_anchor_offset()) +
aoqi@0 96 in_bytes(JavaFrameAnchor::flags_offset()));
aoqi@0 97 #endif /* defined(SPARC) */
aoqi@0 98
aoqi@0 99
aoqi@0 100 // Drop in the last_Java_sp. last_Java_fp is not touched.
aoqi@0 101 // Always do this after the other "last_Java_frame" fields are set since
aoqi@0 102 // as soon as last_Java_sp != NULL the has_last_Java_frame is true and
aoqi@0 103 // users will look at the other fields.
aoqi@0 104 //
aoqi@0 105 Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset()));
aoqi@0 106 Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS);
aoqi@0 107 store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias, MemNode::unordered);
aoqi@0 108
aoqi@0 109 // Set _thread_in_native
aoqi@0 110 // The order of stores into TLS is critical! Setting _thread_in_native MUST
aoqi@0 111 // be last, because a GC is allowed at any time after setting it and the GC
aoqi@0 112 // will require last_Java_pc and last_Java_sp.
aoqi@0 113
aoqi@0 114 //-----------------------------
aoqi@0 115 // Compute signature for C call. Varies from the Java signature!
aoqi@0 116 const Type **fields = TypeTuple::fields(2*parm_cnt+2);
aoqi@0 117 uint cnt = TypeFunc::Parms;
aoqi@0 118 // The C routines gets the base of thread-local storage passed in as an
aoqi@0 119 // extra argument. Not all calls need it, but its cheap to add here.
aoqi@0 120 for (uint pcnt = cnt; pcnt < parm_cnt; pcnt++, cnt++) {
aoqi@0 121 // Convert ints to longs if required.
aoqi@0 122 if (CCallingConventionRequiresIntsAsLongs && jdomain->field_at(pcnt)->isa_int()) {
aoqi@0 123 fields[cnt++] = TypeLong::LONG;
aoqi@0 124 fields[cnt] = Type::HALF; // must add an additional half for a long
aoqi@0 125 } else {
aoqi@0 126 fields[cnt] = jdomain->field_at(pcnt);
aoqi@0 127 }
aoqi@0 128 }
aoqi@0 129
aoqi@0 130 fields[cnt++] = TypeRawPtr::BOTTOM; // Thread-local storage
aoqi@0 131 // Also pass in the caller's PC, if asked for.
aoqi@0 132 if( return_pc )
aoqi@0 133 fields[cnt++] = TypeRawPtr::BOTTOM; // Return PC
aoqi@0 134
aoqi@0 135 const TypeTuple* domain = TypeTuple::make(cnt,fields);
aoqi@0 136 // The C routine we are about to call cannot return an oop; it can block on
aoqi@0 137 // exit and a GC will trash the oop while it sits in C-land. Instead, we
aoqi@0 138 // return the oop through TLS for runtime calls.
aoqi@0 139 // Also, C routines returning integer subword values leave the high
aoqi@0 140 // order bits dirty; these must be cleaned up by explicit sign extension.
aoqi@0 141 const Type* retval = (jrange->cnt() == TypeFunc::Parms) ? Type::TOP : jrange->field_at(TypeFunc::Parms);
aoqi@0 142 // Make a private copy of jrange->fields();
aoqi@0 143 const Type **rfields = TypeTuple::fields(jrange->cnt() - TypeFunc::Parms);
aoqi@0 144 // Fixup oop returns
aoqi@0 145 int retval_ptr = retval->isa_oop_ptr();
aoqi@0 146 if( retval_ptr ) {
aoqi@0 147 assert( pass_tls, "Oop must be returned thru TLS" );
aoqi@0 148 // Fancy-jumps return address; others return void
aoqi@0 149 rfields[TypeFunc::Parms] = is_fancy_jump ? TypeRawPtr::BOTTOM : Type::TOP;
aoqi@0 150
aoqi@0 151 } else if( retval->isa_int() ) { // Returning any integer subtype?
aoqi@0 152 // "Fatten" byte, char & short return types to 'int' to show that
aoqi@0 153 // the native C code can return values with junk high order bits.
aoqi@0 154 // We'll sign-extend it below later.
aoqi@0 155 rfields[TypeFunc::Parms] = TypeInt::INT; // It's "dirty" and needs sign-ext
aoqi@0 156
aoqi@0 157 } else if( jrange->cnt() >= TypeFunc::Parms+1 ) { // Else copy other types
aoqi@0 158 rfields[TypeFunc::Parms] = jrange->field_at(TypeFunc::Parms);
aoqi@0 159 if( jrange->cnt() == TypeFunc::Parms+2 )
aoqi@0 160 rfields[TypeFunc::Parms+1] = jrange->field_at(TypeFunc::Parms+1);
aoqi@0 161 }
aoqi@0 162 const TypeTuple* range = TypeTuple::make(jrange->cnt(),rfields);
aoqi@0 163
aoqi@0 164 // Final C signature
aoqi@0 165 const TypeFunc *c_sig = TypeFunc::make(domain,range);
aoqi@0 166
aoqi@0 167 //-----------------------------
aoqi@0 168 // Make the call node
aoqi@0 169 CallRuntimeNode *call = new (C)
aoqi@0 170 CallRuntimeNode(c_sig, C_function, name, TypePtr::BOTTOM);
aoqi@0 171 //-----------------------------
aoqi@0 172
aoqi@0 173 // Fix-up the debug info for the call
aoqi@0 174 call->set_jvms( new (C) JVMState(0) );
aoqi@0 175 call->jvms()->set_bci(0);
aoqi@0 176 call->jvms()->set_offsets(cnt);
aoqi@0 177
aoqi@0 178 // Set fixed predefined input arguments
aoqi@0 179 cnt = 0;
aoqi@0 180 for (i = 0; i < TypeFunc::Parms; i++)
aoqi@0 181 call->init_req(cnt++, map()->in(i));
aoqi@0 182 // A little too aggressive on the parm copy; return address is not an input
aoqi@0 183 call->set_req(TypeFunc::ReturnAdr, top());
aoqi@0 184 for (; i < parm_cnt; i++) { // Regular input arguments
aoqi@0 185 // Convert ints to longs if required.
aoqi@0 186 if (CCallingConventionRequiresIntsAsLongs && jdomain->field_at(i)->isa_int()) {
aoqi@0 187 Node* int_as_long = _gvn.transform(new (C) ConvI2LNode(map()->in(i)));
aoqi@0 188 call->init_req(cnt++, int_as_long); // long
aoqi@0 189 call->init_req(cnt++, top()); // half
aoqi@0 190 } else {
aoqi@0 191 call->init_req(cnt++, map()->in(i));
aoqi@0 192 }
aoqi@0 193 }
aoqi@0 194
aoqi@0 195 call->init_req( cnt++, thread );
aoqi@0 196 if( return_pc ) // Return PC, if asked for
aoqi@0 197 call->init_req( cnt++, returnadr() );
aoqi@0 198 _gvn.transform_no_reclaim(call);
aoqi@0 199
aoqi@0 200
aoqi@0 201 //-----------------------------
aoqi@0 202 // Now set up the return results
aoqi@0 203 set_control( _gvn.transform( new (C) ProjNode(call,TypeFunc::Control)) );
aoqi@0 204 set_i_o( _gvn.transform( new (C) ProjNode(call,TypeFunc::I_O )) );
aoqi@0 205 set_all_memory_call(call);
aoqi@0 206 if (range->cnt() > TypeFunc::Parms) {
aoqi@0 207 Node* retnode = _gvn.transform( new (C) ProjNode(call,TypeFunc::Parms) );
aoqi@0 208 // C-land is allowed to return sub-word values. Convert to integer type.
aoqi@0 209 assert( retval != Type::TOP, "" );
aoqi@0 210 if (retval == TypeInt::BOOL) {
aoqi@0 211 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFF)) );
aoqi@0 212 } else if (retval == TypeInt::CHAR) {
aoqi@0 213 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFFFF)) );
aoqi@0 214 } else if (retval == TypeInt::BYTE) {
aoqi@0 215 retnode = _gvn.transform( new (C) LShiftINode(retnode, intcon(24)) );
aoqi@0 216 retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(24)) );
aoqi@0 217 } else if (retval == TypeInt::SHORT) {
aoqi@0 218 retnode = _gvn.transform( new (C) LShiftINode(retnode, intcon(16)) );
aoqi@0 219 retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(16)) );
aoqi@0 220 }
aoqi@0 221 map()->set_req( TypeFunc::Parms, retnode );
aoqi@0 222 }
aoqi@0 223
aoqi@0 224 //-----------------------------
aoqi@0 225
aoqi@0 226 // Clear last_Java_sp
aoqi@0 227 store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias, MemNode::unordered);
aoqi@0 228 // Clear last_Java_pc and (optionally)_flags
aoqi@0 229 store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias, MemNode::unordered);
aoqi@0 230 #if defined(SPARC)
aoqi@0 231 store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias, MemNode::unordered);
aoqi@0 232 #endif /* defined(SPARC) */
aoqi@0 233 #if (defined(IA64) && !defined(AIX))
aoqi@0 234 Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset()));
aoqi@0 235 store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias, MemNode::unordered);
aoqi@0 236 #endif
aoqi@0 237
aoqi@0 238 // For is-fancy-jump, the C-return value is also the branch target
aoqi@0 239 Node* target = map()->in(TypeFunc::Parms);
aoqi@0 240 // Runtime call returning oop in TLS? Fetch it out
aoqi@0 241 if( pass_tls ) {
aoqi@0 242 Node* adr = basic_plus_adr(top(), thread, in_bytes(JavaThread::vm_result_offset()));
aoqi@0 243 Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered);
aoqi@0 244 map()->set_req(TypeFunc::Parms, vm_result); // vm_result passed as result
aoqi@0 245 // clear thread-local-storage(tls)
aoqi@0 246 store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias, MemNode::unordered);
aoqi@0 247 }
aoqi@0 248
aoqi@0 249 //-----------------------------
aoqi@0 250 // check exception
aoqi@0 251 Node* adr = basic_plus_adr(top(), thread, in_bytes(Thread::pending_exception_offset()));
aoqi@0 252 Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered);
aoqi@0 253
aoqi@0 254 Node* exit_memory = reset_memory();
aoqi@0 255
aoqi@0 256 Node* cmp = _gvn.transform( new (C) CmpPNode(pending, null()) );
aoqi@0 257 Node* bo = _gvn.transform( new (C) BoolNode(cmp, BoolTest::ne) );
aoqi@0 258 IfNode *iff = create_and_map_if(control(), bo, PROB_MIN, COUNT_UNKNOWN);
aoqi@0 259
aoqi@0 260 Node* if_null = _gvn.transform( new (C) IfFalseNode(iff) );
aoqi@0 261 Node* if_not_null = _gvn.transform( new (C) IfTrueNode(iff) );
aoqi@0 262
aoqi@0 263 assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before");
aoqi@0 264 Node *exc_target = makecon(TypeRawPtr::make( StubRoutines::forward_exception_entry() ));
aoqi@0 265 Node *to_exc = new (C) TailCallNode(if_not_null,
aoqi@0 266 i_o(),
aoqi@0 267 exit_memory,
aoqi@0 268 frameptr(),
aoqi@0 269 returnadr(),
aoqi@0 270 exc_target, null());
aoqi@0 271 root()->add_req(_gvn.transform(to_exc)); // bind to root to keep live
aoqi@0 272 C->init_start(start);
aoqi@0 273
aoqi@0 274 //-----------------------------
aoqi@0 275 // If this is a normal subroutine return, issue the return and be done.
csahu@8316 276 Node *ret = NULL;
aoqi@0 277 switch( is_fancy_jump ) {
aoqi@0 278 case 0: // Make a return instruction
aoqi@0 279 // Return to caller, free any space for return address
aoqi@0 280 ret = new (C) ReturnNode(TypeFunc::Parms, if_null,
aoqi@0 281 i_o(),
aoqi@0 282 exit_memory,
aoqi@0 283 frameptr(),
aoqi@0 284 returnadr());
aoqi@0 285 if (C->tf()->range()->cnt() > TypeFunc::Parms)
aoqi@0 286 ret->add_req( map()->in(TypeFunc::Parms) );
aoqi@0 287 break;
aoqi@0 288 case 1: // This is a fancy tail-call jump. Jump to computed address.
aoqi@0 289 // Jump to new callee; leave old return address alone.
aoqi@0 290 ret = new (C) TailCallNode(if_null,
aoqi@0 291 i_o(),
aoqi@0 292 exit_memory,
aoqi@0 293 frameptr(),
aoqi@0 294 returnadr(),
aoqi@0 295 target, map()->in(TypeFunc::Parms));
aoqi@0 296 break;
aoqi@0 297 case 2: // Pop return address & jump
aoqi@0 298 // Throw away old return address; jump to new computed address
aoqi@0 299 //assert(C_function == CAST_FROM_FN_PTR(address, OptoRuntime::rethrow_C), "fancy_jump==2 only for rethrow");
aoqi@0 300 ret = new (C) TailJumpNode(if_null,
aoqi@0 301 i_o(),
aoqi@0 302 exit_memory,
aoqi@0 303 frameptr(),
aoqi@0 304 target, map()->in(TypeFunc::Parms));
aoqi@0 305 break;
aoqi@0 306 default:
aoqi@0 307 ShouldNotReachHere();
aoqi@0 308 }
aoqi@0 309 root()->add_req(_gvn.transform(ret));
aoqi@0 310 }

mercurial