annotate src/share/vm/opto/callGenerator.hpp @ 9126:bc26f978b0ce

HotSpotResolvedObjectType: implement hasFinalizeSubclass() correctly don't use the (wrong) cached value, but ask the runtime on each request. Fixes regression on xml.* benchmarks @ specjvm2008. The problem was: After the constructor of Object was deoptimized due to an assumption violation, it was recompiled again after some time. However, on recompilation, the value of hasFinalizeSubclass for the class was not updated and it was compiled again with a, now wrong, assumption, which then triggers deoptimization again. This was repeated until it hit the recompilation limit (defined by PerMethodRecompilationCutoff), and therefore only executed by the interpreter from now on, causing the performance regression.
author Bernhard Urban <bernhard.urban@jku.at>
date Mon, 15 Apr 2013 19:54:58 +0200
parents 989155e2d07a
children 836a62f43af9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
6842
b9a9ed0f8eeb 7197424: update copyright year to match last edit in jdk8 hotspot repository
mikael
parents: 6266
diff changeset
2 * Copyright (c) 2000, 2012, 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: 1138
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1138
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: 1138
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
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
25 #ifndef SHARE_VM_OPTO_CALLGENERATOR_HPP
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
26 #define SHARE_VM_OPTO_CALLGENERATOR_HPP
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
27
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
28 #include "compiler/compileBroker.hpp"
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
29 #include "opto/callnode.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
30 #include "opto/compile.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
31 #include "opto/type.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
32 #include "runtime/deoptimization.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
33
0
a61af66fc99e Initial load
duke
parents:
diff changeset
34 //---------------------------CallGenerator-------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
35 // The subclasses of this class handle generation of ideal nodes for
a61af66fc99e Initial load
duke
parents:
diff changeset
36 // call sites and method entry points.
a61af66fc99e Initial load
duke
parents:
diff changeset
37
a61af66fc99e Initial load
duke
parents:
diff changeset
38 class CallGenerator : public ResourceObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
39 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
40 enum {
a61af66fc99e Initial load
duke
parents:
diff changeset
41 xxxunusedxxx
a61af66fc99e Initial load
duke
parents:
diff changeset
42 };
a61af66fc99e Initial load
duke
parents:
diff changeset
43
a61af66fc99e Initial load
duke
parents:
diff changeset
44 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
45 ciMethod* _method; // The method being called.
a61af66fc99e Initial load
duke
parents:
diff changeset
46
a61af66fc99e Initial load
duke
parents:
diff changeset
47 protected:
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
48 CallGenerator(ciMethod* method) : _method(method) {}
0
a61af66fc99e Initial load
duke
parents:
diff changeset
49
a61af66fc99e Initial load
duke
parents:
diff changeset
50 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
51 // Accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
52 ciMethod* method() const { return _method; }
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 // is_inline: At least some code implementing the method is copied here.
a61af66fc99e Initial load
duke
parents:
diff changeset
55 virtual bool is_inline() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
56 // is_intrinsic: There's a method-specific way of generating the inline code.
a61af66fc99e Initial load
duke
parents:
diff changeset
57 virtual bool is_intrinsic() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
58 // is_parse: Bytecodes implementing the specific method are copied here.
a61af66fc99e Initial load
duke
parents:
diff changeset
59 virtual bool is_parse() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
60 // is_virtual: The call uses the receiver type to select or check the method.
a61af66fc99e Initial load
duke
parents:
diff changeset
61 virtual bool is_virtual() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // is_deferred: The decision whether to inline or not is deferred.
a61af66fc99e Initial load
duke
parents:
diff changeset
63 virtual bool is_deferred() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
64 // is_predicted: Uses an explicit check against a predicted type.
a61af66fc99e Initial load
duke
parents:
diff changeset
65 virtual bool is_predicted() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
66 // is_trap: Does not return to the caller. (E.g., uncommon trap.)
a61af66fc99e Initial load
duke
parents:
diff changeset
67 virtual bool is_trap() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
68
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
69 // is_late_inline: supports conversion of call into an inline
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
70 virtual bool is_late_inline() const { return false; }
7473
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
71 // same but for method handle calls
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
72 virtual bool is_mh_late_inline() const { return false; }
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
73
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
74 // for method handle calls: have we tried inlinining the call already?
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
75 virtual bool already_attempted() const { ShouldNotReachHere(); return false; }
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
76
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
77 // Replace the call with an inline version of the code
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
78 virtual void do_late_inline() { ShouldNotReachHere(); }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
79
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
80 virtual CallStaticJavaNode* call_node() const { ShouldNotReachHere(); return NULL; }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
81
0
a61af66fc99e Initial load
duke
parents:
diff changeset
82 // Note: It is possible for a CG to be both inline and virtual.
a61af66fc99e Initial load
duke
parents:
diff changeset
83 // (The hashCode intrinsic does a vtable check and an inlined fast path.)
a61af66fc99e Initial load
duke
parents:
diff changeset
84
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // Utilities:
a61af66fc99e Initial load
duke
parents:
diff changeset
86 const TypeFunc* tf() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
87
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // The given jvms has state and arguments for a call to my method.
a61af66fc99e Initial load
duke
parents:
diff changeset
89 // Edges after jvms->argoff() carry all (pre-popped) argument values.
a61af66fc99e Initial load
duke
parents:
diff changeset
90 //
a61af66fc99e Initial load
duke
parents:
diff changeset
91 // Update the map with state and return values (if any) and return it.
a61af66fc99e Initial load
duke
parents:
diff changeset
92 // The return values (0, 1, or 2) must be pushed on the map's stack,
a61af66fc99e Initial load
duke
parents:
diff changeset
93 // and the sp of the jvms incremented accordingly.
a61af66fc99e Initial load
duke
parents:
diff changeset
94 //
a61af66fc99e Initial load
duke
parents:
diff changeset
95 // The jvms is returned on success. Alternatively, a copy of the
a61af66fc99e Initial load
duke
parents:
diff changeset
96 // given jvms, suitably updated, may be returned, in which case the
a61af66fc99e Initial load
duke
parents:
diff changeset
97 // caller should discard the original jvms.
a61af66fc99e Initial load
duke
parents:
diff changeset
98 //
a61af66fc99e Initial load
duke
parents:
diff changeset
99 // The non-Parm edges of the returned map will contain updated global state,
a61af66fc99e Initial load
duke
parents:
diff changeset
100 // and one or two edges before jvms->sp() will carry any return values.
a61af66fc99e Initial load
duke
parents:
diff changeset
101 // Other map edges may contain locals or monitors, and should not
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // be changed in meaning.
a61af66fc99e Initial load
duke
parents:
diff changeset
103 //
a61af66fc99e Initial load
duke
parents:
diff changeset
104 // If the call traps, the returned map must have a control edge of top.
a61af66fc99e Initial load
duke
parents:
diff changeset
105 // If the call can throw, the returned map must report has_exceptions().
a61af66fc99e Initial load
duke
parents:
diff changeset
106 //
a61af66fc99e Initial load
duke
parents:
diff changeset
107 // If the result is NULL, it means that this CallGenerator was unable
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // to handle the given call, and another CallGenerator should be consulted.
a61af66fc99e Initial load
duke
parents:
diff changeset
109 virtual JVMState* generate(JVMState* jvms) = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
110
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // How to generate a call site that is inlined:
a61af66fc99e Initial load
duke
parents:
diff changeset
112 static CallGenerator* for_inline(ciMethod* m, float expected_uses = -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // How to generate code for an on-stack replacement handler.
a61af66fc99e Initial load
duke
parents:
diff changeset
114 static CallGenerator* for_osr(ciMethod* m, int osr_bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
115
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // How to generate vanilla out-of-line call sites:
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
117 static CallGenerator* for_direct_call(ciMethod* m, bool separate_io_projs = false); // static, special
4117
a04a201f0f5a 7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents: 3852
diff changeset
118 static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface
1137
97125851f396 6829187: compiler optimizations required for JSR 292
twisti
parents: 1080
diff changeset
119 static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic
4117
a04a201f0f5a 7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents: 3852
diff changeset
120
7473
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
121 static CallGenerator* for_method_handle_call( JVMState* jvms, ciMethod* caller, ciMethod* callee, bool delayed_forbidden);
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
122 static CallGenerator* for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool& input_not_const);
3441
f56542cb325a 7050554: JSR 292 - need optimization for selectAlternative
never
parents: 2443
diff changeset
123
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
124 // How to generate a replace a direct call with an inline version
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
125 static CallGenerator* for_late_inline(ciMethod* m, CallGenerator* inline_cg);
7473
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
126 static CallGenerator* for_mh_late_inline(ciMethod* caller, ciMethod* callee, bool input_not_const);
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
127 static CallGenerator* for_string_late_inline(ciMethod* m, CallGenerator* inline_cg);
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
128
0
a61af66fc99e Initial load
duke
parents:
diff changeset
129 // How to make a call but defer the decision whether to inline or not.
a61af66fc99e Initial load
duke
parents:
diff changeset
130 static CallGenerator* for_warm_call(WarmCallInfo* ci,
a61af66fc99e Initial load
duke
parents:
diff changeset
131 CallGenerator* if_cold,
a61af66fc99e Initial load
duke
parents:
diff changeset
132 CallGenerator* if_hot);
a61af66fc99e Initial load
duke
parents:
diff changeset
133
a61af66fc99e Initial load
duke
parents:
diff changeset
134 // How to make a call that optimistically assumes a receiver type:
a61af66fc99e Initial load
duke
parents:
diff changeset
135 static CallGenerator* for_predicted_call(ciKlass* predicted_receiver,
a61af66fc99e Initial load
duke
parents:
diff changeset
136 CallGenerator* if_missed,
a61af66fc99e Initial load
duke
parents:
diff changeset
137 CallGenerator* if_hit,
a61af66fc99e Initial load
duke
parents:
diff changeset
138 float hit_prob);
a61af66fc99e Initial load
duke
parents:
diff changeset
139
1138
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
140 // How to make a call that optimistically assumes a MethodHandle target:
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
141 static CallGenerator* for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
142 CallGenerator* if_missed,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
143 CallGenerator* if_hit,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
144 float hit_prob);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
145
0
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // How to make a call that gives up and goes back to the interpreter:
a61af66fc99e Initial load
duke
parents:
diff changeset
147 static CallGenerator* for_uncommon_trap(ciMethod* m,
a61af66fc99e Initial load
duke
parents:
diff changeset
148 Deoptimization::DeoptReason reason,
a61af66fc99e Initial load
duke
parents:
diff changeset
149 Deoptimization::DeoptAction action);
a61af66fc99e Initial load
duke
parents:
diff changeset
150
a61af66fc99e Initial load
duke
parents:
diff changeset
151 // Registry for intrinsics:
a61af66fc99e Initial load
duke
parents:
diff changeset
152 static CallGenerator* for_intrinsic(ciMethod* m);
a61af66fc99e Initial load
duke
parents:
diff changeset
153 static void register_intrinsic(ciMethod* m, CallGenerator* cg);
6894
a3ecd773a7b9 7184394: add intrinsics to use AES instructions
kvn
parents: 6842
diff changeset
154 static CallGenerator* for_predicted_intrinsic(CallGenerator* intrinsic,
a3ecd773a7b9 7184394: add intrinsics to use AES instructions
kvn
parents: 6842
diff changeset
155 CallGenerator* cg);
a3ecd773a7b9 7184394: add intrinsics to use AES instructions
kvn
parents: 6842
diff changeset
156 virtual Node* generate_predicate(JVMState* jvms) { return NULL; };
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
157
7473
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
158 virtual void print_inlining_late(const char* msg) { ShouldNotReachHere(); }
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
159
7421
ad5dd04754ee 8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents: 6894
diff changeset
160 static void print_inlining(Compile* C, ciMethod* callee, int inline_level, int bci, const char* msg) {
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
161 if (PrintInlining)
7421
ad5dd04754ee 8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents: 6894
diff changeset
162 C->print_inlining(callee, inline_level, bci, msg);
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
163 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
164 };
a61af66fc99e Initial load
duke
parents:
diff changeset
165
a61af66fc99e Initial load
duke
parents:
diff changeset
166
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
167 //------------------------InlineCallGenerator----------------------------------
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
168 class InlineCallGenerator : public CallGenerator {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
169 protected:
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
170 InlineCallGenerator(ciMethod* method) : CallGenerator(method) {}
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
171
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
172 public:
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
173 virtual bool is_inline() const { return true; }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
174 };
a61af66fc99e Initial load
duke
parents:
diff changeset
175
a61af66fc99e Initial load
duke
parents:
diff changeset
176
a61af66fc99e Initial load
duke
parents:
diff changeset
177 //---------------------------WarmCallInfo--------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
178 // A struct to collect information about a given call site.
a61af66fc99e Initial load
duke
parents:
diff changeset
179 // Helps sort call sites into "hot", "medium", and "cold".
a61af66fc99e Initial load
duke
parents:
diff changeset
180 // Participates in the queueing of "medium" call sites for possible inlining.
a61af66fc99e Initial load
duke
parents:
diff changeset
181 class WarmCallInfo : public ResourceObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
182 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
183
a61af66fc99e Initial load
duke
parents:
diff changeset
184 CallNode* _call; // The CallNode which may be inlined.
a61af66fc99e Initial load
duke
parents:
diff changeset
185 CallGenerator* _hot_cg;// CG for expanding the call node
a61af66fc99e Initial load
duke
parents:
diff changeset
186
a61af66fc99e Initial load
duke
parents:
diff changeset
187 // These are the metrics we use to evaluate call sites:
a61af66fc99e Initial load
duke
parents:
diff changeset
188
a61af66fc99e Initial load
duke
parents:
diff changeset
189 float _count; // How often do we expect to reach this site?
a61af66fc99e Initial load
duke
parents:
diff changeset
190 float _profit; // How much time do we expect to save by inlining?
a61af66fc99e Initial load
duke
parents:
diff changeset
191 float _work; // How long do we expect the average call to take?
a61af66fc99e Initial load
duke
parents:
diff changeset
192 float _size; // How big do we expect the inlined code to be?
a61af66fc99e Initial load
duke
parents:
diff changeset
193
a61af66fc99e Initial load
duke
parents:
diff changeset
194 float _heat; // Combined score inducing total order on call sites.
a61af66fc99e Initial load
duke
parents:
diff changeset
195 WarmCallInfo* _next; // Next cooler call info in pending queue.
a61af66fc99e Initial load
duke
parents:
diff changeset
196
a61af66fc99e Initial load
duke
parents:
diff changeset
197 // Count is the number of times this call site is expected to be executed.
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // Large count is favorable for inlining, because the extra compilation
a61af66fc99e Initial load
duke
parents:
diff changeset
199 // work will be amortized more completely.
a61af66fc99e Initial load
duke
parents:
diff changeset
200
a61af66fc99e Initial load
duke
parents:
diff changeset
201 // Profit is a rough measure of the amount of time we expect to save
a61af66fc99e Initial load
duke
parents:
diff changeset
202 // per execution of this site if we inline it. (1.0 == call overhead)
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // Large profit favors inlining. Negative profit disables inlining.
a61af66fc99e Initial load
duke
parents:
diff changeset
204
a61af66fc99e Initial load
duke
parents:
diff changeset
205 // Work is a rough measure of the amount of time a typical out-of-line
a61af66fc99e Initial load
duke
parents:
diff changeset
206 // call from this site is expected to take. (1.0 == call, no-op, return)
a61af66fc99e Initial load
duke
parents:
diff changeset
207 // Small work is somewhat favorable for inlining, since methods with
a61af66fc99e Initial load
duke
parents:
diff changeset
208 // short "hot" traces are more likely to inline smoothly.
a61af66fc99e Initial load
duke
parents:
diff changeset
209
a61af66fc99e Initial load
duke
parents:
diff changeset
210 // Size is the number of graph nodes we expect this method to produce,
a61af66fc99e Initial load
duke
parents:
diff changeset
211 // not counting the inlining of any further warm calls it may include.
a61af66fc99e Initial load
duke
parents:
diff changeset
212 // Small size favors inlining, since small methods are more likely to
a61af66fc99e Initial load
duke
parents:
diff changeset
213 // inline smoothly. The size is estimated by examining the native code
a61af66fc99e Initial load
duke
parents:
diff changeset
214 // if available. The method bytecodes are also examined, assuming
a61af66fc99e Initial load
duke
parents:
diff changeset
215 // empirically observed node counts for each kind of bytecode.
a61af66fc99e Initial load
duke
parents:
diff changeset
216
a61af66fc99e Initial load
duke
parents:
diff changeset
217 // Heat is the combined "goodness" of a site's inlining. If we were
a61af66fc99e Initial load
duke
parents:
diff changeset
218 // omniscient, it would be the difference of two sums of future execution
a61af66fc99e Initial load
duke
parents:
diff changeset
219 // times of code emitted for this site (amortized across multiple sites if
a61af66fc99e Initial load
duke
parents:
diff changeset
220 // sharing applies). The two sums are for versions of this call site with
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // and without inlining.
a61af66fc99e Initial load
duke
parents:
diff changeset
222
a61af66fc99e Initial load
duke
parents:
diff changeset
223 // We approximate this mythical quantity by playing with averages,
a61af66fc99e Initial load
duke
parents:
diff changeset
224 // rough estimates, and assumptions that history repeats itself.
a61af66fc99e Initial load
duke
parents:
diff changeset
225 // The basic formula count * profit is heuristically adjusted
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // by looking at the expected compilation and execution times of
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // of the inlined call.
a61af66fc99e Initial load
duke
parents:
diff changeset
228
a61af66fc99e Initial load
duke
parents:
diff changeset
229 // Note: Some of these metrics may not be present in the final product,
a61af66fc99e Initial load
duke
parents:
diff changeset
230 // but exist in development builds to experiment with inline policy tuning.
a61af66fc99e Initial load
duke
parents:
diff changeset
231
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // This heuristic framework does not model well the very significant
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // effects of multiple-level inlining. It is possible to see no immediate
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // profit from inlining X->Y, but to get great profit from a subsequent
a61af66fc99e Initial load
duke
parents:
diff changeset
235 // inlining X->Y->Z.
a61af66fc99e Initial load
duke
parents:
diff changeset
236
a61af66fc99e Initial load
duke
parents:
diff changeset
237 // This framework does not take well into account the problem of N**2 code
a61af66fc99e Initial load
duke
parents:
diff changeset
238 // size in a clique of mutually inlinable methods.
a61af66fc99e Initial load
duke
parents:
diff changeset
239
a61af66fc99e Initial load
duke
parents:
diff changeset
240 WarmCallInfo* next() const { return _next; }
a61af66fc99e Initial load
duke
parents:
diff changeset
241 void set_next(WarmCallInfo* n) { _next = n; }
a61af66fc99e Initial load
duke
parents:
diff changeset
242
2443
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
243 static WarmCallInfo _always_hot;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
244 static WarmCallInfo _always_cold;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
245
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
246 // Constructor intitialization of always_hot and always_cold
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
247 WarmCallInfo(float c, float p, float w, float s) {
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
248 _call = NULL;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
249 _hot_cg = NULL;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
250 _next = NULL;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
251 _count = c;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
252 _profit = p;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
253 _work = w;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
254 _size = s;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
255 _heat = 0;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
256 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
257
a61af66fc99e Initial load
duke
parents:
diff changeset
258 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
259 // Because WarmInfo objects live over the entire lifetime of the
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // Compile object, they are allocated into the comp_arena, which
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // does not get resource marked or reset during the compile process
a61af66fc99e Initial load
duke
parents:
diff changeset
262 void *operator new( size_t x, Compile* C ) { return C->comp_arena()->Amalloc(x); }
a61af66fc99e Initial load
duke
parents:
diff changeset
263 void operator delete( void * ) { } // fast deallocation
a61af66fc99e Initial load
duke
parents:
diff changeset
264
a61af66fc99e Initial load
duke
parents:
diff changeset
265 static WarmCallInfo* always_hot();
a61af66fc99e Initial load
duke
parents:
diff changeset
266 static WarmCallInfo* always_cold();
a61af66fc99e Initial load
duke
parents:
diff changeset
267
a61af66fc99e Initial load
duke
parents:
diff changeset
268 WarmCallInfo() {
a61af66fc99e Initial load
duke
parents:
diff changeset
269 _call = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
270 _hot_cg = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
271 _next = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
272 _count = _profit = _work = _size = _heat = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
274
a61af66fc99e Initial load
duke
parents:
diff changeset
275 CallNode* call() const { return _call; }
a61af66fc99e Initial load
duke
parents:
diff changeset
276 float count() const { return _count; }
a61af66fc99e Initial load
duke
parents:
diff changeset
277 float size() const { return _size; }
a61af66fc99e Initial load
duke
parents:
diff changeset
278 float work() const { return _work; }
a61af66fc99e Initial load
duke
parents:
diff changeset
279 float profit() const { return _profit; }
a61af66fc99e Initial load
duke
parents:
diff changeset
280 float heat() const { return _heat; }
a61af66fc99e Initial load
duke
parents:
diff changeset
281
a61af66fc99e Initial load
duke
parents:
diff changeset
282 void set_count(float x) { _count = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
283 void set_size(float x) { _size = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
284 void set_work(float x) { _work = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
285 void set_profit(float x) { _profit = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
286 void set_heat(float x) { _heat = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
287
a61af66fc99e Initial load
duke
parents:
diff changeset
288 // Load initial heuristics from profiles, etc.
a61af66fc99e Initial load
duke
parents:
diff changeset
289 // The heuristics can be tweaked further by the caller.
a61af66fc99e Initial load
duke
parents:
diff changeset
290 void init(JVMState* call_site, ciMethod* call_method, ciCallProfile& profile, float prof_factor);
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 static float MAX_VALUE() { return +1.0e10; }
a61af66fc99e Initial load
duke
parents:
diff changeset
293 static float MIN_VALUE() { return -1.0e10; }
a61af66fc99e Initial load
duke
parents:
diff changeset
294
a61af66fc99e Initial load
duke
parents:
diff changeset
295 float compute_heat() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
296
a61af66fc99e Initial load
duke
parents:
diff changeset
297 void set_call(CallNode* call) { _call = call; }
a61af66fc99e Initial load
duke
parents:
diff changeset
298 void set_hot_cg(CallGenerator* cg) { _hot_cg = cg; }
a61af66fc99e Initial load
duke
parents:
diff changeset
299
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // Do not queue very hot or very cold calls.
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // Make very cold ones out of line immediately.
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // Inline very hot ones immediately.
a61af66fc99e Initial load
duke
parents:
diff changeset
303 // These queries apply various tunable limits
a61af66fc99e Initial load
duke
parents:
diff changeset
304 // to the above metrics in a systematic way.
a61af66fc99e Initial load
duke
parents:
diff changeset
305 // Test for coldness before testing for hotness.
a61af66fc99e Initial load
duke
parents:
diff changeset
306 bool is_cold() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
307 bool is_hot() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
308
a61af66fc99e Initial load
duke
parents:
diff changeset
309 // Force a warm call to be hot. This worklists the call node for inlining.
a61af66fc99e Initial load
duke
parents:
diff changeset
310 void make_hot();
a61af66fc99e Initial load
duke
parents:
diff changeset
311
a61af66fc99e Initial load
duke
parents:
diff changeset
312 // Force a warm call to be cold. This worklists the call node for out-of-lining.
a61af66fc99e Initial load
duke
parents:
diff changeset
313 void make_cold();
a61af66fc99e Initial load
duke
parents:
diff changeset
314
a61af66fc99e Initial load
duke
parents:
diff changeset
315 // A reproducible total ordering, in which heat is the major key.
a61af66fc99e Initial load
duke
parents:
diff changeset
316 bool warmer_than(WarmCallInfo* that);
a61af66fc99e Initial load
duke
parents:
diff changeset
317
a61af66fc99e Initial load
duke
parents:
diff changeset
318 // List management. These methods are called with the list head,
a61af66fc99e Initial load
duke
parents:
diff changeset
319 // and return the new list head, inserting or removing the receiver.
a61af66fc99e Initial load
duke
parents:
diff changeset
320 WarmCallInfo* insert_into(WarmCallInfo* head);
a61af66fc99e Initial load
duke
parents:
diff changeset
321 WarmCallInfo* remove_from(WarmCallInfo* head);
a61af66fc99e Initial load
duke
parents:
diff changeset
322
a61af66fc99e Initial load
duke
parents:
diff changeset
323 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
324 void print() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
325 void print_all() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
326 int count_all() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
327 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
328 };
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
329
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
330 #endif // SHARE_VM_OPTO_CALLGENERATOR_HPP