annotate src/share/vm/opto/callGenerator.cpp @ 1941:79d04223b8a5

Added caching for resolved types and resolved fields. This is crucial, because the local load elimination will lead to wrong results, if field equality (of two RiField objects with the same object and the same RiType) is not given. The caching makes sure that the default equals implementation is sufficient.
author Thomas Wuerthinger <wuerthinger@ssw.jku.at>
date Tue, 28 Dec 2010 18:33:26 +0100
parents c18cbe5936b8
children f95d63e2154a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1265
diff changeset
2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1265
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1265
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1265
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 #include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 #include "incls/_callGenerator.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 CallGenerator::CallGenerator(ciMethod* method) {
a61af66fc99e Initial load
duke
parents:
diff changeset
29 _method = method;
a61af66fc99e Initial load
duke
parents:
diff changeset
30 }
a61af66fc99e Initial load
duke
parents:
diff changeset
31
a61af66fc99e Initial load
duke
parents:
diff changeset
32 // Utility function.
a61af66fc99e Initial load
duke
parents:
diff changeset
33 const TypeFunc* CallGenerator::tf() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
34 return TypeFunc::make(method());
a61af66fc99e Initial load
duke
parents:
diff changeset
35 }
a61af66fc99e Initial load
duke
parents:
diff changeset
36
a61af66fc99e Initial load
duke
parents:
diff changeset
37 //-----------------------------ParseGenerator---------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
38 // Internal class which handles all direct bytecode traversal.
a61af66fc99e Initial load
duke
parents:
diff changeset
39 class ParseGenerator : public InlineCallGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
40 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
41 bool _is_osr;
a61af66fc99e Initial load
duke
parents:
diff changeset
42 float _expected_uses;
a61af66fc99e Initial load
duke
parents:
diff changeset
43
a61af66fc99e Initial load
duke
parents:
diff changeset
44 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
45 ParseGenerator(ciMethod* method, float expected_uses, bool is_osr = false)
a61af66fc99e Initial load
duke
parents:
diff changeset
46 : InlineCallGenerator(method)
a61af66fc99e Initial load
duke
parents:
diff changeset
47 {
a61af66fc99e Initial load
duke
parents:
diff changeset
48 _is_osr = is_osr;
a61af66fc99e Initial load
duke
parents:
diff changeset
49 _expected_uses = expected_uses;
a61af66fc99e Initial load
duke
parents:
diff changeset
50 assert(can_parse(method, is_osr), "parse must be possible");
a61af66fc99e Initial load
duke
parents:
diff changeset
51 }
a61af66fc99e Initial load
duke
parents:
diff changeset
52
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // Can we build either an OSR or a regular parser for this method?
a61af66fc99e Initial load
duke
parents:
diff changeset
54 static bool can_parse(ciMethod* method, int is_osr = false);
a61af66fc99e Initial load
duke
parents:
diff changeset
55
a61af66fc99e Initial load
duke
parents:
diff changeset
56 virtual bool is_parse() const { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
57 virtual JVMState* generate(JVMState* jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
58 int is_osr() { return _is_osr; }
a61af66fc99e Initial load
duke
parents:
diff changeset
59
a61af66fc99e Initial load
duke
parents:
diff changeset
60 };
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62 JVMState* ParseGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
63 Compile* C = Compile::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 if (is_osr()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 // The JVMS for a OSR has a single argument (see its TypeFunc).
a61af66fc99e Initial load
duke
parents:
diff changeset
67 assert(jvms->depth() == 1, "no inline OSR");
a61af66fc99e Initial load
duke
parents:
diff changeset
68 }
a61af66fc99e Initial load
duke
parents:
diff changeset
69
a61af66fc99e Initial load
duke
parents:
diff changeset
70 if (C->failing()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
71 return NULL; // bailing out of the compile; do not try to parse
a61af66fc99e Initial load
duke
parents:
diff changeset
72 }
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 Parse parser(jvms, method(), _expected_uses);
a61af66fc99e Initial load
duke
parents:
diff changeset
75 // Grab signature for matching/allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
76 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
77 if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
78 MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
79 assert(C->env()->system_dictionary_modification_counter_changed(),
a61af66fc99e Initial load
duke
parents:
diff changeset
80 "Must invalidate if TypeFuncs differ");
a61af66fc99e Initial load
duke
parents:
diff changeset
81 }
a61af66fc99e Initial load
duke
parents:
diff changeset
82 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 GraphKit& exits = parser.exits();
a61af66fc99e Initial load
duke
parents:
diff changeset
85
a61af66fc99e Initial load
duke
parents:
diff changeset
86 if (C->failing()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
87 while (exits.pop_exception_state() != NULL) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
88 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
89 }
a61af66fc99e Initial load
duke
parents:
diff changeset
90
a61af66fc99e Initial load
duke
parents:
diff changeset
91 assert(exits.jvms()->same_calls_as(jvms), "sanity");
a61af66fc99e Initial load
duke
parents:
diff changeset
92
a61af66fc99e Initial load
duke
parents:
diff changeset
93 // Simply return the exit state of the parser,
a61af66fc99e Initial load
duke
parents:
diff changeset
94 // augmented by any exceptional states.
a61af66fc99e Initial load
duke
parents:
diff changeset
95 return exits.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
96 }
a61af66fc99e Initial load
duke
parents:
diff changeset
97
a61af66fc99e Initial load
duke
parents:
diff changeset
98 //---------------------------DirectCallGenerator------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
99 // Internal class which handles all out-of-line calls w/o receiver type checks.
a61af66fc99e Initial load
duke
parents:
diff changeset
100 class DirectCallGenerator : public CallGenerator {
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
101 private:
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
102 CallStaticJavaNode* _call_node;
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
103 // Force separate memory and I/O projections for the exceptional
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
104 // paths to facilitate late inlinig.
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
105 bool _separate_io_proj;
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
106
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
107 public:
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
108 DirectCallGenerator(ciMethod* method, bool separate_io_proj)
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
109 : CallGenerator(method),
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
110 _separate_io_proj(separate_io_proj)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
111 {
a61af66fc99e Initial load
duke
parents:
diff changeset
112 }
a61af66fc99e Initial load
duke
parents:
diff changeset
113 virtual JVMState* generate(JVMState* jvms);
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
114
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
115 CallStaticJavaNode* call_node() const { return _call_node; }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
116 };
a61af66fc99e Initial load
duke
parents:
diff changeset
117
a61af66fc99e Initial load
duke
parents:
diff changeset
118 JVMState* DirectCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
119 GraphKit kit(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
120 bool is_static = method()->is_static();
a61af66fc99e Initial load
duke
parents:
diff changeset
121 address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
a61af66fc99e Initial load
duke
parents:
diff changeset
122 : SharedRuntime::get_resolve_opt_virtual_call_stub();
a61af66fc99e Initial load
duke
parents:
diff changeset
123
a61af66fc99e Initial load
duke
parents:
diff changeset
124 if (kit.C->log() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 kit.C->log()->elem("direct_call bci='%d'", jvms->bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
126 }
a61af66fc99e Initial load
duke
parents:
diff changeset
127
a61af66fc99e Initial load
duke
parents:
diff changeset
128 CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), target, method(), kit.bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
129 if (!is_static) {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // Make an explicit receiver null_check as part of this call.
a61af66fc99e Initial load
duke
parents:
diff changeset
131 // Since we share a map with the caller, his JVMS gets adjusted.
a61af66fc99e Initial load
duke
parents:
diff changeset
132 kit.null_check_receiver(method());
a61af66fc99e Initial load
duke
parents:
diff changeset
133 if (kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
134 // And dump it back to the caller, decorated with any exceptions:
a61af66fc99e Initial load
duke
parents:
diff changeset
135 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // Mark the call node as virtual, sort of:
a61af66fc99e Initial load
duke
parents:
diff changeset
138 call->set_optimized_virtual(true);
1265
b4b440360f1e 6926782: CodeBuffer size too small after 6921352
twisti
parents: 1138
diff changeset
139 if (method()->is_method_handle_invoke()) {
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
140 call->set_method_handle_invoke(true);
1265
b4b440360f1e 6926782: CodeBuffer size too small after 6921352
twisti
parents: 1138
diff changeset
141 kit.C->set_has_method_handle_invokes(true);
b4b440360f1e 6926782: CodeBuffer size too small after 6921352
twisti
parents: 1138
diff changeset
142 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
143 }
a61af66fc99e Initial load
duke
parents:
diff changeset
144 kit.set_arguments_for_java_call(call);
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
145 kit.set_edges_for_java_call(call, false, _separate_io_proj);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
146 Node* ret = kit.set_results_for_java_call(call, _separate_io_proj);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
147 kit.push_node(method()->return_type()->basic_type(), ret);
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
148 _call_node = call; // Save the call node in case we need it later
0
a61af66fc99e Initial load
duke
parents:
diff changeset
149 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
151
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
152 //---------------------------DynamicCallGenerator-----------------------------
1138
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
153 // Internal class which handles all out-of-line invokedynamic calls.
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
154 class DynamicCallGenerator : public CallGenerator {
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
155 public:
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
156 DynamicCallGenerator(ciMethod* method)
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
157 : CallGenerator(method)
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
158 {
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
159 }
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
160 virtual JVMState* generate(JVMState* jvms);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
161 };
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
162
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
163 JVMState* DynamicCallGenerator::generate(JVMState* jvms) {
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
164 GraphKit kit(jvms);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
165
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
166 if (kit.C->log() != NULL) {
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
167 kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci());
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
168 }
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
169
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
170 // Get the constant pool cache from the caller class.
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
171 ciMethod* caller_method = jvms->method();
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
172 ciBytecodeStream str(caller_method);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
173 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
174 assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!");
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
175 ciCPCache* cpcache = str.get_cpcache();
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
176
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
177 // Get the offset of the CallSite from the constant pool cache
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
178 // pointer.
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
179 int index = str.get_method_index();
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
180 size_t call_site_offset = cpcache->get_f1_offset(index);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
181
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
182 // Load the CallSite object from the constant pool cache.
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
183 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
1138
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
184 Node* cpcache_adr = kit.makecon(cpcache_ptr);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
185 Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
186 Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
187
1138
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
188 // Load the target MethodHandle from the CallSite object.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
189 Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
190 Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT);
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
191
1138
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
192 address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub();
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
193
1138
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
194 CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci());
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
195 // invokedynamic is treated as an optimized invokevirtual.
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
196 call->set_optimized_virtual(true);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
197 // Take extra care (in the presence of argument motion) not to trash the SP:
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
198 call->set_method_handle_invoke(true);
1265
b4b440360f1e 6926782: CodeBuffer size too small after 6921352
twisti
parents: 1138
diff changeset
199 kit.C->set_has_method_handle_invokes(true);
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
200
1138
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
201 // Pass the target MethodHandle as first argument and shift the
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
202 // other arguments.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
203 call->init_req(0 + TypeFunc::Parms, target_mh);
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
204 uint nargs = call->method()->arg_size();
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
205 for (uint i = 1; i < nargs; i++) {
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
206 Node* arg = kit.argument(i - 1);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
207 call->init_req(i + TypeFunc::Parms, arg);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
208 }
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
209
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
210 kit.set_edges_for_java_call(call);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
211 Node* ret = kit.set_results_for_java_call(call);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
212 kit.push_node(method()->return_type()->basic_type(), ret);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
213 return kit.transfer_exceptions_into_jvms();
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
214 }
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
215
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
216 //--------------------------VirtualCallGenerator------------------------------
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
217 // Internal class which handles all out-of-line calls checking receiver type.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
218 class VirtualCallGenerator : public CallGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
219 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
220 int _vtable_index;
a61af66fc99e Initial load
duke
parents:
diff changeset
221 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
222 VirtualCallGenerator(ciMethod* method, int vtable_index)
a61af66fc99e Initial load
duke
parents:
diff changeset
223 : CallGenerator(method), _vtable_index(vtable_index)
a61af66fc99e Initial load
duke
parents:
diff changeset
224 {
a61af66fc99e Initial load
duke
parents:
diff changeset
225 assert(vtable_index == methodOopDesc::invalid_vtable_index ||
a61af66fc99e Initial load
duke
parents:
diff changeset
226 vtable_index >= 0, "either invalid or usable");
a61af66fc99e Initial load
duke
parents:
diff changeset
227 }
a61af66fc99e Initial load
duke
parents:
diff changeset
228 virtual bool is_virtual() const { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
229 virtual JVMState* generate(JVMState* jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
230 };
a61af66fc99e Initial load
duke
parents:
diff changeset
231
a61af66fc99e Initial load
duke
parents:
diff changeset
232 JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
233 GraphKit kit(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
234 Node* receiver = kit.argument(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
235
a61af66fc99e Initial load
duke
parents:
diff changeset
236 if (kit.C->log() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
237 kit.C->log()->elem("virtual_call bci='%d'", jvms->bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
239
a61af66fc99e Initial load
duke
parents:
diff changeset
240 // If the receiver is a constant null, do not torture the system
a61af66fc99e Initial load
duke
parents:
diff changeset
241 // by attempting to call through it. The compile will proceed
a61af66fc99e Initial load
duke
parents:
diff changeset
242 // correctly, but may bail out in final_graph_reshaping, because
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // the call instruction will have a seemingly deficient out-count.
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // (The bailout says something misleading about an "infinite loop".)
a61af66fc99e Initial load
duke
parents:
diff changeset
245 if (kit.gvn().type(receiver)->higher_equal(TypePtr::NULL_PTR)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
246 kit.inc_sp(method()->arg_size()); // restore arguments
a61af66fc99e Initial load
duke
parents:
diff changeset
247 kit.uncommon_trap(Deoptimization::Reason_null_check,
a61af66fc99e Initial load
duke
parents:
diff changeset
248 Deoptimization::Action_none,
a61af66fc99e Initial load
duke
parents:
diff changeset
249 NULL, "null receiver");
a61af66fc99e Initial load
duke
parents:
diff changeset
250 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
252
a61af66fc99e Initial load
duke
parents:
diff changeset
253 // Ideally we would unconditionally do a null check here and let it
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // be converted to an implicit check based on profile information.
a61af66fc99e Initial load
duke
parents:
diff changeset
255 // However currently the conversion to implicit null checks in
a61af66fc99e Initial load
duke
parents:
diff changeset
256 // Block::implicit_null_check() only looks for loads and stores, not calls.
a61af66fc99e Initial load
duke
parents:
diff changeset
257 ciMethod *caller = kit.method();
a61af66fc99e Initial load
duke
parents:
diff changeset
258 ciMethodData *caller_md = (caller == NULL) ? NULL : caller->method_data();
a61af66fc99e Initial load
duke
parents:
diff changeset
259 if (!UseInlineCaches || !ImplicitNullChecks ||
a61af66fc99e Initial load
duke
parents:
diff changeset
260 ((ImplicitNullCheckThreshold > 0) && caller_md &&
a61af66fc99e Initial load
duke
parents:
diff changeset
261 (caller_md->trap_count(Deoptimization::Reason_null_check)
a61af66fc99e Initial load
duke
parents:
diff changeset
262 >= (uint)ImplicitNullCheckThreshold))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
263 // Make an explicit receiver null_check as part of this call.
a61af66fc99e Initial load
duke
parents:
diff changeset
264 // Since we share a map with the caller, his JVMS gets adjusted.
a61af66fc99e Initial load
duke
parents:
diff changeset
265 receiver = kit.null_check_receiver(method());
a61af66fc99e Initial load
duke
parents:
diff changeset
266 if (kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 // And dump it back to the caller, decorated with any exceptions:
a61af66fc99e Initial load
duke
parents:
diff changeset
268 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
269 }
a61af66fc99e Initial load
duke
parents:
diff changeset
270 }
a61af66fc99e Initial load
duke
parents:
diff changeset
271
a61af66fc99e Initial load
duke
parents:
diff changeset
272 assert(!method()->is_static(), "virtual call must not be to static");
a61af66fc99e Initial load
duke
parents:
diff changeset
273 assert(!method()->is_final(), "virtual call should not be to final");
a61af66fc99e Initial load
duke
parents:
diff changeset
274 assert(!method()->is_private(), "virtual call should not be to private");
a61af66fc99e Initial load
duke
parents:
diff changeset
275 assert(_vtable_index == methodOopDesc::invalid_vtable_index || !UseInlineCaches,
a61af66fc99e Initial load
duke
parents:
diff changeset
276 "no vtable calls if +UseInlineCaches ");
a61af66fc99e Initial load
duke
parents:
diff changeset
277 address target = SharedRuntime::get_resolve_virtual_call_stub();
a61af66fc99e Initial load
duke
parents:
diff changeset
278 // Normal inline cache used for call
a61af66fc99e Initial load
duke
parents:
diff changeset
279 CallDynamicJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallDynamicJavaNode(tf(), target, method(), _vtable_index, kit.bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
280 kit.set_arguments_for_java_call(call);
a61af66fc99e Initial load
duke
parents:
diff changeset
281 kit.set_edges_for_java_call(call);
a61af66fc99e Initial load
duke
parents:
diff changeset
282 Node* ret = kit.set_results_for_java_call(call);
a61af66fc99e Initial load
duke
parents:
diff changeset
283 kit.push_node(method()->return_type()->basic_type(), ret);
a61af66fc99e Initial load
duke
parents:
diff changeset
284
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // Represent the effect of an implicit receiver null_check
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // as part of this call. Since we share a map with the caller,
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // his JVMS gets adjusted.
a61af66fc99e Initial load
duke
parents:
diff changeset
288 kit.cast_not_null(receiver);
a61af66fc99e Initial load
duke
parents:
diff changeset
289 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 bool ParseGenerator::can_parse(ciMethod* m, int entry_bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
293 // Certain methods cannot be parsed at all:
a61af66fc99e Initial load
duke
parents:
diff changeset
294 if (!m->can_be_compiled()) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
295 if (!m->has_balanced_monitors()) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
296 if (m->get_flow_analysis()->failing()) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
297
a61af66fc99e Initial load
duke
parents:
diff changeset
298 // (Methods may bail out for other reasons, after the parser is run.
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // We try to avoid this, but if forced, we must return (Node*)NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // The user of the CallGenerator must check for this condition.)
a61af66fc99e Initial load
duke
parents:
diff changeset
301 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
302 }
a61af66fc99e Initial load
duke
parents:
diff changeset
303
a61af66fc99e Initial load
duke
parents:
diff changeset
304 CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) {
a61af66fc99e Initial load
duke
parents:
diff changeset
305 if (!ParseGenerator::can_parse(m)) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
306 return new ParseGenerator(m, expected_uses);
a61af66fc99e Initial load
duke
parents:
diff changeset
307 }
a61af66fc99e Initial load
duke
parents:
diff changeset
308
a61af66fc99e Initial load
duke
parents:
diff changeset
309 // As a special case, the JVMS passed to this CallGenerator is
a61af66fc99e Initial load
duke
parents:
diff changeset
310 // for the method execution already in progress, not just the JVMS
a61af66fc99e Initial load
duke
parents:
diff changeset
311 // of the caller. Thus, this CallGenerator cannot be mixed with others!
a61af66fc99e Initial load
duke
parents:
diff changeset
312 CallGenerator* CallGenerator::for_osr(ciMethod* m, int osr_bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
313 if (!ParseGenerator::can_parse(m, true)) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
314 float past_uses = m->interpreter_invocation_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
315 float expected_uses = past_uses;
a61af66fc99e Initial load
duke
parents:
diff changeset
316 return new ParseGenerator(m, expected_uses, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
318
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
319 CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
320 assert(!m->is_abstract(), "for_direct_call mismatch");
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
321 return new DirectCallGenerator(m, separate_io_proj);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
322 }
a61af66fc99e Initial load
duke
parents:
diff changeset
323
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
324 CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) {
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
325 assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch");
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
326 return new DynamicCallGenerator(m);
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
327 }
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
328
0
a61af66fc99e Initial load
duke
parents:
diff changeset
329 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
330 assert(!m->is_static(), "for_virtual_call mismatch");
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
331 assert(!m->is_method_handle_invoke(), "should be a direct call");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
332 return new VirtualCallGenerator(m, vtable_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
333 }
a61af66fc99e Initial load
duke
parents:
diff changeset
334
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
335 // Allow inlining decisions to be delayed
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
336 class LateInlineCallGenerator : public DirectCallGenerator {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
337 CallGenerator* _inline_cg;
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
338
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
339 public:
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
340 LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
341 DirectCallGenerator(method, true), _inline_cg(inline_cg) {}
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
342
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
343 virtual bool is_late_inline() const { return true; }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
344
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
345 // Convert the CallStaticJava into an inline
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
346 virtual void do_late_inline();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
347
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
348 JVMState* generate(JVMState* jvms) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
349 // Record that this call site should be revisited once the main
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
350 // parse is finished.
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
351 Compile::current()->add_late_inline(this);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
352
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
353 // Emit the CallStaticJava and request separate projections so
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
354 // that the late inlining logic can distinguish between fall
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
355 // through and exceptional uses of the memory and io projections
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
356 // as is done for allocations and macro expansion.
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
357 return DirectCallGenerator::generate(jvms);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
358 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
359
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
360 };
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
361
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
362
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
363 void LateInlineCallGenerator::do_late_inline() {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
364 // Can't inline it
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
365 if (call_node() == NULL || call_node()->outcnt() == 0 ||
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
366 call_node()->in(0) == NULL || call_node()->in(0)->is_top())
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
367 return;
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
368
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
369 CallStaticJavaNode* call = call_node();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
370
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
371 // Make a clone of the JVMState that appropriate to use for driving a parse
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
372 Compile* C = Compile::current();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
373 JVMState* jvms = call->jvms()->clone_shallow(C);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
374 uint size = call->req();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
375 SafePointNode* map = new (C, size) SafePointNode(size, jvms);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
376 for (uint i1 = 0; i1 < size; i1++) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
377 map->init_req(i1, call->in(i1));
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
378 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
379
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
380 // Make sure the state is a MergeMem for parsing.
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
381 if (!map->in(TypeFunc::Memory)->is_MergeMem()) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
382 map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory)));
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
383 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
384
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
385 // Make enough space for the expression stack and transfer the incoming arguments
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
386 int nargs = method()->arg_size();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
387 jvms->set_map(map);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
388 map->ensure_stack(jvms, jvms->method()->max_stack());
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
389 if (nargs > 0) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
390 for (int i1 = 0; i1 < nargs; i1++) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
391 map->set_req(i1 + jvms->argoff(), call->in(TypeFunc::Parms + i1));
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
392 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
393 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
394
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
395 CompileLog* log = C->log();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
396 if (log != NULL) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
397 log->head("late_inline method='%d'", log->identify(method()));
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
398 JVMState* p = jvms;
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
399 while (p != NULL) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
400 log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
401 p = p->caller();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
402 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
403 log->tail("late_inline");
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
404 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
405
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
406 // Setup default node notes to be picked up by the inlining
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
407 Node_Notes* old_nn = C->default_node_notes();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
408 if (old_nn != NULL) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
409 Node_Notes* entry_nn = old_nn->clone(C);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
410 entry_nn->set_jvms(jvms);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
411 C->set_default_node_notes(entry_nn);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
412 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
413
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
414 // Now perform the inling using the synthesized JVMState
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
415 JVMState* new_jvms = _inline_cg->generate(jvms);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
416 if (new_jvms == NULL) return; // no change
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
417 if (C->failing()) return;
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
418
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
419 // Capture any exceptional control flow
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
420 GraphKit kit(new_jvms);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
421
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
422 // Find the result object
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
423 Node* result = C->top();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
424 int result_size = method()->return_type()->size();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
425 if (result_size != 0 && !kit.stopped()) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
426 result = (result_size == 1) ? kit.pop() : kit.pop_pair();
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
427 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
428
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
429 kit.replace_call(call, result);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
430 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
431
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
432
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
433 CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) {
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
434 return new LateInlineCallGenerator(method, inline_cg);
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
435 }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
436
0
a61af66fc99e Initial load
duke
parents:
diff changeset
437
a61af66fc99e Initial load
duke
parents:
diff changeset
438 //---------------------------WarmCallGenerator--------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
439 // Internal class which handles initial deferral of inlining decisions.
a61af66fc99e Initial load
duke
parents:
diff changeset
440 class WarmCallGenerator : public CallGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
441 WarmCallInfo* _call_info;
a61af66fc99e Initial load
duke
parents:
diff changeset
442 CallGenerator* _if_cold;
a61af66fc99e Initial load
duke
parents:
diff changeset
443 CallGenerator* _if_hot;
a61af66fc99e Initial load
duke
parents:
diff changeset
444 bool _is_virtual; // caches virtuality of if_cold
a61af66fc99e Initial load
duke
parents:
diff changeset
445 bool _is_inline; // caches inline-ness of if_hot
a61af66fc99e Initial load
duke
parents:
diff changeset
446
a61af66fc99e Initial load
duke
parents:
diff changeset
447 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
448 WarmCallGenerator(WarmCallInfo* ci,
a61af66fc99e Initial load
duke
parents:
diff changeset
449 CallGenerator* if_cold,
a61af66fc99e Initial load
duke
parents:
diff changeset
450 CallGenerator* if_hot)
a61af66fc99e Initial load
duke
parents:
diff changeset
451 : CallGenerator(if_cold->method())
a61af66fc99e Initial load
duke
parents:
diff changeset
452 {
a61af66fc99e Initial load
duke
parents:
diff changeset
453 assert(method() == if_hot->method(), "consistent choices");
a61af66fc99e Initial load
duke
parents:
diff changeset
454 _call_info = ci;
a61af66fc99e Initial load
duke
parents:
diff changeset
455 _if_cold = if_cold;
a61af66fc99e Initial load
duke
parents:
diff changeset
456 _if_hot = if_hot;
a61af66fc99e Initial load
duke
parents:
diff changeset
457 _is_virtual = if_cold->is_virtual();
a61af66fc99e Initial load
duke
parents:
diff changeset
458 _is_inline = if_hot->is_inline();
a61af66fc99e Initial load
duke
parents:
diff changeset
459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
460
a61af66fc99e Initial load
duke
parents:
diff changeset
461 virtual bool is_inline() const { return _is_inline; }
a61af66fc99e Initial load
duke
parents:
diff changeset
462 virtual bool is_virtual() const { return _is_virtual; }
a61af66fc99e Initial load
duke
parents:
diff changeset
463 virtual bool is_deferred() const { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
464
a61af66fc99e Initial load
duke
parents:
diff changeset
465 virtual JVMState* generate(JVMState* jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
466 };
a61af66fc99e Initial load
duke
parents:
diff changeset
467
a61af66fc99e Initial load
duke
parents:
diff changeset
468
a61af66fc99e Initial load
duke
parents:
diff changeset
469 CallGenerator* CallGenerator::for_warm_call(WarmCallInfo* ci,
a61af66fc99e Initial load
duke
parents:
diff changeset
470 CallGenerator* if_cold,
a61af66fc99e Initial load
duke
parents:
diff changeset
471 CallGenerator* if_hot) {
a61af66fc99e Initial load
duke
parents:
diff changeset
472 return new WarmCallGenerator(ci, if_cold, if_hot);
a61af66fc99e Initial load
duke
parents:
diff changeset
473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
474
a61af66fc99e Initial load
duke
parents:
diff changeset
475 JVMState* WarmCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
476 Compile* C = Compile::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
477 if (C->log() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
478 C->log()->elem("warm_call bci='%d'", jvms->bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
480 jvms = _if_cold->generate(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
481 if (jvms != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
482 Node* m = jvms->map()->control();
a61af66fc99e Initial load
duke
parents:
diff changeset
483 if (m->is_CatchProj()) m = m->in(0); else m = C->top();
a61af66fc99e Initial load
duke
parents:
diff changeset
484 if (m->is_Catch()) m = m->in(0); else m = C->top();
a61af66fc99e Initial load
duke
parents:
diff changeset
485 if (m->is_Proj()) m = m->in(0); else m = C->top();
a61af66fc99e Initial load
duke
parents:
diff changeset
486 if (m->is_CallJava()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
487 _call_info->set_call(m->as_Call());
a61af66fc99e Initial load
duke
parents:
diff changeset
488 _call_info->set_hot_cg(_if_hot);
a61af66fc99e Initial load
duke
parents:
diff changeset
489 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
490 if (PrintOpto || PrintOptoInlining) {
a61af66fc99e Initial load
duke
parents:
diff changeset
491 tty->print_cr("Queueing for warm inlining at bci %d:", jvms->bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
492 tty->print("WCI: ");
a61af66fc99e Initial load
duke
parents:
diff changeset
493 _call_info->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
494 }
a61af66fc99e Initial load
duke
parents:
diff changeset
495 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
496 _call_info->set_heat(_call_info->compute_heat());
a61af66fc99e Initial load
duke
parents:
diff changeset
497 C->set_warm_calls(_call_info->insert_into(C->warm_calls()));
a61af66fc99e Initial load
duke
parents:
diff changeset
498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
499 }
a61af66fc99e Initial load
duke
parents:
diff changeset
500 return jvms;
a61af66fc99e Initial load
duke
parents:
diff changeset
501 }
a61af66fc99e Initial load
duke
parents:
diff changeset
502
a61af66fc99e Initial load
duke
parents:
diff changeset
503 void WarmCallInfo::make_hot() {
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 337
diff changeset
504 Unimplemented();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
505 }
a61af66fc99e Initial load
duke
parents:
diff changeset
506
a61af66fc99e Initial load
duke
parents:
diff changeset
507 void WarmCallInfo::make_cold() {
a61af66fc99e Initial load
duke
parents:
diff changeset
508 // No action: Just dequeue.
a61af66fc99e Initial load
duke
parents:
diff changeset
509 }
a61af66fc99e Initial load
duke
parents:
diff changeset
510
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 //------------------------PredictedCallGenerator------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
513 // Internal class which handles all out-of-line calls checking receiver type.
a61af66fc99e Initial load
duke
parents:
diff changeset
514 class PredictedCallGenerator : public CallGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
515 ciKlass* _predicted_receiver;
a61af66fc99e Initial load
duke
parents:
diff changeset
516 CallGenerator* _if_missed;
a61af66fc99e Initial load
duke
parents:
diff changeset
517 CallGenerator* _if_hit;
a61af66fc99e Initial load
duke
parents:
diff changeset
518 float _hit_prob;
a61af66fc99e Initial load
duke
parents:
diff changeset
519
a61af66fc99e Initial load
duke
parents:
diff changeset
520 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
521 PredictedCallGenerator(ciKlass* predicted_receiver,
a61af66fc99e Initial load
duke
parents:
diff changeset
522 CallGenerator* if_missed,
a61af66fc99e Initial load
duke
parents:
diff changeset
523 CallGenerator* if_hit, float hit_prob)
a61af66fc99e Initial load
duke
parents:
diff changeset
524 : CallGenerator(if_missed->method())
a61af66fc99e Initial load
duke
parents:
diff changeset
525 {
a61af66fc99e Initial load
duke
parents:
diff changeset
526 // The call profile data may predict the hit_prob as extreme as 0 or 1.
a61af66fc99e Initial load
duke
parents:
diff changeset
527 // Remove the extremes values from the range.
a61af66fc99e Initial load
duke
parents:
diff changeset
528 if (hit_prob > PROB_MAX) hit_prob = PROB_MAX;
a61af66fc99e Initial load
duke
parents:
diff changeset
529 if (hit_prob < PROB_MIN) hit_prob = PROB_MIN;
a61af66fc99e Initial load
duke
parents:
diff changeset
530
a61af66fc99e Initial load
duke
parents:
diff changeset
531 _predicted_receiver = predicted_receiver;
a61af66fc99e Initial load
duke
parents:
diff changeset
532 _if_missed = if_missed;
a61af66fc99e Initial load
duke
parents:
diff changeset
533 _if_hit = if_hit;
a61af66fc99e Initial load
duke
parents:
diff changeset
534 _hit_prob = hit_prob;
a61af66fc99e Initial load
duke
parents:
diff changeset
535 }
a61af66fc99e Initial load
duke
parents:
diff changeset
536
a61af66fc99e Initial load
duke
parents:
diff changeset
537 virtual bool is_virtual() const { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
538 virtual bool is_inline() const { return _if_hit->is_inline(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
539 virtual bool is_deferred() const { return _if_hit->is_deferred(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
540
a61af66fc99e Initial load
duke
parents:
diff changeset
541 virtual JVMState* generate(JVMState* jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
542 };
a61af66fc99e Initial load
duke
parents:
diff changeset
543
a61af66fc99e Initial load
duke
parents:
diff changeset
544
a61af66fc99e Initial load
duke
parents:
diff changeset
545 CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver,
a61af66fc99e Initial load
duke
parents:
diff changeset
546 CallGenerator* if_missed,
a61af66fc99e Initial load
duke
parents:
diff changeset
547 CallGenerator* if_hit,
a61af66fc99e Initial load
duke
parents:
diff changeset
548 float hit_prob) {
a61af66fc99e Initial load
duke
parents:
diff changeset
549 return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, hit_prob);
a61af66fc99e Initial load
duke
parents:
diff changeset
550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
551
a61af66fc99e Initial load
duke
parents:
diff changeset
552
a61af66fc99e Initial load
duke
parents:
diff changeset
553 JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
554 GraphKit kit(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
555 PhaseGVN& gvn = kit.gvn();
a61af66fc99e Initial load
duke
parents:
diff changeset
556 // We need an explicit receiver null_check before checking its type.
a61af66fc99e Initial load
duke
parents:
diff changeset
557 // We share a map with the caller, so his JVMS gets adjusted.
a61af66fc99e Initial load
duke
parents:
diff changeset
558 Node* receiver = kit.argument(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
559
a61af66fc99e Initial load
duke
parents:
diff changeset
560 CompileLog* log = kit.C->log();
a61af66fc99e Initial load
duke
parents:
diff changeset
561 if (log != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
562 log->elem("predicted_call bci='%d' klass='%d'",
a61af66fc99e Initial load
duke
parents:
diff changeset
563 jvms->bci(), log->identify(_predicted_receiver));
a61af66fc99e Initial load
duke
parents:
diff changeset
564 }
a61af66fc99e Initial load
duke
parents:
diff changeset
565
a61af66fc99e Initial load
duke
parents:
diff changeset
566 receiver = kit.null_check_receiver(method());
a61af66fc99e Initial load
duke
parents:
diff changeset
567 if (kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
568 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
569 }
a61af66fc99e Initial load
duke
parents:
diff changeset
570
a61af66fc99e Initial load
duke
parents:
diff changeset
571 Node* exact_receiver = receiver; // will get updated in place...
a61af66fc99e Initial load
duke
parents:
diff changeset
572 Node* slow_ctl = kit.type_check_receiver(receiver,
a61af66fc99e Initial load
duke
parents:
diff changeset
573 _predicted_receiver, _hit_prob,
a61af66fc99e Initial load
duke
parents:
diff changeset
574 &exact_receiver);
a61af66fc99e Initial load
duke
parents:
diff changeset
575
a61af66fc99e Initial load
duke
parents:
diff changeset
576 SafePointNode* slow_map = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
577 JVMState* slow_jvms;
a61af66fc99e Initial load
duke
parents:
diff changeset
578 { PreserveJVMState pjvms(&kit);
a61af66fc99e Initial load
duke
parents:
diff changeset
579 kit.set_control(slow_ctl);
a61af66fc99e Initial load
duke
parents:
diff changeset
580 if (!kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
581 slow_jvms = _if_missed->generate(kit.sync_jvms());
a61af66fc99e Initial load
duke
parents:
diff changeset
582 assert(slow_jvms != NULL, "miss path must not fail to generate");
a61af66fc99e Initial load
duke
parents:
diff changeset
583 kit.add_exception_states_from(slow_jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
584 kit.set_map(slow_jvms->map());
a61af66fc99e Initial load
duke
parents:
diff changeset
585 if (!kit.stopped())
a61af66fc99e Initial load
duke
parents:
diff changeset
586 slow_map = kit.stop();
a61af66fc99e Initial load
duke
parents:
diff changeset
587 }
a61af66fc99e Initial load
duke
parents:
diff changeset
588 }
a61af66fc99e Initial load
duke
parents:
diff changeset
589
293
c3e045194476 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents: 0
diff changeset
590 if (kit.stopped()) {
c3e045194476 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents: 0
diff changeset
591 // Instance exactly does not matches the desired type.
c3e045194476 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents: 0
diff changeset
592 kit.set_jvms(slow_jvms);
c3e045194476 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents: 0
diff changeset
593 return kit.transfer_exceptions_into_jvms();
c3e045194476 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents: 0
diff changeset
594 }
c3e045194476 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents: 0
diff changeset
595
0
a61af66fc99e Initial load
duke
parents:
diff changeset
596 // fall through if the instance exactly matches the desired type
a61af66fc99e Initial load
duke
parents:
diff changeset
597 kit.replace_in_map(receiver, exact_receiver);
a61af66fc99e Initial load
duke
parents:
diff changeset
598
a61af66fc99e Initial load
duke
parents:
diff changeset
599 // Make the hot call:
a61af66fc99e Initial load
duke
parents:
diff changeset
600 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
a61af66fc99e Initial load
duke
parents:
diff changeset
601 if (new_jvms == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
602 // Inline failed, so make a direct call.
a61af66fc99e Initial load
duke
parents:
diff changeset
603 assert(_if_hit->is_inline(), "must have been a failed inline");
a61af66fc99e Initial load
duke
parents:
diff changeset
604 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
a61af66fc99e Initial load
duke
parents:
diff changeset
605 new_jvms = cg->generate(kit.sync_jvms());
a61af66fc99e Initial load
duke
parents:
diff changeset
606 }
a61af66fc99e Initial load
duke
parents:
diff changeset
607 kit.add_exception_states_from(new_jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
608 kit.set_jvms(new_jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
609
a61af66fc99e Initial load
duke
parents:
diff changeset
610 // Need to merge slow and fast?
a61af66fc99e Initial load
duke
parents:
diff changeset
611 if (slow_map == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
612 // The fast path is the only path remaining.
a61af66fc99e Initial load
duke
parents:
diff changeset
613 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
614 }
a61af66fc99e Initial load
duke
parents:
diff changeset
615
a61af66fc99e Initial load
duke
parents:
diff changeset
616 if (kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
617 // Inlined method threw an exception, so it's just the slow path after all.
a61af66fc99e Initial load
duke
parents:
diff changeset
618 kit.set_jvms(slow_jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
619 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
621
a61af66fc99e Initial load
duke
parents:
diff changeset
622 // Finish the diamond.
a61af66fc99e Initial load
duke
parents:
diff changeset
623 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
624 RegionNode* region = new (kit.C, 3) RegionNode(3);
a61af66fc99e Initial load
duke
parents:
diff changeset
625 region->init_req(1, kit.control());
a61af66fc99e Initial load
duke
parents:
diff changeset
626 region->init_req(2, slow_map->control());
a61af66fc99e Initial load
duke
parents:
diff changeset
627 kit.set_control(gvn.transform(region));
a61af66fc99e Initial load
duke
parents:
diff changeset
628 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
a61af66fc99e Initial load
duke
parents:
diff changeset
629 iophi->set_req(2, slow_map->i_o());
a61af66fc99e Initial load
duke
parents:
diff changeset
630 kit.set_i_o(gvn.transform(iophi));
a61af66fc99e Initial load
duke
parents:
diff changeset
631 kit.merge_memory(slow_map->merged_memory(), region, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
632 uint tos = kit.jvms()->stkoff() + kit.sp();
a61af66fc99e Initial load
duke
parents:
diff changeset
633 uint limit = slow_map->req();
a61af66fc99e Initial load
duke
parents:
diff changeset
634 for (uint i = TypeFunc::Parms; i < limit; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
635 // Skip unused stack slots; fast forward to monoff();
a61af66fc99e Initial load
duke
parents:
diff changeset
636 if (i == tos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
637 i = kit.jvms()->monoff();
a61af66fc99e Initial load
duke
parents:
diff changeset
638 if( i >= limit ) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
640 Node* m = kit.map()->in(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
641 Node* n = slow_map->in(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
642 if (m != n) {
a61af66fc99e Initial load
duke
parents:
diff changeset
643 const Type* t = gvn.type(m)->meet(gvn.type(n));
a61af66fc99e Initial load
duke
parents:
diff changeset
644 Node* phi = PhiNode::make(region, m, t);
a61af66fc99e Initial load
duke
parents:
diff changeset
645 phi->set_req(2, n);
a61af66fc99e Initial load
duke
parents:
diff changeset
646 kit.map()->set_req(i, gvn.transform(phi));
a61af66fc99e Initial load
duke
parents:
diff changeset
647 }
a61af66fc99e Initial load
duke
parents:
diff changeset
648 }
a61af66fc99e Initial load
duke
parents:
diff changeset
649 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
650 }
a61af66fc99e Initial load
duke
parents:
diff changeset
651
a61af66fc99e Initial load
duke
parents:
diff changeset
652
1138
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
653 //------------------------PredictedDynamicCallGenerator-----------------------
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
654 // Internal class which handles all out-of-line calls checking receiver type.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
655 class PredictedDynamicCallGenerator : public CallGenerator {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
656 ciMethodHandle* _predicted_method_handle;
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
657 CallGenerator* _if_missed;
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
658 CallGenerator* _if_hit;
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
659 float _hit_prob;
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
660
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
661 public:
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
662 PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
663 CallGenerator* if_missed,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
664 CallGenerator* if_hit,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
665 float hit_prob)
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
666 : CallGenerator(if_missed->method()),
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
667 _predicted_method_handle(predicted_method_handle),
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
668 _if_missed(if_missed),
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
669 _if_hit(if_hit),
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
670 _hit_prob(hit_prob)
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
671 {}
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
672
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
673 virtual bool is_inline() const { return _if_hit->is_inline(); }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
674 virtual bool is_deferred() const { return _if_hit->is_deferred(); }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
675
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
676 virtual JVMState* generate(JVMState* jvms);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
677 };
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
678
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
679
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
680 CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
681 CallGenerator* if_missed,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
682 CallGenerator* if_hit,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
683 float hit_prob) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
684 return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
685 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
686
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
687
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
688 JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
689 GraphKit kit(jvms);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
690 PhaseGVN& gvn = kit.gvn();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
691
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
692 CompileLog* log = kit.C->log();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
693 if (log != NULL) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
694 log->elem("predicted_dynamic_call bci='%d'", jvms->bci());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
695 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
696
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
697 // Get the constant pool cache from the caller class.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
698 ciMethod* caller_method = jvms->method();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
699 ciBytecodeStream str(caller_method);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
700 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
701 ciCPCache* cpcache = str.get_cpcache();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
702
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
703 // Get the offset of the CallSite from the constant pool cache
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
704 // pointer.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
705 int index = str.get_method_index();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
706 size_t call_site_offset = cpcache->get_f1_offset(index);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
707
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
708 // Load the CallSite object from the constant pool cache.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
709 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
710 Node* cpcache_adr = kit.makecon(cpcache_ptr);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
711 Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
712 Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
713
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
714 // Load the target MethodHandle from the CallSite object.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
715 Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
716 Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
717
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
718 // Check if the MethodHandle is still the same.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
719 const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
720 Node* predicted_mh = kit.makecon(predicted_mh_ptr);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
721
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
722 Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh));
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
723 Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
724 IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
725 kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff)));
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
726 Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff));
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
727
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
728 SafePointNode* slow_map = NULL;
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
729 JVMState* slow_jvms;
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
730 { PreserveJVMState pjvms(&kit);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
731 kit.set_control(slow_ctl);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
732 if (!kit.stopped()) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
733 slow_jvms = _if_missed->generate(kit.sync_jvms());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
734 assert(slow_jvms != NULL, "miss path must not fail to generate");
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
735 kit.add_exception_states_from(slow_jvms);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
736 kit.set_map(slow_jvms->map());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
737 if (!kit.stopped())
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
738 slow_map = kit.stop();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
739 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
740 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
741
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
742 if (kit.stopped()) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
743 // Instance exactly does not matches the desired type.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
744 kit.set_jvms(slow_jvms);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
745 return kit.transfer_exceptions_into_jvms();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
746 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
747
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
748 // Make the hot call:
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
749 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
750 if (new_jvms == NULL) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
751 // Inline failed, so make a direct call.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
752 assert(_if_hit->is_inline(), "must have been a failed inline");
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
753 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
754 new_jvms = cg->generate(kit.sync_jvms());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
755 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
756 kit.add_exception_states_from(new_jvms);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
757 kit.set_jvms(new_jvms);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
758
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
759 // Need to merge slow and fast?
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
760 if (slow_map == NULL) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
761 // The fast path is the only path remaining.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
762 return kit.transfer_exceptions_into_jvms();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
763 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
764
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
765 if (kit.stopped()) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
766 // Inlined method threw an exception, so it's just the slow path after all.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
767 kit.set_jvms(slow_jvms);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
768 return kit.transfer_exceptions_into_jvms();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
769 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
770
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
771 // Finish the diamond.
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
772 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
773 RegionNode* region = new (kit.C, 3) RegionNode(3);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
774 region->init_req(1, kit.control());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
775 region->init_req(2, slow_map->control());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
776 kit.set_control(gvn.transform(region));
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
777 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
778 iophi->set_req(2, slow_map->i_o());
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
779 kit.set_i_o(gvn.transform(iophi));
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
780 kit.merge_memory(slow_map->merged_memory(), region, 2);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
781 uint tos = kit.jvms()->stkoff() + kit.sp();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
782 uint limit = slow_map->req();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
783 for (uint i = TypeFunc::Parms; i < limit; i++) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
784 // Skip unused stack slots; fast forward to monoff();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
785 if (i == tos) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
786 i = kit.jvms()->monoff();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
787 if( i >= limit ) break;
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
788 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
789 Node* m = kit.map()->in(i);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
790 Node* n = slow_map->in(i);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
791 if (m != n) {
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
792 const Type* t = gvn.type(m)->meet(gvn.type(n));
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
793 Node* phi = PhiNode::make(region, m, t);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
794 phi->set_req(2, n);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
795 kit.map()->set_req(i, gvn.transform(phi));
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
796 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
797 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
798 return kit.transfer_exceptions_into_jvms();
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
799 }
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
800
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
801
0
a61af66fc99e Initial load
duke
parents:
diff changeset
802 //-------------------------UncommonTrapCallGenerator-----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
803 // Internal class which handles all out-of-line calls checking receiver type.
a61af66fc99e Initial load
duke
parents:
diff changeset
804 class UncommonTrapCallGenerator : public CallGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
805 Deoptimization::DeoptReason _reason;
a61af66fc99e Initial load
duke
parents:
diff changeset
806 Deoptimization::DeoptAction _action;
a61af66fc99e Initial load
duke
parents:
diff changeset
807
a61af66fc99e Initial load
duke
parents:
diff changeset
808 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
809 UncommonTrapCallGenerator(ciMethod* m,
a61af66fc99e Initial load
duke
parents:
diff changeset
810 Deoptimization::DeoptReason reason,
a61af66fc99e Initial load
duke
parents:
diff changeset
811 Deoptimization::DeoptAction action)
a61af66fc99e Initial load
duke
parents:
diff changeset
812 : CallGenerator(m)
a61af66fc99e Initial load
duke
parents:
diff changeset
813 {
a61af66fc99e Initial load
duke
parents:
diff changeset
814 _reason = reason;
a61af66fc99e Initial load
duke
parents:
diff changeset
815 _action = action;
a61af66fc99e Initial load
duke
parents:
diff changeset
816 }
a61af66fc99e Initial load
duke
parents:
diff changeset
817
a61af66fc99e Initial load
duke
parents:
diff changeset
818 virtual bool is_virtual() const { ShouldNotReachHere(); return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
819 virtual bool is_trap() const { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
820
a61af66fc99e Initial load
duke
parents:
diff changeset
821 virtual JVMState* generate(JVMState* jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
822 };
a61af66fc99e Initial load
duke
parents:
diff changeset
823
a61af66fc99e Initial load
duke
parents:
diff changeset
824
a61af66fc99e Initial load
duke
parents:
diff changeset
825 CallGenerator*
a61af66fc99e Initial load
duke
parents:
diff changeset
826 CallGenerator::for_uncommon_trap(ciMethod* m,
a61af66fc99e Initial load
duke
parents:
diff changeset
827 Deoptimization::DeoptReason reason,
a61af66fc99e Initial load
duke
parents:
diff changeset
828 Deoptimization::DeoptAction action) {
a61af66fc99e Initial load
duke
parents:
diff changeset
829 return new UncommonTrapCallGenerator(m, reason, action);
a61af66fc99e Initial load
duke
parents:
diff changeset
830 }
a61af66fc99e Initial load
duke
parents:
diff changeset
831
a61af66fc99e Initial load
duke
parents:
diff changeset
832
a61af66fc99e Initial load
duke
parents:
diff changeset
833 JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
834 GraphKit kit(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
835 // Take the trap with arguments pushed on the stack. (Cf. null_check_receiver).
a61af66fc99e Initial load
duke
parents:
diff changeset
836 int nargs = method()->arg_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
837 kit.inc_sp(nargs);
a61af66fc99e Initial load
duke
parents:
diff changeset
838 assert(nargs <= kit.sp() && kit.sp() <= jvms->stk_size(), "sane sp w/ args pushed");
a61af66fc99e Initial load
duke
parents:
diff changeset
839 if (_reason == Deoptimization::Reason_class_check &&
a61af66fc99e Initial load
duke
parents:
diff changeset
840 _action == Deoptimization::Action_maybe_recompile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
841 // Temp fix for 6529811
a61af66fc99e Initial load
duke
parents:
diff changeset
842 // Don't allow uncommon_trap to override our decision to recompile in the event
a61af66fc99e Initial load
duke
parents:
diff changeset
843 // of a class cast failure for a monomorphic call as it will never let us convert
a61af66fc99e Initial load
duke
parents:
diff changeset
844 // the call to either bi-morphic or megamorphic and can lead to unc-trap loops
a61af66fc99e Initial load
duke
parents:
diff changeset
845 bool keep_exact_action = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
846 kit.uncommon_trap(_reason, _action, NULL, "monomorphic vcall checkcast", false, keep_exact_action);
a61af66fc99e Initial load
duke
parents:
diff changeset
847 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
848 kit.uncommon_trap(_reason, _action);
a61af66fc99e Initial load
duke
parents:
diff changeset
849 }
a61af66fc99e Initial load
duke
parents:
diff changeset
850 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
851 }
a61af66fc99e Initial load
duke
parents:
diff changeset
852
a61af66fc99e Initial load
duke
parents:
diff changeset
853 // (Note: Moved hook_up_call to GraphKit::set_edges_for_java_call.)
a61af66fc99e Initial load
duke
parents:
diff changeset
854
a61af66fc99e Initial load
duke
parents:
diff changeset
855 // (Node: Merged hook_up_exits into ParseGenerator::generate.)
a61af66fc99e Initial load
duke
parents:
diff changeset
856
a61af66fc99e Initial load
duke
parents:
diff changeset
857 #define NODES_OVERHEAD_PER_METHOD (30.0)
a61af66fc99e Initial load
duke
parents:
diff changeset
858 #define NODES_PER_BYTECODE (9.5)
a61af66fc99e Initial load
duke
parents:
diff changeset
859
a61af66fc99e Initial load
duke
parents:
diff changeset
860 void WarmCallInfo::init(JVMState* call_site, ciMethod* call_method, ciCallProfile& profile, float prof_factor) {
a61af66fc99e Initial load
duke
parents:
diff changeset
861 int call_count = profile.count();
a61af66fc99e Initial load
duke
parents:
diff changeset
862 int code_size = call_method->code_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
863
a61af66fc99e Initial load
duke
parents:
diff changeset
864 // Expected execution count is based on the historical count:
a61af66fc99e Initial load
duke
parents:
diff changeset
865 _count = call_count < 0 ? 1 : call_site->method()->scale_count(call_count, prof_factor);
a61af66fc99e Initial load
duke
parents:
diff changeset
866
a61af66fc99e Initial load
duke
parents:
diff changeset
867 // Expected profit from inlining, in units of simple call-overheads.
a61af66fc99e Initial load
duke
parents:
diff changeset
868 _profit = 1.0;
a61af66fc99e Initial load
duke
parents:
diff changeset
869
a61af66fc99e Initial load
duke
parents:
diff changeset
870 // Expected work performed by the call in units of call-overheads.
a61af66fc99e Initial load
duke
parents:
diff changeset
871 // %%% need an empirical curve fit for "work" (time in call)
a61af66fc99e Initial load
duke
parents:
diff changeset
872 float bytecodes_per_call = 3;
a61af66fc99e Initial load
duke
parents:
diff changeset
873 _work = 1.0 + code_size / bytecodes_per_call;
a61af66fc99e Initial load
duke
parents:
diff changeset
874
a61af66fc99e Initial load
duke
parents:
diff changeset
875 // Expected size of compilation graph:
a61af66fc99e Initial load
duke
parents:
diff changeset
876 // -XX:+PrintParseStatistics once reported:
a61af66fc99e Initial load
duke
parents:
diff changeset
877 // Methods seen: 9184 Methods parsed: 9184 Nodes created: 1582391
a61af66fc99e Initial load
duke
parents:
diff changeset
878 // Histogram of 144298 parsed bytecodes:
a61af66fc99e Initial load
duke
parents:
diff changeset
879 // %%% Need an better predictor for graph size.
a61af66fc99e Initial load
duke
parents:
diff changeset
880 _size = NODES_OVERHEAD_PER_METHOD + (NODES_PER_BYTECODE * code_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
881 }
a61af66fc99e Initial load
duke
parents:
diff changeset
882
a61af66fc99e Initial load
duke
parents:
diff changeset
883 // is_cold: Return true if the node should never be inlined.
a61af66fc99e Initial load
duke
parents:
diff changeset
884 // This is true if any of the key metrics are extreme.
a61af66fc99e Initial load
duke
parents:
diff changeset
885 bool WarmCallInfo::is_cold() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
886 if (count() < WarmCallMinCount) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
887 if (profit() < WarmCallMinProfit) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
888 if (work() > WarmCallMaxWork) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
889 if (size() > WarmCallMaxSize) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
890 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
891 }
a61af66fc99e Initial load
duke
parents:
diff changeset
892
a61af66fc99e Initial load
duke
parents:
diff changeset
893 // is_hot: Return true if the node should be inlined immediately.
a61af66fc99e Initial load
duke
parents:
diff changeset
894 // This is true if any of the key metrics are extreme.
a61af66fc99e Initial load
duke
parents:
diff changeset
895 bool WarmCallInfo::is_hot() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
896 assert(!is_cold(), "eliminate is_cold cases before testing is_hot");
a61af66fc99e Initial load
duke
parents:
diff changeset
897 if (count() >= HotCallCountThreshold) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
898 if (profit() >= HotCallProfitThreshold) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
899 if (work() <= HotCallTrivialWork) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
900 if (size() <= HotCallTrivialSize) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
901 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
902 }
a61af66fc99e Initial load
duke
parents:
diff changeset
903
a61af66fc99e Initial load
duke
parents:
diff changeset
904 // compute_heat:
a61af66fc99e Initial load
duke
parents:
diff changeset
905 float WarmCallInfo::compute_heat() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
906 assert(!is_cold(), "compute heat only on warm nodes");
a61af66fc99e Initial load
duke
parents:
diff changeset
907 assert(!is_hot(), "compute heat only on warm nodes");
a61af66fc99e Initial load
duke
parents:
diff changeset
908 int min_size = MAX2(0, (int)HotCallTrivialSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
909 int max_size = MIN2(500, (int)WarmCallMaxSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
910 float method_size = (size() - min_size) / MAX2(1, max_size - min_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
911 float size_factor;
a61af66fc99e Initial load
duke
parents:
diff changeset
912 if (method_size < 0.05) size_factor = 4; // 2 sigmas better than avg.
a61af66fc99e Initial load
duke
parents:
diff changeset
913 else if (method_size < 0.15) size_factor = 2; // 1 sigma better than avg.
a61af66fc99e Initial load
duke
parents:
diff changeset
914 else if (method_size < 0.5) size_factor = 1; // better than avg.
a61af66fc99e Initial load
duke
parents:
diff changeset
915 else size_factor = 0.5; // worse than avg.
a61af66fc99e Initial load
duke
parents:
diff changeset
916 return (count() * profit() * size_factor);
a61af66fc99e Initial load
duke
parents:
diff changeset
917 }
a61af66fc99e Initial load
duke
parents:
diff changeset
918
a61af66fc99e Initial load
duke
parents:
diff changeset
919 bool WarmCallInfo::warmer_than(WarmCallInfo* that) {
a61af66fc99e Initial load
duke
parents:
diff changeset
920 assert(this != that, "compare only different WCIs");
a61af66fc99e Initial load
duke
parents:
diff changeset
921 assert(this->heat() != 0 && that->heat() != 0, "call compute_heat 1st");
a61af66fc99e Initial load
duke
parents:
diff changeset
922 if (this->heat() > that->heat()) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
923 if (this->heat() < that->heat()) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
924 assert(this->heat() == that->heat(), "no NaN heat allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
925 // Equal heat. Break the tie some other way.
a61af66fc99e Initial load
duke
parents:
diff changeset
926 if (!this->call() || !that->call()) return (address)this > (address)that;
a61af66fc99e Initial load
duke
parents:
diff changeset
927 return this->call()->_idx > that->call()->_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
928 }
a61af66fc99e Initial load
duke
parents:
diff changeset
929
a61af66fc99e Initial load
duke
parents:
diff changeset
930 //#define UNINIT_NEXT ((WarmCallInfo*)badAddress)
a61af66fc99e Initial load
duke
parents:
diff changeset
931 #define UNINIT_NEXT ((WarmCallInfo*)NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
932
a61af66fc99e Initial load
duke
parents:
diff changeset
933 WarmCallInfo* WarmCallInfo::insert_into(WarmCallInfo* head) {
a61af66fc99e Initial load
duke
parents:
diff changeset
934 assert(next() == UNINIT_NEXT, "not yet on any list");
a61af66fc99e Initial load
duke
parents:
diff changeset
935 WarmCallInfo* prev_p = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
936 WarmCallInfo* next_p = head;
a61af66fc99e Initial load
duke
parents:
diff changeset
937 while (next_p != NULL && next_p->warmer_than(this)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
938 prev_p = next_p;
a61af66fc99e Initial load
duke
parents:
diff changeset
939 next_p = prev_p->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
940 }
a61af66fc99e Initial load
duke
parents:
diff changeset
941 // Install this between prev_p and next_p.
a61af66fc99e Initial load
duke
parents:
diff changeset
942 this->set_next(next_p);
a61af66fc99e Initial load
duke
parents:
diff changeset
943 if (prev_p == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
944 head = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
945 else
a61af66fc99e Initial load
duke
parents:
diff changeset
946 prev_p->set_next(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
947 return head;
a61af66fc99e Initial load
duke
parents:
diff changeset
948 }
a61af66fc99e Initial load
duke
parents:
diff changeset
949
a61af66fc99e Initial load
duke
parents:
diff changeset
950 WarmCallInfo* WarmCallInfo::remove_from(WarmCallInfo* head) {
a61af66fc99e Initial load
duke
parents:
diff changeset
951 WarmCallInfo* prev_p = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
952 WarmCallInfo* next_p = head;
a61af66fc99e Initial load
duke
parents:
diff changeset
953 while (next_p != this) {
a61af66fc99e Initial load
duke
parents:
diff changeset
954 assert(next_p != NULL, "this must be in the list somewhere");
a61af66fc99e Initial load
duke
parents:
diff changeset
955 prev_p = next_p;
a61af66fc99e Initial load
duke
parents:
diff changeset
956 next_p = prev_p->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
957 }
a61af66fc99e Initial load
duke
parents:
diff changeset
958 next_p = this->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
959 debug_only(this->set_next(UNINIT_NEXT));
a61af66fc99e Initial load
duke
parents:
diff changeset
960 // Remove this from between prev_p and next_p.
a61af66fc99e Initial load
duke
parents:
diff changeset
961 if (prev_p == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
962 head = next_p;
a61af66fc99e Initial load
duke
parents:
diff changeset
963 else
a61af66fc99e Initial load
duke
parents:
diff changeset
964 prev_p->set_next(next_p);
a61af66fc99e Initial load
duke
parents:
diff changeset
965 return head;
a61af66fc99e Initial load
duke
parents:
diff changeset
966 }
a61af66fc99e Initial load
duke
parents:
diff changeset
967
a61af66fc99e Initial load
duke
parents:
diff changeset
968 WarmCallInfo* WarmCallInfo::_always_hot = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
969 WarmCallInfo* WarmCallInfo::_always_cold = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
970
a61af66fc99e Initial load
duke
parents:
diff changeset
971 WarmCallInfo* WarmCallInfo::always_hot() {
a61af66fc99e Initial load
duke
parents:
diff changeset
972 if (_always_hot == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
973 static double bits[sizeof(WarmCallInfo) / sizeof(double) + 1] = {0};
a61af66fc99e Initial load
duke
parents:
diff changeset
974 WarmCallInfo* ci = (WarmCallInfo*) bits;
a61af66fc99e Initial load
duke
parents:
diff changeset
975 ci->_profit = ci->_count = MAX_VALUE();
a61af66fc99e Initial load
duke
parents:
diff changeset
976 ci->_work = ci->_size = MIN_VALUE();
a61af66fc99e Initial load
duke
parents:
diff changeset
977 _always_hot = ci;
a61af66fc99e Initial load
duke
parents:
diff changeset
978 }
a61af66fc99e Initial load
duke
parents:
diff changeset
979 assert(_always_hot->is_hot(), "must always be hot");
a61af66fc99e Initial load
duke
parents:
diff changeset
980 return _always_hot;
a61af66fc99e Initial load
duke
parents:
diff changeset
981 }
a61af66fc99e Initial load
duke
parents:
diff changeset
982
a61af66fc99e Initial load
duke
parents:
diff changeset
983 WarmCallInfo* WarmCallInfo::always_cold() {
a61af66fc99e Initial load
duke
parents:
diff changeset
984 if (_always_cold == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
985 static double bits[sizeof(WarmCallInfo) / sizeof(double) + 1] = {0};
a61af66fc99e Initial load
duke
parents:
diff changeset
986 WarmCallInfo* ci = (WarmCallInfo*) bits;
a61af66fc99e Initial load
duke
parents:
diff changeset
987 ci->_profit = ci->_count = MIN_VALUE();
a61af66fc99e Initial load
duke
parents:
diff changeset
988 ci->_work = ci->_size = MAX_VALUE();
a61af66fc99e Initial load
duke
parents:
diff changeset
989 _always_cold = ci;
a61af66fc99e Initial load
duke
parents:
diff changeset
990 }
a61af66fc99e Initial load
duke
parents:
diff changeset
991 assert(_always_cold->is_cold(), "must always be cold");
a61af66fc99e Initial load
duke
parents:
diff changeset
992 return _always_cold;
a61af66fc99e Initial load
duke
parents:
diff changeset
993 }
a61af66fc99e Initial load
duke
parents:
diff changeset
994
a61af66fc99e Initial load
duke
parents:
diff changeset
995
a61af66fc99e Initial load
duke
parents:
diff changeset
996 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
997
a61af66fc99e Initial load
duke
parents:
diff changeset
998 void WarmCallInfo::print() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
999 tty->print("%s : C=%6.1f P=%6.1f W=%6.1f S=%6.1f H=%6.1f -> %p",
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 is_cold() ? "cold" : is_hot() ? "hot " : "warm",
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 count(), profit(), work(), size(), compute_heat(), next());
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 if (call() != NULL) call()->dump();
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1005
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 void print_wci(WarmCallInfo* ci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 ci->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1009
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 void WarmCallInfo::print_all() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 for (const WarmCallInfo* p = this; p != NULL; p = p->next())
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 p->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1014
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 int WarmCallInfo::count_all() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 int cnt = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 for (const WarmCallInfo* p = this; p != NULL; p = p->next())
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 cnt++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 return cnt;
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1021
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 #endif //PRODUCT