src/share/vm/opto/generateOptoStub.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/opto/generateOptoStub.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,310 @@
     1.4 +/*
     1.5 + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "opto/addnode.hpp"
    1.30 +#include "opto/callnode.hpp"
    1.31 +#include "opto/cfgnode.hpp"
    1.32 +#include "opto/compile.hpp"
    1.33 +#include "opto/connode.hpp"
    1.34 +#include "opto/locknode.hpp"
    1.35 +#include "opto/memnode.hpp"
    1.36 +#include "opto/mulnode.hpp"
    1.37 +#include "opto/node.hpp"
    1.38 +#include "opto/parse.hpp"
    1.39 +#include "opto/phaseX.hpp"
    1.40 +#include "opto/rootnode.hpp"
    1.41 +#include "opto/runtime.hpp"
    1.42 +#include "opto/type.hpp"
    1.43 +
    1.44 +//--------------------gen_stub-------------------------------
    1.45 +void GraphKit::gen_stub(address C_function,
    1.46 +                        const char *name,
    1.47 +                        int is_fancy_jump,
    1.48 +                        bool pass_tls,
    1.49 +                        bool return_pc) {
    1.50 +  ResourceMark rm;
    1.51 +
    1.52 +  const TypeTuple *jdomain = C->tf()->domain();
    1.53 +  const TypeTuple *jrange  = C->tf()->range();
    1.54 +
    1.55 +  // The procedure start
    1.56 +  StartNode* start = new (C) StartNode(root(), jdomain);
    1.57 +  _gvn.set_type_bottom(start);
    1.58 +
    1.59 +  // Make a map, with JVM state
    1.60 +  uint parm_cnt = jdomain->cnt();
    1.61 +  uint max_map = MAX2(2*parm_cnt+1, jrange->cnt());
    1.62 +  // %%% SynchronizationEntryBCI is redundant; use InvocationEntryBci in interfaces
    1.63 +  assert(SynchronizationEntryBCI == InvocationEntryBci, "");
    1.64 +  JVMState* jvms = new (C) JVMState(0);
    1.65 +  jvms->set_bci(InvocationEntryBci);
    1.66 +  jvms->set_monoff(max_map);
    1.67 +  jvms->set_scloff(max_map);
    1.68 +  jvms->set_endoff(max_map);
    1.69 +  {
    1.70 +    SafePointNode *map = new (C) SafePointNode( max_map, jvms );
    1.71 +    jvms->set_map(map);
    1.72 +    set_jvms(jvms);
    1.73 +    assert(map == this->map(), "kit.map is set");
    1.74 +  }
    1.75 +
    1.76 +  // Make up the parameters
    1.77 +  uint i;
    1.78 +  for( i = 0; i < parm_cnt; i++ )
    1.79 +    map()->init_req(i, _gvn.transform(new (C) ParmNode(start, i)));
    1.80 +  for( ; i<map()->req(); i++ )
    1.81 +    map()->init_req(i, top());      // For nicer debugging
    1.82 +
    1.83 +  // GraphKit requires memory to be a MergeMemNode:
    1.84 +  set_all_memory(map()->memory());
    1.85 +
    1.86 +  // Get base of thread-local storage area
    1.87 +  Node* thread = _gvn.transform( new (C) ThreadLocalNode() );
    1.88 +
    1.89 +  const int NoAlias = Compile::AliasIdxBot;
    1.90 +
    1.91 +  Node* adr_last_Java_pc = basic_plus_adr(top(),
    1.92 +                                            thread,
    1.93 +                                            in_bytes(JavaThread::frame_anchor_offset()) +
    1.94 +                                            in_bytes(JavaFrameAnchor::last_Java_pc_offset()));
    1.95 +#if defined(SPARC)
    1.96 +  Node* adr_flags = basic_plus_adr(top(),
    1.97 +                                   thread,
    1.98 +                                   in_bytes(JavaThread::frame_anchor_offset()) +
    1.99 +                                   in_bytes(JavaFrameAnchor::flags_offset()));
   1.100 +#endif /* defined(SPARC) */
   1.101 +
   1.102 +
   1.103 +  // Drop in the last_Java_sp.  last_Java_fp is not touched.
   1.104 +  // Always do this after the other "last_Java_frame" fields are set since
   1.105 +  // as soon as last_Java_sp != NULL the has_last_Java_frame is true and
   1.106 +  // users will look at the other fields.
   1.107 +  //
   1.108 +  Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset()));
   1.109 +  Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS);
   1.110 +  store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias, MemNode::unordered);
   1.111 +
   1.112 +  // Set _thread_in_native
   1.113 +  // The order of stores into TLS is critical!  Setting _thread_in_native MUST
   1.114 +  // be last, because a GC is allowed at any time after setting it and the GC
   1.115 +  // will require last_Java_pc and last_Java_sp.
   1.116 +
   1.117 +  //-----------------------------
   1.118 +  // Compute signature for C call.  Varies from the Java signature!
   1.119 +  const Type **fields = TypeTuple::fields(2*parm_cnt+2);
   1.120 +  uint cnt = TypeFunc::Parms;
   1.121 +  // The C routines gets the base of thread-local storage passed in as an
   1.122 +  // extra argument.  Not all calls need it, but its cheap to add here.
   1.123 +  for (uint pcnt = cnt; pcnt < parm_cnt; pcnt++, cnt++) {
   1.124 +    // Convert ints to longs if required.
   1.125 +    if (CCallingConventionRequiresIntsAsLongs && jdomain->field_at(pcnt)->isa_int()) {
   1.126 +      fields[cnt++] = TypeLong::LONG;
   1.127 +      fields[cnt]   = Type::HALF; // must add an additional half for a long
   1.128 +    } else {
   1.129 +      fields[cnt] = jdomain->field_at(pcnt);
   1.130 +    }
   1.131 +  }
   1.132 +
   1.133 +  fields[cnt++] = TypeRawPtr::BOTTOM; // Thread-local storage
   1.134 +  // Also pass in the caller's PC, if asked for.
   1.135 +  if( return_pc )
   1.136 +    fields[cnt++] = TypeRawPtr::BOTTOM; // Return PC
   1.137 +
   1.138 +  const TypeTuple* domain = TypeTuple::make(cnt,fields);
   1.139 +  // The C routine we are about to call cannot return an oop; it can block on
   1.140 +  // exit and a GC will trash the oop while it sits in C-land.  Instead, we
   1.141 +  // return the oop through TLS for runtime calls.
   1.142 +  // Also, C routines returning integer subword values leave the high
   1.143 +  // order bits dirty; these must be cleaned up by explicit sign extension.
   1.144 +  const Type* retval = (jrange->cnt() == TypeFunc::Parms) ? Type::TOP : jrange->field_at(TypeFunc::Parms);
   1.145 +  // Make a private copy of jrange->fields();
   1.146 +  const Type **rfields = TypeTuple::fields(jrange->cnt() - TypeFunc::Parms);
   1.147 +  // Fixup oop returns
   1.148 +  int retval_ptr = retval->isa_oop_ptr();
   1.149 +  if( retval_ptr ) {
   1.150 +    assert( pass_tls, "Oop must be returned thru TLS" );
   1.151 +    // Fancy-jumps return address; others return void
   1.152 +    rfields[TypeFunc::Parms] = is_fancy_jump ? TypeRawPtr::BOTTOM : Type::TOP;
   1.153 +
   1.154 +  } else if( retval->isa_int() ) { // Returning any integer subtype?
   1.155 +    // "Fatten" byte, char & short return types to 'int' to show that
   1.156 +    // the native C code can return values with junk high order bits.
   1.157 +    // We'll sign-extend it below later.
   1.158 +    rfields[TypeFunc::Parms] = TypeInt::INT; // It's "dirty" and needs sign-ext
   1.159 +
   1.160 +  } else if( jrange->cnt() >= TypeFunc::Parms+1 ) { // Else copy other types
   1.161 +    rfields[TypeFunc::Parms] = jrange->field_at(TypeFunc::Parms);
   1.162 +    if( jrange->cnt() == TypeFunc::Parms+2 )
   1.163 +      rfields[TypeFunc::Parms+1] = jrange->field_at(TypeFunc::Parms+1);
   1.164 +  }
   1.165 +  const TypeTuple* range = TypeTuple::make(jrange->cnt(),rfields);
   1.166 +
   1.167 +  // Final C signature
   1.168 +  const TypeFunc *c_sig = TypeFunc::make(domain,range);
   1.169 +
   1.170 +  //-----------------------------
   1.171 +  // Make the call node
   1.172 +  CallRuntimeNode *call = new (C)
   1.173 +    CallRuntimeNode(c_sig, C_function, name, TypePtr::BOTTOM);
   1.174 +  //-----------------------------
   1.175 +
   1.176 +  // Fix-up the debug info for the call
   1.177 +  call->set_jvms( new (C) JVMState(0) );
   1.178 +  call->jvms()->set_bci(0);
   1.179 +  call->jvms()->set_offsets(cnt);
   1.180 +
   1.181 +  // Set fixed predefined input arguments
   1.182 +  cnt = 0;
   1.183 +  for (i = 0; i < TypeFunc::Parms; i++)
   1.184 +    call->init_req(cnt++, map()->in(i));
   1.185 +  // A little too aggressive on the parm copy; return address is not an input
   1.186 +  call->set_req(TypeFunc::ReturnAdr, top());
   1.187 +  for (; i < parm_cnt; i++) { // Regular input arguments
   1.188 +    // Convert ints to longs if required.
   1.189 +    if (CCallingConventionRequiresIntsAsLongs && jdomain->field_at(i)->isa_int()) {
   1.190 +      Node* int_as_long = _gvn.transform(new (C) ConvI2LNode(map()->in(i)));
   1.191 +      call->init_req(cnt++, int_as_long); // long
   1.192 +      call->init_req(cnt++, top());       // half
   1.193 +    } else {
   1.194 +      call->init_req(cnt++, map()->in(i));
   1.195 +    }
   1.196 +  }
   1.197 +
   1.198 +  call->init_req( cnt++, thread );
   1.199 +  if( return_pc )             // Return PC, if asked for
   1.200 +    call->init_req( cnt++, returnadr() );
   1.201 +  _gvn.transform_no_reclaim(call);
   1.202 +
   1.203 +
   1.204 +  //-----------------------------
   1.205 +  // Now set up the return results
   1.206 +  set_control( _gvn.transform( new (C) ProjNode(call,TypeFunc::Control)) );
   1.207 +  set_i_o(     _gvn.transform( new (C) ProjNode(call,TypeFunc::I_O    )) );
   1.208 +  set_all_memory_call(call);
   1.209 +  if (range->cnt() > TypeFunc::Parms) {
   1.210 +    Node* retnode = _gvn.transform( new (C) ProjNode(call,TypeFunc::Parms) );
   1.211 +    // C-land is allowed to return sub-word values.  Convert to integer type.
   1.212 +    assert( retval != Type::TOP, "" );
   1.213 +    if (retval == TypeInt::BOOL) {
   1.214 +      retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFF)) );
   1.215 +    } else if (retval == TypeInt::CHAR) {
   1.216 +      retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFFFF)) );
   1.217 +    } else if (retval == TypeInt::BYTE) {
   1.218 +      retnode = _gvn.transform( new (C) LShiftINode(retnode, intcon(24)) );
   1.219 +      retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(24)) );
   1.220 +    } else if (retval == TypeInt::SHORT) {
   1.221 +      retnode = _gvn.transform( new (C) LShiftINode(retnode, intcon(16)) );
   1.222 +      retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(16)) );
   1.223 +    }
   1.224 +    map()->set_req( TypeFunc::Parms, retnode );
   1.225 +  }
   1.226 +
   1.227 +  //-----------------------------
   1.228 +
   1.229 +  // Clear last_Java_sp
   1.230 +  store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias, MemNode::unordered);
   1.231 +  // Clear last_Java_pc and (optionally)_flags
   1.232 +  store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias, MemNode::unordered);
   1.233 +#if defined(SPARC)
   1.234 +  store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias, MemNode::unordered);
   1.235 +#endif /* defined(SPARC) */
   1.236 +#if (defined(IA64) && !defined(AIX))
   1.237 +  Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset()));
   1.238 +  store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias, MemNode::unordered);
   1.239 +#endif
   1.240 +
   1.241 +  // For is-fancy-jump, the C-return value is also the branch target
   1.242 +  Node* target = map()->in(TypeFunc::Parms);
   1.243 +  // Runtime call returning oop in TLS?  Fetch it out
   1.244 +  if( pass_tls ) {
   1.245 +    Node* adr = basic_plus_adr(top(), thread, in_bytes(JavaThread::vm_result_offset()));
   1.246 +    Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered);
   1.247 +    map()->set_req(TypeFunc::Parms, vm_result); // vm_result passed as result
   1.248 +    // clear thread-local-storage(tls)
   1.249 +    store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias, MemNode::unordered);
   1.250 +  }
   1.251 +
   1.252 +  //-----------------------------
   1.253 +  // check exception
   1.254 +  Node* adr = basic_plus_adr(top(), thread, in_bytes(Thread::pending_exception_offset()));
   1.255 +  Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, MemNode::unordered);
   1.256 +
   1.257 +  Node* exit_memory = reset_memory();
   1.258 +
   1.259 +  Node* cmp = _gvn.transform( new (C) CmpPNode(pending, null()) );
   1.260 +  Node* bo  = _gvn.transform( new (C) BoolNode(cmp, BoolTest::ne) );
   1.261 +  IfNode   *iff = create_and_map_if(control(), bo, PROB_MIN, COUNT_UNKNOWN);
   1.262 +
   1.263 +  Node* if_null     = _gvn.transform( new (C) IfFalseNode(iff) );
   1.264 +  Node* if_not_null = _gvn.transform( new (C) IfTrueNode(iff)  );
   1.265 +
   1.266 +  assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before");
   1.267 +  Node *exc_target = makecon(TypeRawPtr::make( StubRoutines::forward_exception_entry() ));
   1.268 +  Node *to_exc = new (C) TailCallNode(if_not_null,
   1.269 +                                      i_o(),
   1.270 +                                      exit_memory,
   1.271 +                                      frameptr(),
   1.272 +                                      returnadr(),
   1.273 +                                      exc_target, null());
   1.274 +  root()->add_req(_gvn.transform(to_exc));  // bind to root to keep live
   1.275 +  C->init_start(start);
   1.276 +
   1.277 +  //-----------------------------
   1.278 +  // If this is a normal subroutine return, issue the return and be done.
   1.279 +  Node *ret;
   1.280 +  switch( is_fancy_jump ) {
   1.281 +  case 0:                       // Make a return instruction
   1.282 +    // Return to caller, free any space for return address
   1.283 +    ret = new (C) ReturnNode(TypeFunc::Parms, if_null,
   1.284 +                             i_o(),
   1.285 +                             exit_memory,
   1.286 +                             frameptr(),
   1.287 +                             returnadr());
   1.288 +    if (C->tf()->range()->cnt() > TypeFunc::Parms)
   1.289 +      ret->add_req( map()->in(TypeFunc::Parms) );
   1.290 +    break;
   1.291 +  case 1:    // This is a fancy tail-call jump.  Jump to computed address.
   1.292 +    // Jump to new callee; leave old return address alone.
   1.293 +    ret = new (C) TailCallNode(if_null,
   1.294 +                               i_o(),
   1.295 +                               exit_memory,
   1.296 +                               frameptr(),
   1.297 +                               returnadr(),
   1.298 +                               target, map()->in(TypeFunc::Parms));
   1.299 +    break;
   1.300 +  case 2:                       // Pop return address & jump
   1.301 +    // Throw away old return address; jump to new computed address
   1.302 +    //assert(C_function == CAST_FROM_FN_PTR(address, OptoRuntime::rethrow_C), "fancy_jump==2 only for rethrow");
   1.303 +    ret = new (C) TailJumpNode(if_null,
   1.304 +                               i_o(),
   1.305 +                               exit_memory,
   1.306 +                               frameptr(),
   1.307 +                               target, map()->in(TypeFunc::Parms));
   1.308 +    break;
   1.309 +  default:
   1.310 +    ShouldNotReachHere();
   1.311 +  }
   1.312 +  root()->add_req(_gvn.transform(ret));
   1.313 +}

mercurial