1.1 --- a/src/share/vm/opto/callGenerator.cpp Fri Nov 27 07:56:58 2009 -0800 1.2 +++ b/src/share/vm/opto/callGenerator.cpp Thu Nov 12 09:24:21 2009 -0800 1.3 @@ -98,12 +98,21 @@ 1.4 //---------------------------DirectCallGenerator------------------------------ 1.5 // Internal class which handles all out-of-line calls w/o receiver type checks. 1.6 class DirectCallGenerator : public CallGenerator { 1.7 -public: 1.8 - DirectCallGenerator(ciMethod* method) 1.9 - : CallGenerator(method) 1.10 + private: 1.11 + CallStaticJavaNode* _call_node; 1.12 + // Force separate memory and I/O projections for the exceptional 1.13 + // paths to facilitate late inlinig. 1.14 + bool _separate_io_proj; 1.15 + 1.16 + public: 1.17 + DirectCallGenerator(ciMethod* method, bool separate_io_proj) 1.18 + : CallGenerator(method), 1.19 + _separate_io_proj(separate_io_proj) 1.20 { 1.21 } 1.22 virtual JVMState* generate(JVMState* jvms); 1.23 + 1.24 + CallStaticJavaNode* call_node() const { return _call_node; } 1.25 }; 1.26 1.27 JVMState* DirectCallGenerator::generate(JVMState* jvms) { 1.28 @@ -129,9 +138,10 @@ 1.29 call->set_optimized_virtual(true); 1.30 } 1.31 kit.set_arguments_for_java_call(call); 1.32 - kit.set_edges_for_java_call(call); 1.33 - Node* ret = kit.set_results_for_java_call(call); 1.34 + kit.set_edges_for_java_call(call, false, _separate_io_proj); 1.35 + Node* ret = kit.set_results_for_java_call(call, _separate_io_proj); 1.36 kit.push_node(method()->return_type()->basic_type(), ret); 1.37 + _call_node = call; // Save the call node in case we need it later 1.38 return kit.transfer_exceptions_into_jvms(); 1.39 } 1.40 1.41 @@ -238,9 +248,9 @@ 1.42 return new ParseGenerator(m, expected_uses, true); 1.43 } 1.44 1.45 -CallGenerator* CallGenerator::for_direct_call(ciMethod* m) { 1.46 +CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) { 1.47 assert(!m->is_abstract(), "for_direct_call mismatch"); 1.48 - return new DirectCallGenerator(m); 1.49 + return new DirectCallGenerator(m, separate_io_proj); 1.50 } 1.51 1.52 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { 1.53 @@ -248,6 +258,108 @@ 1.54 return new VirtualCallGenerator(m, vtable_index); 1.55 } 1.56 1.57 +// Allow inlining decisions to be delayed 1.58 +class LateInlineCallGenerator : public DirectCallGenerator { 1.59 + CallGenerator* _inline_cg; 1.60 + 1.61 + public: 1.62 + LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) : 1.63 + DirectCallGenerator(method, true), _inline_cg(inline_cg) {} 1.64 + 1.65 + virtual bool is_late_inline() const { return true; } 1.66 + 1.67 + // Convert the CallStaticJava into an inline 1.68 + virtual void do_late_inline(); 1.69 + 1.70 + JVMState* generate(JVMState* jvms) { 1.71 + // Record that this call site should be revisited once the main 1.72 + // parse is finished. 1.73 + Compile::current()->add_late_inline(this); 1.74 + 1.75 + // Emit the CallStaticJava and request separate projections so 1.76 + // that the late inlining logic can distinguish between fall 1.77 + // through and exceptional uses of the memory and io projections 1.78 + // as is done for allocations and macro expansion. 1.79 + return DirectCallGenerator::generate(jvms); 1.80 + } 1.81 + 1.82 +}; 1.83 + 1.84 + 1.85 +void LateInlineCallGenerator::do_late_inline() { 1.86 + // Can't inline it 1.87 + if (call_node() == NULL || call_node()->outcnt() == 0 || 1.88 + call_node()->in(0) == NULL || call_node()->in(0)->is_top()) 1.89 + return; 1.90 + 1.91 + CallStaticJavaNode* call = call_node(); 1.92 + 1.93 + // Make a clone of the JVMState that appropriate to use for driving a parse 1.94 + Compile* C = Compile::current(); 1.95 + JVMState* jvms = call->jvms()->clone_shallow(C); 1.96 + uint size = call->req(); 1.97 + SafePointNode* map = new (C, size) SafePointNode(size, jvms); 1.98 + for (uint i1 = 0; i1 < size; i1++) { 1.99 + map->init_req(i1, call->in(i1)); 1.100 + } 1.101 + 1.102 + // Make sure the state is a MergeMem for parsing. 1.103 + if (!map->in(TypeFunc::Memory)->is_MergeMem()) { 1.104 + map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory))); 1.105 + } 1.106 + 1.107 + // Make enough space for the expression stack and transfer the incoming arguments 1.108 + int nargs = method()->arg_size(); 1.109 + jvms->set_map(map); 1.110 + map->ensure_stack(jvms, jvms->method()->max_stack()); 1.111 + if (nargs > 0) { 1.112 + for (int i1 = 0; i1 < nargs; i1++) { 1.113 + map->set_req(i1 + jvms->argoff(), call->in(TypeFunc::Parms + i1)); 1.114 + } 1.115 + } 1.116 + 1.117 + CompileLog* log = C->log(); 1.118 + if (log != NULL) { 1.119 + log->head("late_inline method='%d'", log->identify(method())); 1.120 + JVMState* p = jvms; 1.121 + while (p != NULL) { 1.122 + log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); 1.123 + p = p->caller(); 1.124 + } 1.125 + log->tail("late_inline"); 1.126 + } 1.127 + 1.128 + // Setup default node notes to be picked up by the inlining 1.129 + Node_Notes* old_nn = C->default_node_notes(); 1.130 + if (old_nn != NULL) { 1.131 + Node_Notes* entry_nn = old_nn->clone(C); 1.132 + entry_nn->set_jvms(jvms); 1.133 + C->set_default_node_notes(entry_nn); 1.134 + } 1.135 + 1.136 + // Now perform the inling using the synthesized JVMState 1.137 + JVMState* new_jvms = _inline_cg->generate(jvms); 1.138 + if (new_jvms == NULL) return; // no change 1.139 + if (C->failing()) return; 1.140 + 1.141 + // Capture any exceptional control flow 1.142 + GraphKit kit(new_jvms); 1.143 + 1.144 + // Find the result object 1.145 + Node* result = C->top(); 1.146 + int result_size = method()->return_type()->size(); 1.147 + if (result_size != 0 && !kit.stopped()) { 1.148 + result = (result_size == 1) ? kit.pop() : kit.pop_pair(); 1.149 + } 1.150 + 1.151 + kit.replace_call(call, result); 1.152 +} 1.153 + 1.154 + 1.155 +CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) { 1.156 + return new LateInlineCallGenerator(method, inline_cg); 1.157 +} 1.158 + 1.159 1.160 //---------------------------WarmCallGenerator-------------------------------- 1.161 // Internal class which handles initial deferral of inlining decisions. 1.162 @@ -315,70 +427,7 @@ 1.163 } 1.164 1.165 void WarmCallInfo::make_hot() { 1.166 - Compile* C = Compile::current(); 1.167 - // Replace the callnode with something better. 1.168 - CallJavaNode* call = this->call()->as_CallJava(); 1.169 - ciMethod* method = call->method(); 1.170 - int nargs = method->arg_size(); 1.171 - JVMState* jvms = call->jvms()->clone_shallow(C); 1.172 - uint size = TypeFunc::Parms + MAX2(2, nargs); 1.173 - SafePointNode* map = new (C, size) SafePointNode(size, jvms); 1.174 - for (uint i1 = 0; i1 < (uint)(TypeFunc::Parms + nargs); i1++) { 1.175 - map->init_req(i1, call->in(i1)); 1.176 - } 1.177 - jvms->set_map(map); 1.178 - jvms->set_offsets(map->req()); 1.179 - jvms->set_locoff(TypeFunc::Parms); 1.180 - jvms->set_stkoff(TypeFunc::Parms); 1.181 - GraphKit kit(jvms); 1.182 - 1.183 - JVMState* new_jvms = _hot_cg->generate(kit.jvms()); 1.184 - if (new_jvms == NULL) return; // no change 1.185 - if (C->failing()) return; 1.186 - 1.187 - kit.set_jvms(new_jvms); 1.188 - Node* res = C->top(); 1.189 - int res_size = method->return_type()->size(); 1.190 - if (res_size != 0) { 1.191 - kit.inc_sp(-res_size); 1.192 - res = kit.argument(0); 1.193 - } 1.194 - GraphKit ekit(kit.combine_and_pop_all_exception_states()->jvms()); 1.195 - 1.196 - // Replace the call: 1.197 - for (DUIterator i = call->outs(); call->has_out(i); i++) { 1.198 - Node* n = call->out(i); 1.199 - Node* nn = NULL; // replacement 1.200 - if (n->is_Proj()) { 1.201 - ProjNode* nproj = n->as_Proj(); 1.202 - assert(nproj->_con < (uint)(TypeFunc::Parms + (res_size ? 1 : 0)), "sane proj"); 1.203 - if (nproj->_con == TypeFunc::Parms) { 1.204 - nn = res; 1.205 - } else { 1.206 - nn = kit.map()->in(nproj->_con); 1.207 - } 1.208 - if (nproj->_con == TypeFunc::I_O) { 1.209 - for (DUIterator j = nproj->outs(); nproj->has_out(j); j++) { 1.210 - Node* e = nproj->out(j); 1.211 - if (e->Opcode() == Op_CreateEx) { 1.212 - e->replace_by(ekit.argument(0)); 1.213 - } else if (e->Opcode() == Op_Catch) { 1.214 - for (DUIterator k = e->outs(); e->has_out(k); k++) { 1.215 - CatchProjNode* p = e->out(j)->as_CatchProj(); 1.216 - if (p->is_handler_proj()) { 1.217 - p->replace_by(ekit.control()); 1.218 - } else { 1.219 - p->replace_by(kit.control()); 1.220 - } 1.221 - } 1.222 - } 1.223 - } 1.224 - } 1.225 - } 1.226 - NOT_PRODUCT(if (!nn) n->dump(2)); 1.227 - assert(nn != NULL, "don't know what to do with this user"); 1.228 - n->replace_by(nn); 1.229 - } 1.230 + Unimplemented(); 1.231 } 1.232 1.233 void WarmCallInfo::make_cold() {