annotate src/share/vm/opto/callGenerator.cpp @ 452:00b023ae2d78

6722113: CMS: Incorrect overflow handling during precleaning of Reference lists Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery. Reviewed-by: apetrusenko, jcoomes
author ysr
date Thu, 20 Nov 2008 12:27:41 -0800
parents 9ee9cf798b59
children 7c57aead6d3e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
337
9ee9cf798b59 6754988: Update copyright year
xdono
parents: 293
diff changeset
2 * Copyright 2000-2008 Sun Microsystems, Inc. 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 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
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 {
a61af66fc99e Initial load
duke
parents:
diff changeset
101 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
102 DirectCallGenerator(ciMethod* method)
a61af66fc99e Initial load
duke
parents:
diff changeset
103 : CallGenerator(method)
a61af66fc99e Initial load
duke
parents:
diff changeset
104 {
a61af66fc99e Initial load
duke
parents:
diff changeset
105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
106 virtual JVMState* generate(JVMState* jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
107 };
a61af66fc99e Initial load
duke
parents:
diff changeset
108
a61af66fc99e Initial load
duke
parents:
diff changeset
109 JVMState* DirectCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
110 GraphKit kit(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
111 bool is_static = method()->is_static();
a61af66fc99e Initial load
duke
parents:
diff changeset
112 address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
a61af66fc99e Initial load
duke
parents:
diff changeset
113 : SharedRuntime::get_resolve_opt_virtual_call_stub();
a61af66fc99e Initial load
duke
parents:
diff changeset
114
a61af66fc99e Initial load
duke
parents:
diff changeset
115 if (kit.C->log() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
116 kit.C->log()->elem("direct_call bci='%d'", jvms->bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
117 }
a61af66fc99e Initial load
duke
parents:
diff changeset
118
a61af66fc99e Initial load
duke
parents:
diff changeset
119 CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), target, method(), kit.bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
120 if (!is_static) {
a61af66fc99e Initial load
duke
parents:
diff changeset
121 // Make an explicit receiver null_check as part of this call.
a61af66fc99e Initial load
duke
parents:
diff changeset
122 // Since we share a map with the caller, his JVMS gets adjusted.
a61af66fc99e Initial load
duke
parents:
diff changeset
123 kit.null_check_receiver(method());
a61af66fc99e Initial load
duke
parents:
diff changeset
124 if (kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 // And dump it back to the caller, decorated with any exceptions:
a61af66fc99e Initial load
duke
parents:
diff changeset
126 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
128 // Mark the call node as virtual, sort of:
a61af66fc99e Initial load
duke
parents:
diff changeset
129 call->set_optimized_virtual(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
131 kit.set_arguments_for_java_call(call);
a61af66fc99e Initial load
duke
parents:
diff changeset
132 kit.set_edges_for_java_call(call);
a61af66fc99e Initial load
duke
parents:
diff changeset
133 Node* ret = kit.set_results_for_java_call(call);
a61af66fc99e Initial load
duke
parents:
diff changeset
134 kit.push_node(method()->return_type()->basic_type(), ret);
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
a61af66fc99e Initial load
duke
parents:
diff changeset
138 class VirtualCallGenerator : public CallGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
139 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
140 int _vtable_index;
a61af66fc99e Initial load
duke
parents:
diff changeset
141 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
142 VirtualCallGenerator(ciMethod* method, int vtable_index)
a61af66fc99e Initial load
duke
parents:
diff changeset
143 : CallGenerator(method), _vtable_index(vtable_index)
a61af66fc99e Initial load
duke
parents:
diff changeset
144 {
a61af66fc99e Initial load
duke
parents:
diff changeset
145 assert(vtable_index == methodOopDesc::invalid_vtable_index ||
a61af66fc99e Initial load
duke
parents:
diff changeset
146 vtable_index >= 0, "either invalid or usable");
a61af66fc99e Initial load
duke
parents:
diff changeset
147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
148 virtual bool is_virtual() const { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
149 virtual JVMState* generate(JVMState* jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
150 };
a61af66fc99e Initial load
duke
parents:
diff changeset
151
a61af66fc99e Initial load
duke
parents:
diff changeset
152 //--------------------------VirtualCallGenerator------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
153 // Internal class which handles all out-of-line calls checking receiver type.
a61af66fc99e Initial load
duke
parents:
diff changeset
154 JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
155 GraphKit kit(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 Node* receiver = kit.argument(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
157
a61af66fc99e Initial load
duke
parents:
diff changeset
158 if (kit.C->log() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
159 kit.C->log()->elem("virtual_call bci='%d'", jvms->bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
160 }
a61af66fc99e Initial load
duke
parents:
diff changeset
161
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // If the receiver is a constant null, do not torture the system
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // by attempting to call through it. The compile will proceed
a61af66fc99e Initial load
duke
parents:
diff changeset
164 // correctly, but may bail out in final_graph_reshaping, because
a61af66fc99e Initial load
duke
parents:
diff changeset
165 // the call instruction will have a seemingly deficient out-count.
a61af66fc99e Initial load
duke
parents:
diff changeset
166 // (The bailout says something misleading about an "infinite loop".)
a61af66fc99e Initial load
duke
parents:
diff changeset
167 if (kit.gvn().type(receiver)->higher_equal(TypePtr::NULL_PTR)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
168 kit.inc_sp(method()->arg_size()); // restore arguments
a61af66fc99e Initial load
duke
parents:
diff changeset
169 kit.uncommon_trap(Deoptimization::Reason_null_check,
a61af66fc99e Initial load
duke
parents:
diff changeset
170 Deoptimization::Action_none,
a61af66fc99e Initial load
duke
parents:
diff changeset
171 NULL, "null receiver");
a61af66fc99e Initial load
duke
parents:
diff changeset
172 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
173 }
a61af66fc99e Initial load
duke
parents:
diff changeset
174
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // Ideally we would unconditionally do a null check here and let it
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // be converted to an implicit check based on profile information.
a61af66fc99e Initial load
duke
parents:
diff changeset
177 // However currently the conversion to implicit null checks in
a61af66fc99e Initial load
duke
parents:
diff changeset
178 // Block::implicit_null_check() only looks for loads and stores, not calls.
a61af66fc99e Initial load
duke
parents:
diff changeset
179 ciMethod *caller = kit.method();
a61af66fc99e Initial load
duke
parents:
diff changeset
180 ciMethodData *caller_md = (caller == NULL) ? NULL : caller->method_data();
a61af66fc99e Initial load
duke
parents:
diff changeset
181 if (!UseInlineCaches || !ImplicitNullChecks ||
a61af66fc99e Initial load
duke
parents:
diff changeset
182 ((ImplicitNullCheckThreshold > 0) && caller_md &&
a61af66fc99e Initial load
duke
parents:
diff changeset
183 (caller_md->trap_count(Deoptimization::Reason_null_check)
a61af66fc99e Initial load
duke
parents:
diff changeset
184 >= (uint)ImplicitNullCheckThreshold))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // Make an explicit receiver null_check as part of this call.
a61af66fc99e Initial load
duke
parents:
diff changeset
186 // Since we share a map with the caller, his JVMS gets adjusted.
a61af66fc99e Initial load
duke
parents:
diff changeset
187 receiver = kit.null_check_receiver(method());
a61af66fc99e Initial load
duke
parents:
diff changeset
188 if (kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // And dump it back to the caller, decorated with any exceptions:
a61af66fc99e Initial load
duke
parents:
diff changeset
190 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
192 }
a61af66fc99e Initial load
duke
parents:
diff changeset
193
a61af66fc99e Initial load
duke
parents:
diff changeset
194 assert(!method()->is_static(), "virtual call must not be to static");
a61af66fc99e Initial load
duke
parents:
diff changeset
195 assert(!method()->is_final(), "virtual call should not be to final");
a61af66fc99e Initial load
duke
parents:
diff changeset
196 assert(!method()->is_private(), "virtual call should not be to private");
a61af66fc99e Initial load
duke
parents:
diff changeset
197 assert(_vtable_index == methodOopDesc::invalid_vtable_index || !UseInlineCaches,
a61af66fc99e Initial load
duke
parents:
diff changeset
198 "no vtable calls if +UseInlineCaches ");
a61af66fc99e Initial load
duke
parents:
diff changeset
199 address target = SharedRuntime::get_resolve_virtual_call_stub();
a61af66fc99e Initial load
duke
parents:
diff changeset
200 // Normal inline cache used for call
a61af66fc99e Initial load
duke
parents:
diff changeset
201 CallDynamicJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallDynamicJavaNode(tf(), target, method(), _vtable_index, kit.bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
202 kit.set_arguments_for_java_call(call);
a61af66fc99e Initial load
duke
parents:
diff changeset
203 kit.set_edges_for_java_call(call);
a61af66fc99e Initial load
duke
parents:
diff changeset
204 Node* ret = kit.set_results_for_java_call(call);
a61af66fc99e Initial load
duke
parents:
diff changeset
205 kit.push_node(method()->return_type()->basic_type(), ret);
a61af66fc99e Initial load
duke
parents:
diff changeset
206
a61af66fc99e Initial load
duke
parents:
diff changeset
207 // Represent the effect of an implicit receiver null_check
a61af66fc99e Initial load
duke
parents:
diff changeset
208 // as part of this call. Since we share a map with the caller,
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // his JVMS gets adjusted.
a61af66fc99e Initial load
duke
parents:
diff changeset
210 kit.cast_not_null(receiver);
a61af66fc99e Initial load
duke
parents:
diff changeset
211 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
212 }
a61af66fc99e Initial load
duke
parents:
diff changeset
213
a61af66fc99e Initial load
duke
parents:
diff changeset
214 bool ParseGenerator::can_parse(ciMethod* m, int entry_bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
215 // Certain methods cannot be parsed at all:
a61af66fc99e Initial load
duke
parents:
diff changeset
216 if (!m->can_be_compiled()) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
217 if (!m->has_balanced_monitors()) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
218 if (m->get_flow_analysis()->failing()) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
219
a61af66fc99e Initial load
duke
parents:
diff changeset
220 // (Methods may bail out for other reasons, after the parser is run.
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // We try to avoid this, but if forced, we must return (Node*)NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
222 // The user of the CallGenerator must check for this condition.)
a61af66fc99e Initial load
duke
parents:
diff changeset
223 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
224 }
a61af66fc99e Initial load
duke
parents:
diff changeset
225
a61af66fc99e Initial load
duke
parents:
diff changeset
226 CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) {
a61af66fc99e Initial load
duke
parents:
diff changeset
227 if (!ParseGenerator::can_parse(m)) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
228 return new ParseGenerator(m, expected_uses);
a61af66fc99e Initial load
duke
parents:
diff changeset
229 }
a61af66fc99e Initial load
duke
parents:
diff changeset
230
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // As a special case, the JVMS passed to this CallGenerator is
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // for the method execution already in progress, not just the JVMS
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // of the caller. Thus, this CallGenerator cannot be mixed with others!
a61af66fc99e Initial load
duke
parents:
diff changeset
234 CallGenerator* CallGenerator::for_osr(ciMethod* m, int osr_bci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
235 if (!ParseGenerator::can_parse(m, true)) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
236 float past_uses = m->interpreter_invocation_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
237 float expected_uses = past_uses;
a61af66fc99e Initial load
duke
parents:
diff changeset
238 return new ParseGenerator(m, expected_uses, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
239 }
a61af66fc99e Initial load
duke
parents:
diff changeset
240
a61af66fc99e Initial load
duke
parents:
diff changeset
241 CallGenerator* CallGenerator::for_direct_call(ciMethod* m) {
a61af66fc99e Initial load
duke
parents:
diff changeset
242 assert(!m->is_abstract(), "for_direct_call mismatch");
a61af66fc99e Initial load
duke
parents:
diff changeset
243 return new DirectCallGenerator(m);
a61af66fc99e Initial load
duke
parents:
diff changeset
244 }
a61af66fc99e Initial load
duke
parents:
diff changeset
245
a61af66fc99e Initial load
duke
parents:
diff changeset
246 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
247 assert(!m->is_static(), "for_virtual_call mismatch");
a61af66fc99e Initial load
duke
parents:
diff changeset
248 return new VirtualCallGenerator(m, vtable_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
249 }
a61af66fc99e Initial load
duke
parents:
diff changeset
250
a61af66fc99e Initial load
duke
parents:
diff changeset
251
a61af66fc99e Initial load
duke
parents:
diff changeset
252 //---------------------------WarmCallGenerator--------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
253 // Internal class which handles initial deferral of inlining decisions.
a61af66fc99e Initial load
duke
parents:
diff changeset
254 class WarmCallGenerator : public CallGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
255 WarmCallInfo* _call_info;
a61af66fc99e Initial load
duke
parents:
diff changeset
256 CallGenerator* _if_cold;
a61af66fc99e Initial load
duke
parents:
diff changeset
257 CallGenerator* _if_hot;
a61af66fc99e Initial load
duke
parents:
diff changeset
258 bool _is_virtual; // caches virtuality of if_cold
a61af66fc99e Initial load
duke
parents:
diff changeset
259 bool _is_inline; // caches inline-ness of if_hot
a61af66fc99e Initial load
duke
parents:
diff changeset
260
a61af66fc99e Initial load
duke
parents:
diff changeset
261 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
262 WarmCallGenerator(WarmCallInfo* ci,
a61af66fc99e Initial load
duke
parents:
diff changeset
263 CallGenerator* if_cold,
a61af66fc99e Initial load
duke
parents:
diff changeset
264 CallGenerator* if_hot)
a61af66fc99e Initial load
duke
parents:
diff changeset
265 : CallGenerator(if_cold->method())
a61af66fc99e Initial load
duke
parents:
diff changeset
266 {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 assert(method() == if_hot->method(), "consistent choices");
a61af66fc99e Initial load
duke
parents:
diff changeset
268 _call_info = ci;
a61af66fc99e Initial load
duke
parents:
diff changeset
269 _if_cold = if_cold;
a61af66fc99e Initial load
duke
parents:
diff changeset
270 _if_hot = if_hot;
a61af66fc99e Initial load
duke
parents:
diff changeset
271 _is_virtual = if_cold->is_virtual();
a61af66fc99e Initial load
duke
parents:
diff changeset
272 _is_inline = if_hot->is_inline();
a61af66fc99e Initial load
duke
parents:
diff changeset
273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
274
a61af66fc99e Initial load
duke
parents:
diff changeset
275 virtual bool is_inline() const { return _is_inline; }
a61af66fc99e Initial load
duke
parents:
diff changeset
276 virtual bool is_virtual() const { return _is_virtual; }
a61af66fc99e Initial load
duke
parents:
diff changeset
277 virtual bool is_deferred() const { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
278
a61af66fc99e Initial load
duke
parents:
diff changeset
279 virtual JVMState* generate(JVMState* jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
280 };
a61af66fc99e Initial load
duke
parents:
diff changeset
281
a61af66fc99e Initial load
duke
parents:
diff changeset
282
a61af66fc99e Initial load
duke
parents:
diff changeset
283 CallGenerator* CallGenerator::for_warm_call(WarmCallInfo* ci,
a61af66fc99e Initial load
duke
parents:
diff changeset
284 CallGenerator* if_cold,
a61af66fc99e Initial load
duke
parents:
diff changeset
285 CallGenerator* if_hot) {
a61af66fc99e Initial load
duke
parents:
diff changeset
286 return new WarmCallGenerator(ci, if_cold, if_hot);
a61af66fc99e Initial load
duke
parents:
diff changeset
287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
288
a61af66fc99e Initial load
duke
parents:
diff changeset
289 JVMState* WarmCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
290 Compile* C = Compile::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
291 if (C->log() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
292 C->log()->elem("warm_call bci='%d'", jvms->bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
293 }
a61af66fc99e Initial load
duke
parents:
diff changeset
294 jvms = _if_cold->generate(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
295 if (jvms != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
296 Node* m = jvms->map()->control();
a61af66fc99e Initial load
duke
parents:
diff changeset
297 if (m->is_CatchProj()) m = m->in(0); else m = C->top();
a61af66fc99e Initial load
duke
parents:
diff changeset
298 if (m->is_Catch()) m = m->in(0); else m = C->top();
a61af66fc99e Initial load
duke
parents:
diff changeset
299 if (m->is_Proj()) m = m->in(0); else m = C->top();
a61af66fc99e Initial load
duke
parents:
diff changeset
300 if (m->is_CallJava()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
301 _call_info->set_call(m->as_Call());
a61af66fc99e Initial load
duke
parents:
diff changeset
302 _call_info->set_hot_cg(_if_hot);
a61af66fc99e Initial load
duke
parents:
diff changeset
303 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
304 if (PrintOpto || PrintOptoInlining) {
a61af66fc99e Initial load
duke
parents:
diff changeset
305 tty->print_cr("Queueing for warm inlining at bci %d:", jvms->bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
306 tty->print("WCI: ");
a61af66fc99e Initial load
duke
parents:
diff changeset
307 _call_info->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
308 }
a61af66fc99e Initial load
duke
parents:
diff changeset
309 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
310 _call_info->set_heat(_call_info->compute_heat());
a61af66fc99e Initial load
duke
parents:
diff changeset
311 C->set_warm_calls(_call_info->insert_into(C->warm_calls()));
a61af66fc99e Initial load
duke
parents:
diff changeset
312 }
a61af66fc99e Initial load
duke
parents:
diff changeset
313 }
a61af66fc99e Initial load
duke
parents:
diff changeset
314 return jvms;
a61af66fc99e Initial load
duke
parents:
diff changeset
315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
316
a61af66fc99e Initial load
duke
parents:
diff changeset
317 void WarmCallInfo::make_hot() {
a61af66fc99e Initial load
duke
parents:
diff changeset
318 Compile* C = Compile::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
319 // Replace the callnode with something better.
a61af66fc99e Initial load
duke
parents:
diff changeset
320 CallJavaNode* call = this->call()->as_CallJava();
a61af66fc99e Initial load
duke
parents:
diff changeset
321 ciMethod* method = call->method();
a61af66fc99e Initial load
duke
parents:
diff changeset
322 int nargs = method->arg_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
323 JVMState* jvms = call->jvms()->clone_shallow(C);
a61af66fc99e Initial load
duke
parents:
diff changeset
324 uint size = TypeFunc::Parms + MAX2(2, nargs);
a61af66fc99e Initial load
duke
parents:
diff changeset
325 SafePointNode* map = new (C, size) SafePointNode(size, jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
326 for (uint i1 = 0; i1 < (uint)(TypeFunc::Parms + nargs); i1++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
327 map->init_req(i1, call->in(i1));
a61af66fc99e Initial load
duke
parents:
diff changeset
328 }
a61af66fc99e Initial load
duke
parents:
diff changeset
329 jvms->set_map(map);
a61af66fc99e Initial load
duke
parents:
diff changeset
330 jvms->set_offsets(map->req());
a61af66fc99e Initial load
duke
parents:
diff changeset
331 jvms->set_locoff(TypeFunc::Parms);
a61af66fc99e Initial load
duke
parents:
diff changeset
332 jvms->set_stkoff(TypeFunc::Parms);
a61af66fc99e Initial load
duke
parents:
diff changeset
333 GraphKit kit(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
334
a61af66fc99e Initial load
duke
parents:
diff changeset
335 JVMState* new_jvms = _hot_cg->generate(kit.jvms());
a61af66fc99e Initial load
duke
parents:
diff changeset
336 if (new_jvms == NULL) return; // no change
a61af66fc99e Initial load
duke
parents:
diff changeset
337 if (C->failing()) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
338
a61af66fc99e Initial load
duke
parents:
diff changeset
339 kit.set_jvms(new_jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
340 Node* res = C->top();
a61af66fc99e Initial load
duke
parents:
diff changeset
341 int res_size = method->return_type()->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
342 if (res_size != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
343 kit.inc_sp(-res_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
344 res = kit.argument(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
346 GraphKit ekit(kit.combine_and_pop_all_exception_states()->jvms());
a61af66fc99e Initial load
duke
parents:
diff changeset
347
a61af66fc99e Initial load
duke
parents:
diff changeset
348 // Replace the call:
a61af66fc99e Initial load
duke
parents:
diff changeset
349 for (DUIterator i = call->outs(); call->has_out(i); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
350 Node* n = call->out(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
351 Node* nn = NULL; // replacement
a61af66fc99e Initial load
duke
parents:
diff changeset
352 if (n->is_Proj()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
353 ProjNode* nproj = n->as_Proj();
a61af66fc99e Initial load
duke
parents:
diff changeset
354 assert(nproj->_con < (uint)(TypeFunc::Parms + (res_size ? 1 : 0)), "sane proj");
a61af66fc99e Initial load
duke
parents:
diff changeset
355 if (nproj->_con == TypeFunc::Parms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
356 nn = res;
a61af66fc99e Initial load
duke
parents:
diff changeset
357 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
358 nn = kit.map()->in(nproj->_con);
a61af66fc99e Initial load
duke
parents:
diff changeset
359 }
a61af66fc99e Initial load
duke
parents:
diff changeset
360 if (nproj->_con == TypeFunc::I_O) {
a61af66fc99e Initial load
duke
parents:
diff changeset
361 for (DUIterator j = nproj->outs(); nproj->has_out(j); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
362 Node* e = nproj->out(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
363 if (e->Opcode() == Op_CreateEx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
364 e->replace_by(ekit.argument(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
365 } else if (e->Opcode() == Op_Catch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
366 for (DUIterator k = e->outs(); e->has_out(k); k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
367 CatchProjNode* p = e->out(j)->as_CatchProj();
a61af66fc99e Initial load
duke
parents:
diff changeset
368 if (p->is_handler_proj()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
369 p->replace_by(ekit.control());
a61af66fc99e Initial load
duke
parents:
diff changeset
370 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
371 p->replace_by(kit.control());
a61af66fc99e Initial load
duke
parents:
diff changeset
372 }
a61af66fc99e Initial load
duke
parents:
diff changeset
373 }
a61af66fc99e Initial load
duke
parents:
diff changeset
374 }
a61af66fc99e Initial load
duke
parents:
diff changeset
375 }
a61af66fc99e Initial load
duke
parents:
diff changeset
376 }
a61af66fc99e Initial load
duke
parents:
diff changeset
377 }
a61af66fc99e Initial load
duke
parents:
diff changeset
378 NOT_PRODUCT(if (!nn) n->dump(2));
a61af66fc99e Initial load
duke
parents:
diff changeset
379 assert(nn != NULL, "don't know what to do with this user");
a61af66fc99e Initial load
duke
parents:
diff changeset
380 n->replace_by(nn);
a61af66fc99e Initial load
duke
parents:
diff changeset
381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
382 }
a61af66fc99e Initial load
duke
parents:
diff changeset
383
a61af66fc99e Initial load
duke
parents:
diff changeset
384 void WarmCallInfo::make_cold() {
a61af66fc99e Initial load
duke
parents:
diff changeset
385 // No action: Just dequeue.
a61af66fc99e Initial load
duke
parents:
diff changeset
386 }
a61af66fc99e Initial load
duke
parents:
diff changeset
387
a61af66fc99e Initial load
duke
parents:
diff changeset
388
a61af66fc99e Initial load
duke
parents:
diff changeset
389 //------------------------PredictedCallGenerator------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
390 // Internal class which handles all out-of-line calls checking receiver type.
a61af66fc99e Initial load
duke
parents:
diff changeset
391 class PredictedCallGenerator : public CallGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
392 ciKlass* _predicted_receiver;
a61af66fc99e Initial load
duke
parents:
diff changeset
393 CallGenerator* _if_missed;
a61af66fc99e Initial load
duke
parents:
diff changeset
394 CallGenerator* _if_hit;
a61af66fc99e Initial load
duke
parents:
diff changeset
395 float _hit_prob;
a61af66fc99e Initial load
duke
parents:
diff changeset
396
a61af66fc99e Initial load
duke
parents:
diff changeset
397 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
398 PredictedCallGenerator(ciKlass* predicted_receiver,
a61af66fc99e Initial load
duke
parents:
diff changeset
399 CallGenerator* if_missed,
a61af66fc99e Initial load
duke
parents:
diff changeset
400 CallGenerator* if_hit, float hit_prob)
a61af66fc99e Initial load
duke
parents:
diff changeset
401 : CallGenerator(if_missed->method())
a61af66fc99e Initial load
duke
parents:
diff changeset
402 {
a61af66fc99e Initial load
duke
parents:
diff changeset
403 // The call profile data may predict the hit_prob as extreme as 0 or 1.
a61af66fc99e Initial load
duke
parents:
diff changeset
404 // Remove the extremes values from the range.
a61af66fc99e Initial load
duke
parents:
diff changeset
405 if (hit_prob > PROB_MAX) hit_prob = PROB_MAX;
a61af66fc99e Initial load
duke
parents:
diff changeset
406 if (hit_prob < PROB_MIN) hit_prob = PROB_MIN;
a61af66fc99e Initial load
duke
parents:
diff changeset
407
a61af66fc99e Initial load
duke
parents:
diff changeset
408 _predicted_receiver = predicted_receiver;
a61af66fc99e Initial load
duke
parents:
diff changeset
409 _if_missed = if_missed;
a61af66fc99e Initial load
duke
parents:
diff changeset
410 _if_hit = if_hit;
a61af66fc99e Initial load
duke
parents:
diff changeset
411 _hit_prob = hit_prob;
a61af66fc99e Initial load
duke
parents:
diff changeset
412 }
a61af66fc99e Initial load
duke
parents:
diff changeset
413
a61af66fc99e Initial load
duke
parents:
diff changeset
414 virtual bool is_virtual() const { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
415 virtual bool is_inline() const { return _if_hit->is_inline(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
416 virtual bool is_deferred() const { return _if_hit->is_deferred(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
417
a61af66fc99e Initial load
duke
parents:
diff changeset
418 virtual JVMState* generate(JVMState* jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
419 };
a61af66fc99e Initial load
duke
parents:
diff changeset
420
a61af66fc99e Initial load
duke
parents:
diff changeset
421
a61af66fc99e Initial load
duke
parents:
diff changeset
422 CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver,
a61af66fc99e Initial load
duke
parents:
diff changeset
423 CallGenerator* if_missed,
a61af66fc99e Initial load
duke
parents:
diff changeset
424 CallGenerator* if_hit,
a61af66fc99e Initial load
duke
parents:
diff changeset
425 float hit_prob) {
a61af66fc99e Initial load
duke
parents:
diff changeset
426 return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, hit_prob);
a61af66fc99e Initial load
duke
parents:
diff changeset
427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
428
a61af66fc99e Initial load
duke
parents:
diff changeset
429
a61af66fc99e Initial load
duke
parents:
diff changeset
430 JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
431 GraphKit kit(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
432 PhaseGVN& gvn = kit.gvn();
a61af66fc99e Initial load
duke
parents:
diff changeset
433 // We need an explicit receiver null_check before checking its type.
a61af66fc99e Initial load
duke
parents:
diff changeset
434 // We share a map with the caller, so his JVMS gets adjusted.
a61af66fc99e Initial load
duke
parents:
diff changeset
435 Node* receiver = kit.argument(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
436
a61af66fc99e Initial load
duke
parents:
diff changeset
437 CompileLog* log = kit.C->log();
a61af66fc99e Initial load
duke
parents:
diff changeset
438 if (log != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
439 log->elem("predicted_call bci='%d' klass='%d'",
a61af66fc99e Initial load
duke
parents:
diff changeset
440 jvms->bci(), log->identify(_predicted_receiver));
a61af66fc99e Initial load
duke
parents:
diff changeset
441 }
a61af66fc99e Initial load
duke
parents:
diff changeset
442
a61af66fc99e Initial load
duke
parents:
diff changeset
443 receiver = kit.null_check_receiver(method());
a61af66fc99e Initial load
duke
parents:
diff changeset
444 if (kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
445 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
447
a61af66fc99e Initial load
duke
parents:
diff changeset
448 Node* exact_receiver = receiver; // will get updated in place...
a61af66fc99e Initial load
duke
parents:
diff changeset
449 Node* slow_ctl = kit.type_check_receiver(receiver,
a61af66fc99e Initial load
duke
parents:
diff changeset
450 _predicted_receiver, _hit_prob,
a61af66fc99e Initial load
duke
parents:
diff changeset
451 &exact_receiver);
a61af66fc99e Initial load
duke
parents:
diff changeset
452
a61af66fc99e Initial load
duke
parents:
diff changeset
453 SafePointNode* slow_map = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
454 JVMState* slow_jvms;
a61af66fc99e Initial load
duke
parents:
diff changeset
455 { PreserveJVMState pjvms(&kit);
a61af66fc99e Initial load
duke
parents:
diff changeset
456 kit.set_control(slow_ctl);
a61af66fc99e Initial load
duke
parents:
diff changeset
457 if (!kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
458 slow_jvms = _if_missed->generate(kit.sync_jvms());
a61af66fc99e Initial load
duke
parents:
diff changeset
459 assert(slow_jvms != NULL, "miss path must not fail to generate");
a61af66fc99e Initial load
duke
parents:
diff changeset
460 kit.add_exception_states_from(slow_jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
461 kit.set_map(slow_jvms->map());
a61af66fc99e Initial load
duke
parents:
diff changeset
462 if (!kit.stopped())
a61af66fc99e Initial load
duke
parents:
diff changeset
463 slow_map = kit.stop();
a61af66fc99e Initial load
duke
parents:
diff changeset
464 }
a61af66fc99e Initial load
duke
parents:
diff changeset
465 }
a61af66fc99e Initial load
duke
parents:
diff changeset
466
293
c3e045194476 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents: 0
diff changeset
467 if (kit.stopped()) {
c3e045194476 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents: 0
diff changeset
468 // 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
469 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
470 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
471 }
c3e045194476 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents: 0
diff changeset
472
0
a61af66fc99e Initial load
duke
parents:
diff changeset
473 // fall through if the instance exactly matches the desired type
a61af66fc99e Initial load
duke
parents:
diff changeset
474 kit.replace_in_map(receiver, exact_receiver);
a61af66fc99e Initial load
duke
parents:
diff changeset
475
a61af66fc99e Initial load
duke
parents:
diff changeset
476 // Make the hot call:
a61af66fc99e Initial load
duke
parents:
diff changeset
477 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
a61af66fc99e Initial load
duke
parents:
diff changeset
478 if (new_jvms == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
479 // Inline failed, so make a direct call.
a61af66fc99e Initial load
duke
parents:
diff changeset
480 assert(_if_hit->is_inline(), "must have been a failed inline");
a61af66fc99e Initial load
duke
parents:
diff changeset
481 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
a61af66fc99e Initial load
duke
parents:
diff changeset
482 new_jvms = cg->generate(kit.sync_jvms());
a61af66fc99e Initial load
duke
parents:
diff changeset
483 }
a61af66fc99e Initial load
duke
parents:
diff changeset
484 kit.add_exception_states_from(new_jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
485 kit.set_jvms(new_jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
486
a61af66fc99e Initial load
duke
parents:
diff changeset
487 // Need to merge slow and fast?
a61af66fc99e Initial load
duke
parents:
diff changeset
488 if (slow_map == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
489 // The fast path is the only path remaining.
a61af66fc99e Initial load
duke
parents:
diff changeset
490 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
491 }
a61af66fc99e Initial load
duke
parents:
diff changeset
492
a61af66fc99e Initial load
duke
parents:
diff changeset
493 if (kit.stopped()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
494 // Inlined method threw an exception, so it's just the slow path after all.
a61af66fc99e Initial load
duke
parents:
diff changeset
495 kit.set_jvms(slow_jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
496 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
497 }
a61af66fc99e Initial load
duke
parents:
diff changeset
498
a61af66fc99e Initial load
duke
parents:
diff changeset
499 // Finish the diamond.
a61af66fc99e Initial load
duke
parents:
diff changeset
500 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
501 RegionNode* region = new (kit.C, 3) RegionNode(3);
a61af66fc99e Initial load
duke
parents:
diff changeset
502 region->init_req(1, kit.control());
a61af66fc99e Initial load
duke
parents:
diff changeset
503 region->init_req(2, slow_map->control());
a61af66fc99e Initial load
duke
parents:
diff changeset
504 kit.set_control(gvn.transform(region));
a61af66fc99e Initial load
duke
parents:
diff changeset
505 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
a61af66fc99e Initial load
duke
parents:
diff changeset
506 iophi->set_req(2, slow_map->i_o());
a61af66fc99e Initial load
duke
parents:
diff changeset
507 kit.set_i_o(gvn.transform(iophi));
a61af66fc99e Initial load
duke
parents:
diff changeset
508 kit.merge_memory(slow_map->merged_memory(), region, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
509 uint tos = kit.jvms()->stkoff() + kit.sp();
a61af66fc99e Initial load
duke
parents:
diff changeset
510 uint limit = slow_map->req();
a61af66fc99e Initial load
duke
parents:
diff changeset
511 for (uint i = TypeFunc::Parms; i < limit; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
512 // Skip unused stack slots; fast forward to monoff();
a61af66fc99e Initial load
duke
parents:
diff changeset
513 if (i == tos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
514 i = kit.jvms()->monoff();
a61af66fc99e Initial load
duke
parents:
diff changeset
515 if( i >= limit ) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
516 }
a61af66fc99e Initial load
duke
parents:
diff changeset
517 Node* m = kit.map()->in(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
518 Node* n = slow_map->in(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
519 if (m != n) {
a61af66fc99e Initial load
duke
parents:
diff changeset
520 const Type* t = gvn.type(m)->meet(gvn.type(n));
a61af66fc99e Initial load
duke
parents:
diff changeset
521 Node* phi = PhiNode::make(region, m, t);
a61af66fc99e Initial load
duke
parents:
diff changeset
522 phi->set_req(2, n);
a61af66fc99e Initial load
duke
parents:
diff changeset
523 kit.map()->set_req(i, gvn.transform(phi));
a61af66fc99e Initial load
duke
parents:
diff changeset
524 }
a61af66fc99e Initial load
duke
parents:
diff changeset
525 }
a61af66fc99e Initial load
duke
parents:
diff changeset
526 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
527 }
a61af66fc99e Initial load
duke
parents:
diff changeset
528
a61af66fc99e Initial load
duke
parents:
diff changeset
529
a61af66fc99e Initial load
duke
parents:
diff changeset
530 //-------------------------UncommonTrapCallGenerator-----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
531 // Internal class which handles all out-of-line calls checking receiver type.
a61af66fc99e Initial load
duke
parents:
diff changeset
532 class UncommonTrapCallGenerator : public CallGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
533 Deoptimization::DeoptReason _reason;
a61af66fc99e Initial load
duke
parents:
diff changeset
534 Deoptimization::DeoptAction _action;
a61af66fc99e Initial load
duke
parents:
diff changeset
535
a61af66fc99e Initial load
duke
parents:
diff changeset
536 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
537 UncommonTrapCallGenerator(ciMethod* m,
a61af66fc99e Initial load
duke
parents:
diff changeset
538 Deoptimization::DeoptReason reason,
a61af66fc99e Initial load
duke
parents:
diff changeset
539 Deoptimization::DeoptAction action)
a61af66fc99e Initial load
duke
parents:
diff changeset
540 : CallGenerator(m)
a61af66fc99e Initial load
duke
parents:
diff changeset
541 {
a61af66fc99e Initial load
duke
parents:
diff changeset
542 _reason = reason;
a61af66fc99e Initial load
duke
parents:
diff changeset
543 _action = action;
a61af66fc99e Initial load
duke
parents:
diff changeset
544 }
a61af66fc99e Initial load
duke
parents:
diff changeset
545
a61af66fc99e Initial load
duke
parents:
diff changeset
546 virtual bool is_virtual() const { ShouldNotReachHere(); return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
547 virtual bool is_trap() const { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
548
a61af66fc99e Initial load
duke
parents:
diff changeset
549 virtual JVMState* generate(JVMState* jvms);
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 CallGenerator*
a61af66fc99e Initial load
duke
parents:
diff changeset
554 CallGenerator::for_uncommon_trap(ciMethod* m,
a61af66fc99e Initial load
duke
parents:
diff changeset
555 Deoptimization::DeoptReason reason,
a61af66fc99e Initial load
duke
parents:
diff changeset
556 Deoptimization::DeoptAction action) {
a61af66fc99e Initial load
duke
parents:
diff changeset
557 return new UncommonTrapCallGenerator(m, reason, action);
a61af66fc99e Initial load
duke
parents:
diff changeset
558 }
a61af66fc99e Initial load
duke
parents:
diff changeset
559
a61af66fc99e Initial load
duke
parents:
diff changeset
560
a61af66fc99e Initial load
duke
parents:
diff changeset
561 JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) {
a61af66fc99e Initial load
duke
parents:
diff changeset
562 GraphKit kit(jvms);
a61af66fc99e Initial load
duke
parents:
diff changeset
563 // Take the trap with arguments pushed on the stack. (Cf. null_check_receiver).
a61af66fc99e Initial load
duke
parents:
diff changeset
564 int nargs = method()->arg_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
565 kit.inc_sp(nargs);
a61af66fc99e Initial load
duke
parents:
diff changeset
566 assert(nargs <= kit.sp() && kit.sp() <= jvms->stk_size(), "sane sp w/ args pushed");
a61af66fc99e Initial load
duke
parents:
diff changeset
567 if (_reason == Deoptimization::Reason_class_check &&
a61af66fc99e Initial load
duke
parents:
diff changeset
568 _action == Deoptimization::Action_maybe_recompile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
569 // Temp fix for 6529811
a61af66fc99e Initial load
duke
parents:
diff changeset
570 // Don't allow uncommon_trap to override our decision to recompile in the event
a61af66fc99e Initial load
duke
parents:
diff changeset
571 // of a class cast failure for a monomorphic call as it will never let us convert
a61af66fc99e Initial load
duke
parents:
diff changeset
572 // the call to either bi-morphic or megamorphic and can lead to unc-trap loops
a61af66fc99e Initial load
duke
parents:
diff changeset
573 bool keep_exact_action = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
574 kit.uncommon_trap(_reason, _action, NULL, "monomorphic vcall checkcast", false, keep_exact_action);
a61af66fc99e Initial load
duke
parents:
diff changeset
575 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
576 kit.uncommon_trap(_reason, _action);
a61af66fc99e Initial load
duke
parents:
diff changeset
577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
578 return kit.transfer_exceptions_into_jvms();
a61af66fc99e Initial load
duke
parents:
diff changeset
579 }
a61af66fc99e Initial load
duke
parents:
diff changeset
580
a61af66fc99e Initial load
duke
parents:
diff changeset
581 // (Note: Moved hook_up_call to GraphKit::set_edges_for_java_call.)
a61af66fc99e Initial load
duke
parents:
diff changeset
582
a61af66fc99e Initial load
duke
parents:
diff changeset
583 // (Node: Merged hook_up_exits into ParseGenerator::generate.)
a61af66fc99e Initial load
duke
parents:
diff changeset
584
a61af66fc99e Initial load
duke
parents:
diff changeset
585 #define NODES_OVERHEAD_PER_METHOD (30.0)
a61af66fc99e Initial load
duke
parents:
diff changeset
586 #define NODES_PER_BYTECODE (9.5)
a61af66fc99e Initial load
duke
parents:
diff changeset
587
a61af66fc99e Initial load
duke
parents:
diff changeset
588 void WarmCallInfo::init(JVMState* call_site, ciMethod* call_method, ciCallProfile& profile, float prof_factor) {
a61af66fc99e Initial load
duke
parents:
diff changeset
589 int call_count = profile.count();
a61af66fc99e Initial load
duke
parents:
diff changeset
590 int code_size = call_method->code_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
591
a61af66fc99e Initial load
duke
parents:
diff changeset
592 // Expected execution count is based on the historical count:
a61af66fc99e Initial load
duke
parents:
diff changeset
593 _count = call_count < 0 ? 1 : call_site->method()->scale_count(call_count, prof_factor);
a61af66fc99e Initial load
duke
parents:
diff changeset
594
a61af66fc99e Initial load
duke
parents:
diff changeset
595 // Expected profit from inlining, in units of simple call-overheads.
a61af66fc99e Initial load
duke
parents:
diff changeset
596 _profit = 1.0;
a61af66fc99e Initial load
duke
parents:
diff changeset
597
a61af66fc99e Initial load
duke
parents:
diff changeset
598 // Expected work performed by the call in units of call-overheads.
a61af66fc99e Initial load
duke
parents:
diff changeset
599 // %%% need an empirical curve fit for "work" (time in call)
a61af66fc99e Initial load
duke
parents:
diff changeset
600 float bytecodes_per_call = 3;
a61af66fc99e Initial load
duke
parents:
diff changeset
601 _work = 1.0 + code_size / bytecodes_per_call;
a61af66fc99e Initial load
duke
parents:
diff changeset
602
a61af66fc99e Initial load
duke
parents:
diff changeset
603 // Expected size of compilation graph:
a61af66fc99e Initial load
duke
parents:
diff changeset
604 // -XX:+PrintParseStatistics once reported:
a61af66fc99e Initial load
duke
parents:
diff changeset
605 // Methods seen: 9184 Methods parsed: 9184 Nodes created: 1582391
a61af66fc99e Initial load
duke
parents:
diff changeset
606 // Histogram of 144298 parsed bytecodes:
a61af66fc99e Initial load
duke
parents:
diff changeset
607 // %%% Need an better predictor for graph size.
a61af66fc99e Initial load
duke
parents:
diff changeset
608 _size = NODES_OVERHEAD_PER_METHOD + (NODES_PER_BYTECODE * code_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
609 }
a61af66fc99e Initial load
duke
parents:
diff changeset
610
a61af66fc99e Initial load
duke
parents:
diff changeset
611 // is_cold: Return true if the node should never be inlined.
a61af66fc99e Initial load
duke
parents:
diff changeset
612 // This is true if any of the key metrics are extreme.
a61af66fc99e Initial load
duke
parents:
diff changeset
613 bool WarmCallInfo::is_cold() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
614 if (count() < WarmCallMinCount) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
615 if (profit() < WarmCallMinProfit) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
616 if (work() > WarmCallMaxWork) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
617 if (size() > WarmCallMaxSize) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
618 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
619 }
a61af66fc99e Initial load
duke
parents:
diff changeset
620
a61af66fc99e Initial load
duke
parents:
diff changeset
621 // is_hot: Return true if the node should be inlined immediately.
a61af66fc99e Initial load
duke
parents:
diff changeset
622 // This is true if any of the key metrics are extreme.
a61af66fc99e Initial load
duke
parents:
diff changeset
623 bool WarmCallInfo::is_hot() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
624 assert(!is_cold(), "eliminate is_cold cases before testing is_hot");
a61af66fc99e Initial load
duke
parents:
diff changeset
625 if (count() >= HotCallCountThreshold) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
626 if (profit() >= HotCallProfitThreshold) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
627 if (work() <= HotCallTrivialWork) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
628 if (size() <= HotCallTrivialSize) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
629 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
631
a61af66fc99e Initial load
duke
parents:
diff changeset
632 // compute_heat:
a61af66fc99e Initial load
duke
parents:
diff changeset
633 float WarmCallInfo::compute_heat() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
634 assert(!is_cold(), "compute heat only on warm nodes");
a61af66fc99e Initial load
duke
parents:
diff changeset
635 assert(!is_hot(), "compute heat only on warm nodes");
a61af66fc99e Initial load
duke
parents:
diff changeset
636 int min_size = MAX2(0, (int)HotCallTrivialSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
637 int max_size = MIN2(500, (int)WarmCallMaxSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
638 float method_size = (size() - min_size) / MAX2(1, max_size - min_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
639 float size_factor;
a61af66fc99e Initial load
duke
parents:
diff changeset
640 if (method_size < 0.05) size_factor = 4; // 2 sigmas better than avg.
a61af66fc99e Initial load
duke
parents:
diff changeset
641 else if (method_size < 0.15) size_factor = 2; // 1 sigma better than avg.
a61af66fc99e Initial load
duke
parents:
diff changeset
642 else if (method_size < 0.5) size_factor = 1; // better than avg.
a61af66fc99e Initial load
duke
parents:
diff changeset
643 else size_factor = 0.5; // worse than avg.
a61af66fc99e Initial load
duke
parents:
diff changeset
644 return (count() * profit() * size_factor);
a61af66fc99e Initial load
duke
parents:
diff changeset
645 }
a61af66fc99e Initial load
duke
parents:
diff changeset
646
a61af66fc99e Initial load
duke
parents:
diff changeset
647 bool WarmCallInfo::warmer_than(WarmCallInfo* that) {
a61af66fc99e Initial load
duke
parents:
diff changeset
648 assert(this != that, "compare only different WCIs");
a61af66fc99e Initial load
duke
parents:
diff changeset
649 assert(this->heat() != 0 && that->heat() != 0, "call compute_heat 1st");
a61af66fc99e Initial load
duke
parents:
diff changeset
650 if (this->heat() > that->heat()) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
651 if (this->heat() < that->heat()) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
652 assert(this->heat() == that->heat(), "no NaN heat allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
653 // Equal heat. Break the tie some other way.
a61af66fc99e Initial load
duke
parents:
diff changeset
654 if (!this->call() || !that->call()) return (address)this > (address)that;
a61af66fc99e Initial load
duke
parents:
diff changeset
655 return this->call()->_idx > that->call()->_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
656 }
a61af66fc99e Initial load
duke
parents:
diff changeset
657
a61af66fc99e Initial load
duke
parents:
diff changeset
658 //#define UNINIT_NEXT ((WarmCallInfo*)badAddress)
a61af66fc99e Initial load
duke
parents:
diff changeset
659 #define UNINIT_NEXT ((WarmCallInfo*)NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
660
a61af66fc99e Initial load
duke
parents:
diff changeset
661 WarmCallInfo* WarmCallInfo::insert_into(WarmCallInfo* head) {
a61af66fc99e Initial load
duke
parents:
diff changeset
662 assert(next() == UNINIT_NEXT, "not yet on any list");
a61af66fc99e Initial load
duke
parents:
diff changeset
663 WarmCallInfo* prev_p = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
664 WarmCallInfo* next_p = head;
a61af66fc99e Initial load
duke
parents:
diff changeset
665 while (next_p != NULL && next_p->warmer_than(this)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
666 prev_p = next_p;
a61af66fc99e Initial load
duke
parents:
diff changeset
667 next_p = prev_p->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
668 }
a61af66fc99e Initial load
duke
parents:
diff changeset
669 // Install this between prev_p and next_p.
a61af66fc99e Initial load
duke
parents:
diff changeset
670 this->set_next(next_p);
a61af66fc99e Initial load
duke
parents:
diff changeset
671 if (prev_p == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
672 head = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
673 else
a61af66fc99e Initial load
duke
parents:
diff changeset
674 prev_p->set_next(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
675 return head;
a61af66fc99e Initial load
duke
parents:
diff changeset
676 }
a61af66fc99e Initial load
duke
parents:
diff changeset
677
a61af66fc99e Initial load
duke
parents:
diff changeset
678 WarmCallInfo* WarmCallInfo::remove_from(WarmCallInfo* head) {
a61af66fc99e Initial load
duke
parents:
diff changeset
679 WarmCallInfo* prev_p = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
680 WarmCallInfo* next_p = head;
a61af66fc99e Initial load
duke
parents:
diff changeset
681 while (next_p != this) {
a61af66fc99e Initial load
duke
parents:
diff changeset
682 assert(next_p != NULL, "this must be in the list somewhere");
a61af66fc99e Initial load
duke
parents:
diff changeset
683 prev_p = next_p;
a61af66fc99e Initial load
duke
parents:
diff changeset
684 next_p = prev_p->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
685 }
a61af66fc99e Initial load
duke
parents:
diff changeset
686 next_p = this->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
687 debug_only(this->set_next(UNINIT_NEXT));
a61af66fc99e Initial load
duke
parents:
diff changeset
688 // Remove this from between prev_p and next_p.
a61af66fc99e Initial load
duke
parents:
diff changeset
689 if (prev_p == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
690 head = next_p;
a61af66fc99e Initial load
duke
parents:
diff changeset
691 else
a61af66fc99e Initial load
duke
parents:
diff changeset
692 prev_p->set_next(next_p);
a61af66fc99e Initial load
duke
parents:
diff changeset
693 return head;
a61af66fc99e Initial load
duke
parents:
diff changeset
694 }
a61af66fc99e Initial load
duke
parents:
diff changeset
695
a61af66fc99e Initial load
duke
parents:
diff changeset
696 WarmCallInfo* WarmCallInfo::_always_hot = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
697 WarmCallInfo* WarmCallInfo::_always_cold = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
698
a61af66fc99e Initial load
duke
parents:
diff changeset
699 WarmCallInfo* WarmCallInfo::always_hot() {
a61af66fc99e Initial load
duke
parents:
diff changeset
700 if (_always_hot == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
701 static double bits[sizeof(WarmCallInfo) / sizeof(double) + 1] = {0};
a61af66fc99e Initial load
duke
parents:
diff changeset
702 WarmCallInfo* ci = (WarmCallInfo*) bits;
a61af66fc99e Initial load
duke
parents:
diff changeset
703 ci->_profit = ci->_count = MAX_VALUE();
a61af66fc99e Initial load
duke
parents:
diff changeset
704 ci->_work = ci->_size = MIN_VALUE();
a61af66fc99e Initial load
duke
parents:
diff changeset
705 _always_hot = ci;
a61af66fc99e Initial load
duke
parents:
diff changeset
706 }
a61af66fc99e Initial load
duke
parents:
diff changeset
707 assert(_always_hot->is_hot(), "must always be hot");
a61af66fc99e Initial load
duke
parents:
diff changeset
708 return _always_hot;
a61af66fc99e Initial load
duke
parents:
diff changeset
709 }
a61af66fc99e Initial load
duke
parents:
diff changeset
710
a61af66fc99e Initial load
duke
parents:
diff changeset
711 WarmCallInfo* WarmCallInfo::always_cold() {
a61af66fc99e Initial load
duke
parents:
diff changeset
712 if (_always_cold == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
713 static double bits[sizeof(WarmCallInfo) / sizeof(double) + 1] = {0};
a61af66fc99e Initial load
duke
parents:
diff changeset
714 WarmCallInfo* ci = (WarmCallInfo*) bits;
a61af66fc99e Initial load
duke
parents:
diff changeset
715 ci->_profit = ci->_count = MIN_VALUE();
a61af66fc99e Initial load
duke
parents:
diff changeset
716 ci->_work = ci->_size = MAX_VALUE();
a61af66fc99e Initial load
duke
parents:
diff changeset
717 _always_cold = ci;
a61af66fc99e Initial load
duke
parents:
diff changeset
718 }
a61af66fc99e Initial load
duke
parents:
diff changeset
719 assert(_always_cold->is_cold(), "must always be cold");
a61af66fc99e Initial load
duke
parents:
diff changeset
720 return _always_cold;
a61af66fc99e Initial load
duke
parents:
diff changeset
721 }
a61af66fc99e Initial load
duke
parents:
diff changeset
722
a61af66fc99e Initial load
duke
parents:
diff changeset
723
a61af66fc99e Initial load
duke
parents:
diff changeset
724 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
725
a61af66fc99e Initial load
duke
parents:
diff changeset
726 void WarmCallInfo::print() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
727 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
728 is_cold() ? "cold" : is_hot() ? "hot " : "warm",
a61af66fc99e Initial load
duke
parents:
diff changeset
729 count(), profit(), work(), size(), compute_heat(), next());
a61af66fc99e Initial load
duke
parents:
diff changeset
730 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
731 if (call() != NULL) call()->dump();
a61af66fc99e Initial load
duke
parents:
diff changeset
732 }
a61af66fc99e Initial load
duke
parents:
diff changeset
733
a61af66fc99e Initial load
duke
parents:
diff changeset
734 void print_wci(WarmCallInfo* ci) {
a61af66fc99e Initial load
duke
parents:
diff changeset
735 ci->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
736 }
a61af66fc99e Initial load
duke
parents:
diff changeset
737
a61af66fc99e Initial load
duke
parents:
diff changeset
738 void WarmCallInfo::print_all() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
739 for (const WarmCallInfo* p = this; p != NULL; p = p->next())
a61af66fc99e Initial load
duke
parents:
diff changeset
740 p->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
741 }
a61af66fc99e Initial load
duke
parents:
diff changeset
742
a61af66fc99e Initial load
duke
parents:
diff changeset
743 int WarmCallInfo::count_all() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
744 int cnt = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
745 for (const WarmCallInfo* p = this; p != NULL; p = p->next())
a61af66fc99e Initial load
duke
parents:
diff changeset
746 cnt++;
a61af66fc99e Initial load
duke
parents:
diff changeset
747 return cnt;
a61af66fc99e Initial load
duke
parents:
diff changeset
748 }
a61af66fc99e Initial load
duke
parents:
diff changeset
749
a61af66fc99e Initial load
duke
parents:
diff changeset
750 #endif //PRODUCT