annotate src/share/vm/opto/callGenerator.hpp @ 14649:f6301b007a16

6498581: ThreadInterruptTest3 produces wrong output on Windows Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set. Reviewed-by: acorn, kvn Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author minqi
date Wed, 26 Feb 2014 15:20:41 -0800
parents b2ee5dc63353
children 096c224171c4 922c87c9aed4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
12146
9758d9f36299 8021954: VM SIGSEGV during classloading on MacOS; hs_err_pid file produced
coleenp
parents: 10278
diff changeset
2 * Copyright (c) 2000, 2013, 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
12956
3213ba4d3dff 8024069: replace_in_map() should operate on parent maps
roland
parents: 12330
diff changeset
34 class Parse;
3213ba4d3dff 8024069: replace_in_map() should operate on parent maps
roland
parents: 12330
diff changeset
35
0
a61af66fc99e Initial load
duke
parents:
diff changeset
36 //---------------------------CallGenerator-------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
37 // The subclasses of this class handle generation of ideal nodes for
a61af66fc99e Initial load
duke
parents:
diff changeset
38 // call sites and method entry points.
a61af66fc99e Initial load
duke
parents:
diff changeset
39
a61af66fc99e Initial load
duke
parents:
diff changeset
40 class CallGenerator : public ResourceObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
41 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
42 enum {
a61af66fc99e Initial load
duke
parents:
diff changeset
43 xxxunusedxxx
a61af66fc99e Initial load
duke
parents:
diff changeset
44 };
a61af66fc99e Initial load
duke
parents:
diff changeset
45
a61af66fc99e Initial load
duke
parents:
diff changeset
46 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
47 ciMethod* _method; // The method being called.
a61af66fc99e Initial load
duke
parents:
diff changeset
48
a61af66fc99e Initial load
duke
parents:
diff changeset
49 protected:
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
50 CallGenerator(ciMethod* method) : _method(method) {}
0
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // Accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
54 ciMethod* method() const { return _method; }
a61af66fc99e Initial load
duke
parents:
diff changeset
55
a61af66fc99e Initial load
duke
parents:
diff changeset
56 // is_inline: At least some code implementing the method is copied here.
a61af66fc99e Initial load
duke
parents:
diff changeset
57 virtual bool is_inline() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
58 // is_intrinsic: There's a method-specific way of generating the inline code.
a61af66fc99e Initial load
duke
parents:
diff changeset
59 virtual bool is_intrinsic() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
60 // is_parse: Bytecodes implementing the specific method are copied here.
a61af66fc99e Initial load
duke
parents:
diff changeset
61 virtual bool is_parse() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // is_virtual: The call uses the receiver type to select or check the method.
a61af66fc99e Initial load
duke
parents:
diff changeset
63 virtual bool is_virtual() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
64 // is_deferred: The decision whether to inline or not is deferred.
a61af66fc99e Initial load
duke
parents:
diff changeset
65 virtual bool is_deferred() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
66 // is_predicted: Uses an explicit check against a predicted type.
a61af66fc99e Initial load
duke
parents:
diff changeset
67 virtual bool is_predicted() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
68 // is_trap: Does not return to the caller. (E.g., uncommon trap.)
a61af66fc99e Initial load
duke
parents:
diff changeset
69 virtual bool is_trap() const { return false; }
12330
29bdcf12457c 8014447: Object.hashCode intrinsic breaks inline caches
shade
parents: 12295
diff changeset
70 // does_virtual_dispatch: Should try inlining as normal method first.
29bdcf12457c 8014447: Object.hashCode intrinsic breaks inline caches
shade
parents: 12295
diff changeset
71 virtual bool does_virtual_dispatch() const { return false; }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
72
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
73 // is_late_inline: supports conversion of call into an inline
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
74 virtual bool is_late_inline() const { return false; }
7473
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
75 // same but for method handle calls
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
76 virtual bool is_mh_late_inline() const { return false; }
12966
b2ee5dc63353 8024070: C2 needs some form of type speculation
roland
parents: 12956
diff changeset
77 virtual bool is_string_late_inline() const{ return false; }
7473
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
78
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
79 // for method handle calls: have we tried inlinining the call already?
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
80 virtual bool already_attempted() const { ShouldNotReachHere(); return false; }
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
81
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
82 // Replace the call with an inline version of the code
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
83 virtual void do_late_inline() { ShouldNotReachHere(); }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
84
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
85 virtual CallStaticJavaNode* call_node() const { ShouldNotReachHere(); return NULL; }
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
87 // Note: It is possible for a CG to be both inline and virtual.
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // (The hashCode intrinsic does a vtable check and an inlined fast path.)
a61af66fc99e Initial load
duke
parents:
diff changeset
89
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // Utilities:
a61af66fc99e Initial load
duke
parents:
diff changeset
91 const TypeFunc* tf() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
92
a61af66fc99e Initial load
duke
parents:
diff changeset
93 // The given jvms has state and arguments for a call to my method.
a61af66fc99e Initial load
duke
parents:
diff changeset
94 // Edges after jvms->argoff() carry all (pre-popped) argument values.
a61af66fc99e Initial load
duke
parents:
diff changeset
95 //
a61af66fc99e Initial load
duke
parents:
diff changeset
96 // Update the map with state and return values (if any) and return it.
a61af66fc99e Initial load
duke
parents:
diff changeset
97 // The return values (0, 1, or 2) must be pushed on the map's stack,
a61af66fc99e Initial load
duke
parents:
diff changeset
98 // and the sp of the jvms incremented accordingly.
a61af66fc99e Initial load
duke
parents:
diff changeset
99 //
a61af66fc99e Initial load
duke
parents:
diff changeset
100 // The jvms is returned on success. Alternatively, a copy of the
a61af66fc99e Initial load
duke
parents:
diff changeset
101 // given jvms, suitably updated, may be returned, in which case the
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // caller should discard the original jvms.
a61af66fc99e Initial load
duke
parents:
diff changeset
103 //
a61af66fc99e Initial load
duke
parents:
diff changeset
104 // The non-Parm edges of the returned map will contain updated global state,
a61af66fc99e Initial load
duke
parents:
diff changeset
105 // and one or two edges before jvms->sp() will carry any return values.
a61af66fc99e Initial load
duke
parents:
diff changeset
106 // Other map edges may contain locals or monitors, and should not
a61af66fc99e Initial load
duke
parents:
diff changeset
107 // be changed in meaning.
a61af66fc99e Initial load
duke
parents:
diff changeset
108 //
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // If the call traps, the returned map must have a control edge of top.
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // If the call can throw, the returned map must report has_exceptions().
a61af66fc99e Initial load
duke
parents:
diff changeset
111 //
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // If the result is NULL, it means that this CallGenerator was unable
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // to handle the given call, and another CallGenerator should be consulted.
12956
3213ba4d3dff 8024069: replace_in_map() should operate on parent maps
roland
parents: 12330
diff changeset
114 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) = 0;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
115
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // How to generate a call site that is inlined:
a61af66fc99e Initial load
duke
parents:
diff changeset
117 static CallGenerator* for_inline(ciMethod* m, float expected_uses = -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // How to generate code for an on-stack replacement handler.
a61af66fc99e Initial load
duke
parents:
diff changeset
119 static CallGenerator* for_osr(ciMethod* m, int osr_bci);
a61af66fc99e Initial load
duke
parents:
diff changeset
120
a61af66fc99e Initial load
duke
parents:
diff changeset
121 // How to generate vanilla out-of-line call sites:
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
122 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
123 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
124 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
125
7473
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
126 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
127 static CallGenerator* for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool& input_not_const);
3752
f918d6096e23 7050554: JSR 292 - need optimization for selectAlternative
never
parents: 2443
diff changeset
128
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
129 // 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
130 static CallGenerator* for_late_inline(ciMethod* m, CallGenerator* inline_cg);
7473
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
131 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
132 static CallGenerator* for_string_late_inline(ciMethod* m, CallGenerator* inline_cg);
10278
6f3fd5150b67 6934604: enable parts of EliminateAutoBox by default
kvn
parents: 7473
diff changeset
133 static CallGenerator* for_boxing_late_inline(ciMethod* m, CallGenerator* inline_cg);
1080
7c57aead6d3e 6892658: C2 should optimize some stringbuilder patterns
never
parents: 0
diff changeset
134
0
a61af66fc99e Initial load
duke
parents:
diff changeset
135 // How to make a call but defer the decision whether to inline or not.
a61af66fc99e Initial load
duke
parents:
diff changeset
136 static CallGenerator* for_warm_call(WarmCallInfo* ci,
a61af66fc99e Initial load
duke
parents:
diff changeset
137 CallGenerator* if_cold,
a61af66fc99e Initial load
duke
parents:
diff changeset
138 CallGenerator* if_hot);
a61af66fc99e Initial load
duke
parents:
diff changeset
139
a61af66fc99e Initial load
duke
parents:
diff changeset
140 // How to make a call that optimistically assumes a receiver type:
a61af66fc99e Initial load
duke
parents:
diff changeset
141 static CallGenerator* for_predicted_call(ciKlass* predicted_receiver,
a61af66fc99e Initial load
duke
parents:
diff changeset
142 CallGenerator* if_missed,
a61af66fc99e Initial load
duke
parents:
diff changeset
143 CallGenerator* if_hit,
a61af66fc99e Initial load
duke
parents:
diff changeset
144 float hit_prob);
a61af66fc99e Initial load
duke
parents:
diff changeset
145
1138
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
146 // 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
147 static CallGenerator* for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
148 CallGenerator* if_missed,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
149 CallGenerator* if_hit,
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
150 float hit_prob);
dd57230ba8fe 6893268: additional dynamic language related optimizations in C2
twisti
parents: 1137
diff changeset
151
0
a61af66fc99e Initial load
duke
parents:
diff changeset
152 // How to make a call that gives up and goes back to the interpreter:
a61af66fc99e Initial load
duke
parents:
diff changeset
153 static CallGenerator* for_uncommon_trap(ciMethod* m,
a61af66fc99e Initial load
duke
parents:
diff changeset
154 Deoptimization::DeoptReason reason,
a61af66fc99e Initial load
duke
parents:
diff changeset
155 Deoptimization::DeoptAction action);
a61af66fc99e Initial load
duke
parents:
diff changeset
156
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // Registry for intrinsics:
a61af66fc99e Initial load
duke
parents:
diff changeset
158 static CallGenerator* for_intrinsic(ciMethod* m);
a61af66fc99e Initial load
duke
parents:
diff changeset
159 static void register_intrinsic(ciMethod* m, CallGenerator* cg);
6894
a3ecd773a7b9 7184394: add intrinsics to use AES instructions
kvn
parents: 6842
diff changeset
160 static CallGenerator* for_predicted_intrinsic(CallGenerator* intrinsic,
a3ecd773a7b9 7184394: add intrinsics to use AES instructions
kvn
parents: 6842
diff changeset
161 CallGenerator* cg);
a3ecd773a7b9 7184394: add intrinsics to use AES instructions
kvn
parents: 6842
diff changeset
162 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
163
7473
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
164 virtual void print_inlining_late(const char* msg) { ShouldNotReachHere(); }
d092d1b31229 8005071: Incremental inlining for JSR 292
roland
parents: 7421
diff changeset
165
7421
ad5dd04754ee 8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents: 6894
diff changeset
166 static void print_inlining(Compile* C, ciMethod* callee, int inline_level, int bci, const char* msg) {
12295
1b64d46620a3 8022585: VM crashes when ran with -XX:+PrintInlining
kvn
parents: 12146
diff changeset
167 if (C->print_inlining()) {
7421
ad5dd04754ee 8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents: 6894
diff changeset
168 C->print_inlining(callee, inline_level, bci, msg);
12295
1b64d46620a3 8022585: VM crashes when ran with -XX:+PrintInlining
kvn
parents: 12146
diff changeset
169 }
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
170 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
171 };
a61af66fc99e Initial load
duke
parents:
diff changeset
172
a61af66fc99e Initial load
duke
parents:
diff changeset
173
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
174 //------------------------InlineCallGenerator----------------------------------
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
175 class InlineCallGenerator : public CallGenerator {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
176 protected:
6266
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
177 InlineCallGenerator(ciMethod* method) : CallGenerator(method) {}
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
178
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
179 public:
1d7922586cf6 7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents: 4117
diff changeset
180 virtual bool is_inline() const { return true; }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
181 };
a61af66fc99e Initial load
duke
parents:
diff changeset
182
a61af66fc99e Initial load
duke
parents:
diff changeset
183
a61af66fc99e Initial load
duke
parents:
diff changeset
184 //---------------------------WarmCallInfo--------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // A struct to collect information about a given call site.
a61af66fc99e Initial load
duke
parents:
diff changeset
186 // Helps sort call sites into "hot", "medium", and "cold".
a61af66fc99e Initial load
duke
parents:
diff changeset
187 // Participates in the queueing of "medium" call sites for possible inlining.
a61af66fc99e Initial load
duke
parents:
diff changeset
188 class WarmCallInfo : public ResourceObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
189 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
190
a61af66fc99e Initial load
duke
parents:
diff changeset
191 CallNode* _call; // The CallNode which may be inlined.
a61af66fc99e Initial load
duke
parents:
diff changeset
192 CallGenerator* _hot_cg;// CG for expanding the call node
a61af66fc99e Initial load
duke
parents:
diff changeset
193
a61af66fc99e Initial load
duke
parents:
diff changeset
194 // These are the metrics we use to evaluate call sites:
a61af66fc99e Initial load
duke
parents:
diff changeset
195
a61af66fc99e Initial load
duke
parents:
diff changeset
196 float _count; // How often do we expect to reach this site?
a61af66fc99e Initial load
duke
parents:
diff changeset
197 float _profit; // How much time do we expect to save by inlining?
a61af66fc99e Initial load
duke
parents:
diff changeset
198 float _work; // How long do we expect the average call to take?
a61af66fc99e Initial load
duke
parents:
diff changeset
199 float _size; // How big do we expect the inlined code to be?
a61af66fc99e Initial load
duke
parents:
diff changeset
200
a61af66fc99e Initial load
duke
parents:
diff changeset
201 float _heat; // Combined score inducing total order on call sites.
a61af66fc99e Initial load
duke
parents:
diff changeset
202 WarmCallInfo* _next; // Next cooler call info in pending queue.
a61af66fc99e Initial load
duke
parents:
diff changeset
203
a61af66fc99e Initial load
duke
parents:
diff changeset
204 // Count is the number of times this call site is expected to be executed.
a61af66fc99e Initial load
duke
parents:
diff changeset
205 // Large count is favorable for inlining, because the extra compilation
a61af66fc99e Initial load
duke
parents:
diff changeset
206 // work will be amortized more completely.
a61af66fc99e Initial load
duke
parents:
diff changeset
207
a61af66fc99e Initial load
duke
parents:
diff changeset
208 // Profit is a rough measure of the amount of time we expect to save
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // per execution of this site if we inline it. (1.0 == call overhead)
a61af66fc99e Initial load
duke
parents:
diff changeset
210 // Large profit favors inlining. Negative profit disables inlining.
a61af66fc99e Initial load
duke
parents:
diff changeset
211
a61af66fc99e Initial load
duke
parents:
diff changeset
212 // Work is a rough measure of the amount of time a typical out-of-line
a61af66fc99e Initial load
duke
parents:
diff changeset
213 // call from this site is expected to take. (1.0 == call, no-op, return)
a61af66fc99e Initial load
duke
parents:
diff changeset
214 // Small work is somewhat favorable for inlining, since methods with
a61af66fc99e Initial load
duke
parents:
diff changeset
215 // short "hot" traces are more likely to inline smoothly.
a61af66fc99e Initial load
duke
parents:
diff changeset
216
a61af66fc99e Initial load
duke
parents:
diff changeset
217 // Size is the number of graph nodes we expect this method to produce,
a61af66fc99e Initial load
duke
parents:
diff changeset
218 // not counting the inlining of any further warm calls it may include.
a61af66fc99e Initial load
duke
parents:
diff changeset
219 // Small size favors inlining, since small methods are more likely to
a61af66fc99e Initial load
duke
parents:
diff changeset
220 // inline smoothly. The size is estimated by examining the native code
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // if available. The method bytecodes are also examined, assuming
a61af66fc99e Initial load
duke
parents:
diff changeset
222 // empirically observed node counts for each kind of bytecode.
a61af66fc99e Initial load
duke
parents:
diff changeset
223
a61af66fc99e Initial load
duke
parents:
diff changeset
224 // Heat is the combined "goodness" of a site's inlining. If we were
a61af66fc99e Initial load
duke
parents:
diff changeset
225 // omniscient, it would be the difference of two sums of future execution
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // times of code emitted for this site (amortized across multiple sites if
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // sharing applies). The two sums are for versions of this call site with
a61af66fc99e Initial load
duke
parents:
diff changeset
228 // and without inlining.
a61af66fc99e Initial load
duke
parents:
diff changeset
229
a61af66fc99e Initial load
duke
parents:
diff changeset
230 // We approximate this mythical quantity by playing with averages,
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // rough estimates, and assumptions that history repeats itself.
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // The basic formula count * profit is heuristically adjusted
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // by looking at the expected compilation and execution times of
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // of the inlined call.
a61af66fc99e Initial load
duke
parents:
diff changeset
235
a61af66fc99e Initial load
duke
parents:
diff changeset
236 // Note: Some of these metrics may not be present in the final product,
a61af66fc99e Initial load
duke
parents:
diff changeset
237 // but exist in development builds to experiment with inline policy tuning.
a61af66fc99e Initial load
duke
parents:
diff changeset
238
a61af66fc99e Initial load
duke
parents:
diff changeset
239 // This heuristic framework does not model well the very significant
a61af66fc99e Initial load
duke
parents:
diff changeset
240 // effects of multiple-level inlining. It is possible to see no immediate
a61af66fc99e Initial load
duke
parents:
diff changeset
241 // profit from inlining X->Y, but to get great profit from a subsequent
a61af66fc99e Initial load
duke
parents:
diff changeset
242 // inlining X->Y->Z.
a61af66fc99e Initial load
duke
parents:
diff changeset
243
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // This framework does not take well into account the problem of N**2 code
a61af66fc99e Initial load
duke
parents:
diff changeset
245 // size in a clique of mutually inlinable methods.
a61af66fc99e Initial load
duke
parents:
diff changeset
246
a61af66fc99e Initial load
duke
parents:
diff changeset
247 WarmCallInfo* next() const { return _next; }
a61af66fc99e Initial load
duke
parents:
diff changeset
248 void set_next(WarmCallInfo* n) { _next = n; }
a61af66fc99e Initial load
duke
parents:
diff changeset
249
2443
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
250 static WarmCallInfo _always_hot;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
251 static WarmCallInfo _always_cold;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
252
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
253 // 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
254 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
255 _call = NULL;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
256 _hot_cg = NULL;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
257 _next = NULL;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
258 _count = c;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
259 _profit = p;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
260 _work = w;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
261 _size = s;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
262 _heat = 0;
f8b038506985 6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents: 1972
diff changeset
263 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
264
a61af66fc99e Initial load
duke
parents:
diff changeset
265 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
266 // Because WarmInfo objects live over the entire lifetime of the
a61af66fc99e Initial load
duke
parents:
diff changeset
267 // Compile object, they are allocated into the comp_arena, which
a61af66fc99e Initial load
duke
parents:
diff changeset
268 // does not get resource marked or reset during the compile process
12146
9758d9f36299 8021954: VM SIGSEGV during classloading on MacOS; hs_err_pid file produced
coleenp
parents: 10278
diff changeset
269 void *operator new( size_t x, Compile* C ) throw() { return C->comp_arena()->Amalloc(x); }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
270 void operator delete( void * ) { } // fast deallocation
a61af66fc99e Initial load
duke
parents:
diff changeset
271
a61af66fc99e Initial load
duke
parents:
diff changeset
272 static WarmCallInfo* always_hot();
a61af66fc99e Initial load
duke
parents:
diff changeset
273 static WarmCallInfo* always_cold();
a61af66fc99e Initial load
duke
parents:
diff changeset
274
a61af66fc99e Initial load
duke
parents:
diff changeset
275 WarmCallInfo() {
a61af66fc99e Initial load
duke
parents:
diff changeset
276 _call = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
277 _hot_cg = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
278 _next = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
279 _count = _profit = _work = _size = _heat = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
280 }
a61af66fc99e Initial load
duke
parents:
diff changeset
281
a61af66fc99e Initial load
duke
parents:
diff changeset
282 CallNode* call() const { return _call; }
a61af66fc99e Initial load
duke
parents:
diff changeset
283 float count() const { return _count; }
a61af66fc99e Initial load
duke
parents:
diff changeset
284 float size() const { return _size; }
a61af66fc99e Initial load
duke
parents:
diff changeset
285 float work() const { return _work; }
a61af66fc99e Initial load
duke
parents:
diff changeset
286 float profit() const { return _profit; }
a61af66fc99e Initial load
duke
parents:
diff changeset
287 float heat() const { return _heat; }
a61af66fc99e Initial load
duke
parents:
diff changeset
288
a61af66fc99e Initial load
duke
parents:
diff changeset
289 void set_count(float x) { _count = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
290 void set_size(float x) { _size = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
291 void set_work(float x) { _work = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
292 void set_profit(float x) { _profit = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
293 void set_heat(float x) { _heat = x; }
a61af66fc99e Initial load
duke
parents:
diff changeset
294
a61af66fc99e Initial load
duke
parents:
diff changeset
295 // Load initial heuristics from profiles, etc.
a61af66fc99e Initial load
duke
parents:
diff changeset
296 // The heuristics can be tweaked further by the caller.
a61af66fc99e Initial load
duke
parents:
diff changeset
297 void init(JVMState* call_site, ciMethod* call_method, ciCallProfile& profile, float prof_factor);
a61af66fc99e Initial load
duke
parents:
diff changeset
298
a61af66fc99e Initial load
duke
parents:
diff changeset
299 static float MAX_VALUE() { return +1.0e10; }
a61af66fc99e Initial load
duke
parents:
diff changeset
300 static float MIN_VALUE() { return -1.0e10; }
a61af66fc99e Initial load
duke
parents:
diff changeset
301
a61af66fc99e Initial load
duke
parents:
diff changeset
302 float compute_heat() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
303
a61af66fc99e Initial load
duke
parents:
diff changeset
304 void set_call(CallNode* call) { _call = call; }
a61af66fc99e Initial load
duke
parents:
diff changeset
305 void set_hot_cg(CallGenerator* cg) { _hot_cg = cg; }
a61af66fc99e Initial load
duke
parents:
diff changeset
306
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // Do not queue very hot or very cold calls.
a61af66fc99e Initial load
duke
parents:
diff changeset
308 // Make very cold ones out of line immediately.
a61af66fc99e Initial load
duke
parents:
diff changeset
309 // Inline very hot ones immediately.
a61af66fc99e Initial load
duke
parents:
diff changeset
310 // These queries apply various tunable limits
a61af66fc99e Initial load
duke
parents:
diff changeset
311 // to the above metrics in a systematic way.
a61af66fc99e Initial load
duke
parents:
diff changeset
312 // Test for coldness before testing for hotness.
a61af66fc99e Initial load
duke
parents:
diff changeset
313 bool is_cold() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
314 bool is_hot() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
315
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // Force a warm call to be hot. This worklists the call node for inlining.
a61af66fc99e Initial load
duke
parents:
diff changeset
317 void make_hot();
a61af66fc99e Initial load
duke
parents:
diff changeset
318
a61af66fc99e Initial load
duke
parents:
diff changeset
319 // Force a warm call to be cold. This worklists the call node for out-of-lining.
a61af66fc99e Initial load
duke
parents:
diff changeset
320 void make_cold();
a61af66fc99e Initial load
duke
parents:
diff changeset
321
a61af66fc99e Initial load
duke
parents:
diff changeset
322 // A reproducible total ordering, in which heat is the major key.
a61af66fc99e Initial load
duke
parents:
diff changeset
323 bool warmer_than(WarmCallInfo* that);
a61af66fc99e Initial load
duke
parents:
diff changeset
324
a61af66fc99e Initial load
duke
parents:
diff changeset
325 // List management. These methods are called with the list head,
a61af66fc99e Initial load
duke
parents:
diff changeset
326 // and return the new list head, inserting or removing the receiver.
a61af66fc99e Initial load
duke
parents:
diff changeset
327 WarmCallInfo* insert_into(WarmCallInfo* head);
a61af66fc99e Initial load
duke
parents:
diff changeset
328 WarmCallInfo* remove_from(WarmCallInfo* head);
a61af66fc99e Initial load
duke
parents:
diff changeset
329
a61af66fc99e Initial load
duke
parents:
diff changeset
330 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
331 void print() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
332 void print_all() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
333 int count_all() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
334 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
335 };
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
336
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
337 #endif // SHARE_VM_OPTO_CALLGENERATOR_HPP