annotate src/share/vm/c1/c1_LinearScan.hpp @ 1994:6cd6d394f280

7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed()) 7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages. Reviewed-by: johnc, tonyp
author ysr
date Tue, 07 Dec 2010 21:55:53 -0800
parents f95d63e2154a
children 7223744c2784
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 337
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 337
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: 337
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: 1819
diff changeset
25 #ifndef SHARE_VM_C1_C1_LINEARSCAN_HPP
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
26 #define SHARE_VM_C1_C1_LINEARSCAN_HPP
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
27
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
28 #include "c1/c1_FpuStackSim.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
29 #include "c1/c1_FrameMap.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
30 #include "c1/c1_IR.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
31 #include "c1/c1_Instruction.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
32 #include "c1/c1_LIR.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
33 #include "c1/c1_LIRGenerator.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
34
0
a61af66fc99e Initial load
duke
parents:
diff changeset
35 class DebugInfoCache;
a61af66fc99e Initial load
duke
parents:
diff changeset
36 class FpuStackAllocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
37 class IRScopeDebugInfo;
a61af66fc99e Initial load
duke
parents:
diff changeset
38 class Interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
39 class IntervalWalker;
a61af66fc99e Initial load
duke
parents:
diff changeset
40 class LIRGenerator;
a61af66fc99e Initial load
duke
parents:
diff changeset
41 class LinearScan;
a61af66fc99e Initial load
duke
parents:
diff changeset
42 class MoveResolver;
a61af66fc99e Initial load
duke
parents:
diff changeset
43 class Range;
a61af66fc99e Initial load
duke
parents:
diff changeset
44
a61af66fc99e Initial load
duke
parents:
diff changeset
45 define_array(IntervalArray, Interval*)
a61af66fc99e Initial load
duke
parents:
diff changeset
46 define_stack(IntervalList, IntervalArray)
a61af66fc99e Initial load
duke
parents:
diff changeset
47
a61af66fc99e Initial load
duke
parents:
diff changeset
48 define_array(IntervalsArray, IntervalList*)
a61af66fc99e Initial load
duke
parents:
diff changeset
49 define_stack(IntervalsList, IntervalsArray)
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51 define_array(OopMapArray, OopMap*)
a61af66fc99e Initial load
duke
parents:
diff changeset
52 define_stack(OopMapList, OopMapArray)
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 define_array(ScopeValueArray, ScopeValue*)
a61af66fc99e Initial load
duke
parents:
diff changeset
55
a61af66fc99e Initial load
duke
parents:
diff changeset
56 define_array(LIR_OpListArray, LIR_OpList*);
a61af66fc99e Initial load
duke
parents:
diff changeset
57 define_stack(LIR_OpListStack, LIR_OpListArray);
a61af66fc99e Initial load
duke
parents:
diff changeset
58
a61af66fc99e Initial load
duke
parents:
diff changeset
59
a61af66fc99e Initial load
duke
parents:
diff changeset
60 enum IntervalUseKind {
a61af66fc99e Initial load
duke
parents:
diff changeset
61 // priority of use kinds must be ascending
a61af66fc99e Initial load
duke
parents:
diff changeset
62 noUse = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
63 loopEndMarker = 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
64 shouldHaveRegister = 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
65 mustHaveRegister = 3,
a61af66fc99e Initial load
duke
parents:
diff changeset
66
a61af66fc99e Initial load
duke
parents:
diff changeset
67 firstValidKind = 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
68 lastValidKind = 3
a61af66fc99e Initial load
duke
parents:
diff changeset
69 };
a61af66fc99e Initial load
duke
parents:
diff changeset
70 define_array(UseKindArray, IntervalUseKind)
a61af66fc99e Initial load
duke
parents:
diff changeset
71 define_stack(UseKindStack, UseKindArray)
a61af66fc99e Initial load
duke
parents:
diff changeset
72
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 enum IntervalKind {
a61af66fc99e Initial load
duke
parents:
diff changeset
75 fixedKind = 0, // interval pre-colored by LIR_Generator
a61af66fc99e Initial load
duke
parents:
diff changeset
76 anyKind = 1, // no register/memory allocated by LIR_Generator
a61af66fc99e Initial load
duke
parents:
diff changeset
77 nofKinds,
a61af66fc99e Initial load
duke
parents:
diff changeset
78 firstKind = fixedKind
a61af66fc99e Initial load
duke
parents:
diff changeset
79 };
a61af66fc99e Initial load
duke
parents:
diff changeset
80
a61af66fc99e Initial load
duke
parents:
diff changeset
81
a61af66fc99e Initial load
duke
parents:
diff changeset
82 // during linear scan an interval is in one of four states in
a61af66fc99e Initial load
duke
parents:
diff changeset
83 enum IntervalState {
a61af66fc99e Initial load
duke
parents:
diff changeset
84 unhandledState = 0, // unhandled state (not processed yet)
a61af66fc99e Initial load
duke
parents:
diff changeset
85 activeState = 1, // life and is in a physical register
a61af66fc99e Initial load
duke
parents:
diff changeset
86 inactiveState = 2, // in a life time hole and is in a physical register
a61af66fc99e Initial load
duke
parents:
diff changeset
87 handledState = 3, // spilled or not life again
a61af66fc99e Initial load
duke
parents:
diff changeset
88 invalidState = -1
a61af66fc99e Initial load
duke
parents:
diff changeset
89 };
a61af66fc99e Initial load
duke
parents:
diff changeset
90
a61af66fc99e Initial load
duke
parents:
diff changeset
91
a61af66fc99e Initial load
duke
parents:
diff changeset
92 enum IntervalSpillState {
a61af66fc99e Initial load
duke
parents:
diff changeset
93 noDefinitionFound, // starting state of calculation: no definition found yet
a61af66fc99e Initial load
duke
parents:
diff changeset
94 oneDefinitionFound, // one definition has already been found.
a61af66fc99e Initial load
duke
parents:
diff changeset
95 // Note: two consecutive definitions are treated as one (e.g. consecutive move and add because of two-operand LIR form)
a61af66fc99e Initial load
duke
parents:
diff changeset
96 // the position of this definition is stored in _definition_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
97 oneMoveInserted, // one spill move has already been inserted.
a61af66fc99e Initial load
duke
parents:
diff changeset
98 storeAtDefinition, // the interval should be stored immediately after its definition because otherwise
a61af66fc99e Initial load
duke
parents:
diff changeset
99 // there would be multiple redundant stores
a61af66fc99e Initial load
duke
parents:
diff changeset
100 startInMemory, // the interval starts in memory (e.g. method parameter), so a store is never necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
101 noOptimization // the interval has more then one definition (e.g. resulting from phi moves), so stores to memory are not optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
102 };
a61af66fc99e Initial load
duke
parents:
diff changeset
103
a61af66fc99e Initial load
duke
parents:
diff changeset
104
a61af66fc99e Initial load
duke
parents:
diff changeset
105 #define for_each_interval_kind(kind) \
a61af66fc99e Initial load
duke
parents:
diff changeset
106 for (IntervalKind kind = firstKind; kind < nofKinds; kind = (IntervalKind)(kind + 1))
a61af66fc99e Initial load
duke
parents:
diff changeset
107
a61af66fc99e Initial load
duke
parents:
diff changeset
108 #define for_each_visitor_mode(mode) \
a61af66fc99e Initial load
duke
parents:
diff changeset
109 for (LIR_OpVisitState::OprMode mode = LIR_OpVisitState::firstMode; mode < LIR_OpVisitState::numModes; mode = (LIR_OpVisitState::OprMode)(mode + 1))
a61af66fc99e Initial load
duke
parents:
diff changeset
110
a61af66fc99e Initial load
duke
parents:
diff changeset
111
a61af66fc99e Initial load
duke
parents:
diff changeset
112 class LinearScan : public CompilationResourceObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // declare classes used by LinearScan as friends because they
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // need a wide variety of functions declared here
a61af66fc99e Initial load
duke
parents:
diff changeset
115 //
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // Only the small interface to the rest of the compiler is public
a61af66fc99e Initial load
duke
parents:
diff changeset
117 friend class Interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
118 friend class IntervalWalker;
a61af66fc99e Initial load
duke
parents:
diff changeset
119 friend class LinearScanWalker;
a61af66fc99e Initial load
duke
parents:
diff changeset
120 friend class FpuStackAllocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
121 friend class MoveResolver;
a61af66fc99e Initial load
duke
parents:
diff changeset
122 friend class LinearScanStatistic;
a61af66fc99e Initial load
duke
parents:
diff changeset
123 friend class LinearScanTimers;
a61af66fc99e Initial load
duke
parents:
diff changeset
124 friend class RegisterVerifier;
a61af66fc99e Initial load
duke
parents:
diff changeset
125
a61af66fc99e Initial load
duke
parents:
diff changeset
126 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
127 enum {
a61af66fc99e Initial load
duke
parents:
diff changeset
128 any_reg = -1,
a61af66fc99e Initial load
duke
parents:
diff changeset
129 nof_cpu_regs = pd_nof_cpu_regs_linearscan,
a61af66fc99e Initial load
duke
parents:
diff changeset
130 nof_fpu_regs = pd_nof_fpu_regs_linearscan,
a61af66fc99e Initial load
duke
parents:
diff changeset
131 nof_xmm_regs = pd_nof_xmm_regs_linearscan,
a61af66fc99e Initial load
duke
parents:
diff changeset
132 nof_regs = nof_cpu_regs + nof_fpu_regs + nof_xmm_regs
a61af66fc99e Initial load
duke
parents:
diff changeset
133 };
a61af66fc99e Initial load
duke
parents:
diff changeset
134
a61af66fc99e Initial load
duke
parents:
diff changeset
135 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
136 Compilation* _compilation;
a61af66fc99e Initial load
duke
parents:
diff changeset
137 IR* _ir;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 LIRGenerator* _gen;
a61af66fc99e Initial load
duke
parents:
diff changeset
139 FrameMap* _frame_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
140
a61af66fc99e Initial load
duke
parents:
diff changeset
141 BlockList _cached_blocks; // cached list with all blocks in linear-scan order (only correct if original list keeps unchanged)
a61af66fc99e Initial load
duke
parents:
diff changeset
142 int _num_virtual_regs; // number of virtual registers (without new registers introduced because of splitting intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
143 bool _has_fpu_registers; // true if this method uses any floating point registers (and so fpu stack allocation is necessary)
a61af66fc99e Initial load
duke
parents:
diff changeset
144 int _num_calls; // total number of calls in this method
a61af66fc99e Initial load
duke
parents:
diff changeset
145 int _max_spills; // number of stack slots used for intervals allocated to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
146 int _unused_spill_slot; // unused spill slot for a single-word value because of alignment of a double-word value
a61af66fc99e Initial load
duke
parents:
diff changeset
147
a61af66fc99e Initial load
duke
parents:
diff changeset
148 IntervalList _intervals; // mapping from register number to interval
a61af66fc99e Initial load
duke
parents:
diff changeset
149 IntervalList* _new_intervals_from_allocation; // list with all intervals created during allocation when an existing interval is split
a61af66fc99e Initial load
duke
parents:
diff changeset
150 IntervalArray* _sorted_intervals; // intervals sorted by Interval::from()
a61af66fc99e Initial load
duke
parents:
diff changeset
151
a61af66fc99e Initial load
duke
parents:
diff changeset
152 LIR_OpArray _lir_ops; // mapping from LIR_Op id to LIR_Op node
a61af66fc99e Initial load
duke
parents:
diff changeset
153 BlockBeginArray _block_of_op; // mapping from LIR_Op id to the BlockBegin containing this instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
154 BitMap _has_info; // bit set for each LIR_Op id that has a CodeEmitInfo
a61af66fc99e Initial load
duke
parents:
diff changeset
155 BitMap _has_call; // bit set for each LIR_Op id that destroys all caller save registers
a61af66fc99e Initial load
duke
parents:
diff changeset
156 BitMap2D _interval_in_loop; // bit set for each virtual register that is contained in each loop
a61af66fc99e Initial load
duke
parents:
diff changeset
157
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // cached debug info to prevent multiple creation of same object
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // TODO: cached scope values for registers could be static
a61af66fc99e Initial load
duke
parents:
diff changeset
160 ScopeValueArray _scope_value_cache;
a61af66fc99e Initial load
duke
parents:
diff changeset
161
a61af66fc99e Initial load
duke
parents:
diff changeset
162 static ConstantOopWriteValue _oop_null_scope_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
163 static ConstantIntValue _int_m1_scope_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
164 static ConstantIntValue _int_0_scope_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
165 static ConstantIntValue _int_1_scope_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
166 static ConstantIntValue _int_2_scope_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
167
a61af66fc99e Initial load
duke
parents:
diff changeset
168 // accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
169 IR* ir() const { return _ir; }
a61af66fc99e Initial load
duke
parents:
diff changeset
170 Compilation* compilation() const { return _compilation; }
a61af66fc99e Initial load
duke
parents:
diff changeset
171 LIRGenerator* gen() const { return _gen; }
a61af66fc99e Initial load
duke
parents:
diff changeset
172 FrameMap* frame_map() const { return _frame_map; }
a61af66fc99e Initial load
duke
parents:
diff changeset
173
a61af66fc99e Initial load
duke
parents:
diff changeset
174 // unified bailout support
a61af66fc99e Initial load
duke
parents:
diff changeset
175 void bailout(const char* msg) const { compilation()->bailout(msg); }
a61af66fc99e Initial load
duke
parents:
diff changeset
176 bool bailed_out() const { return compilation()->bailed_out(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
177
a61af66fc99e Initial load
duke
parents:
diff changeset
178 // access to block list (sorted in linear scan order)
a61af66fc99e Initial load
duke
parents:
diff changeset
179 int block_count() const { assert(_cached_blocks.length() == ir()->linear_scan_order()->length(), "invalid cached block list"); return _cached_blocks.length(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
180 BlockBegin* block_at(int idx) const { assert(_cached_blocks.at(idx) == ir()->linear_scan_order()->at(idx), "invalid cached block list"); return _cached_blocks.at(idx); }
a61af66fc99e Initial load
duke
parents:
diff changeset
181
a61af66fc99e Initial load
duke
parents:
diff changeset
182 int num_virtual_regs() const { return _num_virtual_regs; }
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // size of live_in and live_out sets of BasicBlocks (BitMap needs rounded size for iteration)
a61af66fc99e Initial load
duke
parents:
diff changeset
184 int live_set_size() const { return round_to(_num_virtual_regs, BitsPerWord); }
a61af66fc99e Initial load
duke
parents:
diff changeset
185 bool has_fpu_registers() const { return _has_fpu_registers; }
a61af66fc99e Initial load
duke
parents:
diff changeset
186 int num_loops() const { return ir()->num_loops(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
187 bool is_interval_in_loop(int interval, int loop) const { return _interval_in_loop.at(interval, loop); }
a61af66fc99e Initial load
duke
parents:
diff changeset
188
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // handling of fpu stack allocation (platform dependent, needed for debug information generation)
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
190 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
191 FpuStackAllocator* _fpu_stack_allocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
192 bool use_fpu_stack_allocation() const { return UseSSE < 2 && has_fpu_registers(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
193 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
194 bool use_fpu_stack_allocation() const { return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
195 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
196
a61af66fc99e Initial load
duke
parents:
diff changeset
197
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // access to interval list
a61af66fc99e Initial load
duke
parents:
diff changeset
199 int interval_count() const { return _intervals.length(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
200 Interval* interval_at(int reg_num) const { return _intervals.at(reg_num); }
a61af66fc99e Initial load
duke
parents:
diff changeset
201
a61af66fc99e Initial load
duke
parents:
diff changeset
202 IntervalList* new_intervals_from_allocation() const { return _new_intervals_from_allocation; }
a61af66fc99e Initial load
duke
parents:
diff changeset
203
a61af66fc99e Initial load
duke
parents:
diff changeset
204 // access to LIR_Ops and Blocks indexed by op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
205 int max_lir_op_id() const { assert(_lir_ops.length() > 0, "no operations"); return (_lir_ops.length() - 1) << 1; }
a61af66fc99e Initial load
duke
parents:
diff changeset
206 LIR_Op* lir_op_with_id(int op_id) const { assert(op_id >= 0 && op_id <= max_lir_op_id() && op_id % 2 == 0, "op_id out of range or not even"); return _lir_ops.at(op_id >> 1); }
a61af66fc99e Initial load
duke
parents:
diff changeset
207 BlockBegin* block_of_op_with_id(int op_id) const { assert(_block_of_op.length() > 0 && op_id >= 0 && op_id <= max_lir_op_id() + 1, "op_id out of range"); return _block_of_op.at(op_id >> 1); }
a61af66fc99e Initial load
duke
parents:
diff changeset
208
a61af66fc99e Initial load
duke
parents:
diff changeset
209 bool is_block_begin(int op_id) { return op_id == 0 || block_of_op_with_id(op_id) != block_of_op_with_id(op_id - 1); }
a61af66fc99e Initial load
duke
parents:
diff changeset
210 bool covers_block_begin(int op_id_1, int op_id_2) { return block_of_op_with_id(op_id_1) != block_of_op_with_id(op_id_2); }
a61af66fc99e Initial load
duke
parents:
diff changeset
211
a61af66fc99e Initial load
duke
parents:
diff changeset
212 bool has_call(int op_id) { assert(op_id % 2 == 0, "must be even"); return _has_call.at(op_id >> 1); }
a61af66fc99e Initial load
duke
parents:
diff changeset
213 bool has_info(int op_id) { assert(op_id % 2 == 0, "must be even"); return _has_info.at(op_id >> 1); }
a61af66fc99e Initial load
duke
parents:
diff changeset
214
a61af66fc99e Initial load
duke
parents:
diff changeset
215
a61af66fc99e Initial load
duke
parents:
diff changeset
216 // functions for converting LIR-Operands to register numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
217 static bool is_valid_reg_num(int reg_num) { return reg_num >= 0; }
a61af66fc99e Initial load
duke
parents:
diff changeset
218 static int reg_num(LIR_Opr opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
219 static int reg_numHi(LIR_Opr opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
220
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // functions for classification of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
222 static bool is_precolored_interval(const Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
223 static bool is_virtual_interval(const Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
224
a61af66fc99e Initial load
duke
parents:
diff changeset
225 static bool is_precolored_cpu_interval(const Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
226 static bool is_virtual_cpu_interval(const Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
227 static bool is_precolored_fpu_interval(const Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
228 static bool is_virtual_fpu_interval(const Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
229
a61af66fc99e Initial load
duke
parents:
diff changeset
230 static bool is_in_fpu_register(const Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
231 static bool is_oop_interval(const Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
232
a61af66fc99e Initial load
duke
parents:
diff changeset
233
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // General helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
235 int allocate_spill_slot(bool double_word);
a61af66fc99e Initial load
duke
parents:
diff changeset
236 void assign_spill_slot(Interval* it);
a61af66fc99e Initial load
duke
parents:
diff changeset
237 void propagate_spill_slots();
a61af66fc99e Initial load
duke
parents:
diff changeset
238
a61af66fc99e Initial load
duke
parents:
diff changeset
239 Interval* create_interval(int reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
240 void append_interval(Interval* it);
a61af66fc99e Initial load
duke
parents:
diff changeset
241 void copy_register_flags(Interval* from, Interval* to);
a61af66fc99e Initial load
duke
parents:
diff changeset
242
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // platform dependent functions
a61af66fc99e Initial load
duke
parents:
diff changeset
244 static bool is_processed_reg_num(int reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
245 static int num_physical_regs(BasicType type);
a61af66fc99e Initial load
duke
parents:
diff changeset
246 static bool requires_adjacent_regs(BasicType type);
a61af66fc99e Initial load
duke
parents:
diff changeset
247 static bool is_caller_save(int assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
248
a61af66fc99e Initial load
duke
parents:
diff changeset
249 // spill move optimization: eliminate moves from register to stack if
a61af66fc99e Initial load
duke
parents:
diff changeset
250 // stack slot is known to be correct
a61af66fc99e Initial load
duke
parents:
diff changeset
251 void change_spill_definition_pos(Interval* interval, int def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
252 void change_spill_state(Interval* interval, int spill_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
253 static bool must_store_at_definition(const Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
254 void eliminate_spill_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
255
a61af66fc99e Initial load
duke
parents:
diff changeset
256 // Phase 1: number all instructions in all blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
257 void number_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
258
a61af66fc99e Initial load
duke
parents:
diff changeset
259 // Phase 2: compute local live sets separately for each block
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // (sets live_gen and live_kill for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
261 //
a61af66fc99e Initial load
duke
parents:
diff changeset
262 // helper methods used by compute_local_live_sets()
a61af66fc99e Initial load
duke
parents:
diff changeset
263 void set_live_gen_kill(Value value, LIR_Op* op, BitMap& live_gen, BitMap& live_kill);
a61af66fc99e Initial load
duke
parents:
diff changeset
264
a61af66fc99e Initial load
duke
parents:
diff changeset
265 void compute_local_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
266
a61af66fc99e Initial load
duke
parents:
diff changeset
267 // Phase 3: perform a backward dataflow analysis to compute global live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
268 // (sets live_in and live_out for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
269 void compute_global_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
270
a61af66fc99e Initial load
duke
parents:
diff changeset
271
a61af66fc99e Initial load
duke
parents:
diff changeset
272 // Phase 4: build intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
273 // (fills the list _intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
274 //
a61af66fc99e Initial load
duke
parents:
diff changeset
275 // helper methods used by build_intervals()
a61af66fc99e Initial load
duke
parents:
diff changeset
276 void add_use (Value value, int from, int to, IntervalUseKind use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
277
a61af66fc99e Initial load
duke
parents:
diff changeset
278 void add_def (LIR_Opr opr, int def_pos, IntervalUseKind use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
279 void add_use (LIR_Opr opr, int from, int to, IntervalUseKind use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
280 void add_temp(LIR_Opr opr, int temp_pos, IntervalUseKind use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
281
a61af66fc99e Initial load
duke
parents:
diff changeset
282 void add_def (int reg_num, int def_pos, IntervalUseKind use_kind, BasicType type);
a61af66fc99e Initial load
duke
parents:
diff changeset
283 void add_use (int reg_num, int from, int to, IntervalUseKind use_kind, BasicType type);
a61af66fc99e Initial load
duke
parents:
diff changeset
284 void add_temp(int reg_num, int temp_pos, IntervalUseKind use_kind, BasicType type);
a61af66fc99e Initial load
duke
parents:
diff changeset
285
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // Add platform dependent kills for particular LIR ops. Can be used
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // to add platform dependent behaviour for some operations.
a61af66fc99e Initial load
duke
parents:
diff changeset
288 void pd_add_temps(LIR_Op* op);
a61af66fc99e Initial load
duke
parents:
diff changeset
289
a61af66fc99e Initial load
duke
parents:
diff changeset
290 IntervalUseKind use_kind_of_output_operand(LIR_Op* op, LIR_Opr opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
291 IntervalUseKind use_kind_of_input_operand(LIR_Op* op, LIR_Opr opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
292 void handle_method_arguments(LIR_Op* op);
a61af66fc99e Initial load
duke
parents:
diff changeset
293 void handle_doubleword_moves(LIR_Op* op);
a61af66fc99e Initial load
duke
parents:
diff changeset
294 void add_register_hints(LIR_Op* op);
a61af66fc99e Initial load
duke
parents:
diff changeset
295
a61af66fc99e Initial load
duke
parents:
diff changeset
296 void build_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
297
a61af66fc99e Initial load
duke
parents:
diff changeset
298
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // Phase 5: actual register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // (Uses LinearScanWalker)
a61af66fc99e Initial load
duke
parents:
diff changeset
301 //
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // helper functions for building a sorted list of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
303 NOT_PRODUCT(bool is_sorted(IntervalArray* intervals);)
a61af66fc99e Initial load
duke
parents:
diff changeset
304 static int interval_cmp(Interval** a, Interval** b);
a61af66fc99e Initial load
duke
parents:
diff changeset
305 void add_to_list(Interval** first, Interval** prev, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
306 void create_unhandled_lists(Interval** list1, Interval** list2, bool (is_list1)(const Interval* i), bool (is_list2)(const Interval* i));
a61af66fc99e Initial load
duke
parents:
diff changeset
307
a61af66fc99e Initial load
duke
parents:
diff changeset
308 void sort_intervals_before_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
309 void sort_intervals_after_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
310 void allocate_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
311
a61af66fc99e Initial load
duke
parents:
diff changeset
312
a61af66fc99e Initial load
duke
parents:
diff changeset
313 // Phase 6: resolve data flow
a61af66fc99e Initial load
duke
parents:
diff changeset
314 // (insert moves at edges between blocks if intervals have been split)
a61af66fc99e Initial load
duke
parents:
diff changeset
315 //
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // helper functions for resolve_data_flow()
a61af66fc99e Initial load
duke
parents:
diff changeset
317 Interval* split_child_at_op_id(Interval* interval, int op_id, LIR_OpVisitState::OprMode mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
318 Interval* interval_at_block_begin(BlockBegin* block, int reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
319 Interval* interval_at_block_end(BlockBegin* block, int reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
320 Interval* interval_at_op_id(int reg_num, int op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
321 void resolve_collect_mappings(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
322 void resolve_find_insert_pos(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
323 void resolve_data_flow();
a61af66fc99e Initial load
duke
parents:
diff changeset
324
a61af66fc99e Initial load
duke
parents:
diff changeset
325 void resolve_exception_entry(BlockBegin* block, int reg_num, MoveResolver &move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
326 void resolve_exception_entry(BlockBegin* block, MoveResolver &move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
327 void resolve_exception_edge(XHandler* handler, int throwing_op_id, int reg_num, Phi* phi, MoveResolver &move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
328 void resolve_exception_edge(XHandler* handler, int throwing_op_id, MoveResolver &move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
329 void resolve_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
330
a61af66fc99e Initial load
duke
parents:
diff changeset
331 // Phase 7: assign register numbers back to LIR
a61af66fc99e Initial load
duke
parents:
diff changeset
332 // (includes computation of debug information and oop maps)
a61af66fc99e Initial load
duke
parents:
diff changeset
333 //
a61af66fc99e Initial load
duke
parents:
diff changeset
334 // helper functions for assign_reg_num()
a61af66fc99e Initial load
duke
parents:
diff changeset
335 VMReg vm_reg_for_interval(Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
336 VMReg vm_reg_for_operand(LIR_Opr opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
337
a61af66fc99e Initial load
duke
parents:
diff changeset
338 static LIR_Opr operand_for_interval(Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
339 static LIR_Opr calc_operand_for_interval(const Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
340 LIR_Opr canonical_spill_opr(Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
341
a61af66fc99e Initial load
duke
parents:
diff changeset
342 LIR_Opr color_lir_opr(LIR_Opr opr, int id, LIR_OpVisitState::OprMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
343
a61af66fc99e Initial load
duke
parents:
diff changeset
344 // methods used for oop map computation
a61af66fc99e Initial load
duke
parents:
diff changeset
345 IntervalWalker* init_compute_oop_maps();
a61af66fc99e Initial load
duke
parents:
diff changeset
346 OopMap* compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo* info, bool is_call_site);
a61af66fc99e Initial load
duke
parents:
diff changeset
347 void compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &visitor, LIR_Op* op);
a61af66fc99e Initial load
duke
parents:
diff changeset
348
a61af66fc99e Initial load
duke
parents:
diff changeset
349 // methods used for debug information computation
a61af66fc99e Initial load
duke
parents:
diff changeset
350 void init_compute_debug_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
351
a61af66fc99e Initial load
duke
parents:
diff changeset
352 MonitorValue* location_for_monitor_index(int monitor_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
353 LocationValue* location_for_name(int name, Location::Type loc_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
354
a61af66fc99e Initial load
duke
parents:
diff changeset
355 int append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
356 int append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
357 int append_scope_value(int op_id, Value value, GrowableArray<ScopeValue*>* scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
358
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1584
diff changeset
359 IRScopeDebugInfo* compute_debug_info_for_scope(int op_id, IRScope* cur_scope, ValueStack* cur_state, ValueStack* innermost_state);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
360 void compute_debug_info(CodeEmitInfo* info, int op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
361
a61af66fc99e Initial load
duke
parents:
diff changeset
362 void assign_reg_num(LIR_OpList* instructions, IntervalWalker* iw);
a61af66fc99e Initial load
duke
parents:
diff changeset
363 void assign_reg_num();
a61af66fc99e Initial load
duke
parents:
diff changeset
364
a61af66fc99e Initial load
duke
parents:
diff changeset
365
a61af66fc99e Initial load
duke
parents:
diff changeset
366 // Phase 8: fpu stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
367 // (Used only on x86 when fpu operands are present)
a61af66fc99e Initial load
duke
parents:
diff changeset
368 void allocate_fpu_stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
369
a61af66fc99e Initial load
duke
parents:
diff changeset
370
a61af66fc99e Initial load
duke
parents:
diff changeset
371 // helper functions for printing state
a61af66fc99e Initial load
duke
parents:
diff changeset
372 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
373 static void print_bitmap(BitMap& bitmap);
a61af66fc99e Initial load
duke
parents:
diff changeset
374 void print_intervals(const char* label);
a61af66fc99e Initial load
duke
parents:
diff changeset
375 void print_lir(int level, const char* label, bool hir_valid = true);
a61af66fc99e Initial load
duke
parents:
diff changeset
376 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
377
a61af66fc99e Initial load
duke
parents:
diff changeset
378 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
379 // verification functions for allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
380 // (check that all intervals have a correct register and that no registers are overwritten)
a61af66fc99e Initial load
duke
parents:
diff changeset
381 void verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
382 void verify_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
383 void verify_no_oops_in_fixed_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
384 void verify_constants();
a61af66fc99e Initial load
duke
parents:
diff changeset
385 void verify_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
386 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
387
a61af66fc99e Initial load
duke
parents:
diff changeset
388 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
389 // creation
a61af66fc99e Initial load
duke
parents:
diff changeset
390 LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map);
a61af66fc99e Initial load
duke
parents:
diff changeset
391
a61af66fc99e Initial load
duke
parents:
diff changeset
392 // main entry function: perform linear scan register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
393 void do_linear_scan();
a61af66fc99e Initial load
duke
parents:
diff changeset
394
a61af66fc99e Initial load
duke
parents:
diff changeset
395 // accessors used by Compilation
a61af66fc99e Initial load
duke
parents:
diff changeset
396 int max_spills() const { return _max_spills; }
a61af66fc99e Initial load
duke
parents:
diff changeset
397 int num_calls() const { assert(_num_calls >= 0, "not set"); return _num_calls; }
a61af66fc99e Initial load
duke
parents:
diff changeset
398
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // entry functions for printing
a61af66fc99e Initial load
duke
parents:
diff changeset
400 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
401 static void print_statistics();
a61af66fc99e Initial load
duke
parents:
diff changeset
402 static void print_timers(double total);
a61af66fc99e Initial load
duke
parents:
diff changeset
403 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
404 };
a61af66fc99e Initial load
duke
parents:
diff changeset
405
a61af66fc99e Initial load
duke
parents:
diff changeset
406
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // Helper class for ordering moves that are inserted at the same position in the LIR
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // When moves between registers are inserted, it is important that the moves are
a61af66fc99e Initial load
duke
parents:
diff changeset
409 // ordered such that no register is overwritten. So moves from register to stack
a61af66fc99e Initial load
duke
parents:
diff changeset
410 // are processed prior to moves from stack to register. When moves have circular
a61af66fc99e Initial load
duke
parents:
diff changeset
411 // dependencies, a temporary stack slot is used to break the circle.
a61af66fc99e Initial load
duke
parents:
diff changeset
412 // The same logic is used in the LinearScanWalker and in LinearScan during resolve_data_flow
a61af66fc99e Initial load
duke
parents:
diff changeset
413 // and therefore factored out in a separate class
a61af66fc99e Initial load
duke
parents:
diff changeset
414 class MoveResolver: public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
415 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
416 LinearScan* _allocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
417
a61af66fc99e Initial load
duke
parents:
diff changeset
418 LIR_List* _insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
419 int _insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
420 LIR_InsertionBuffer _insertion_buffer; // buffer where moves are inserted
a61af66fc99e Initial load
duke
parents:
diff changeset
421
a61af66fc99e Initial load
duke
parents:
diff changeset
422 IntervalList _mapping_from;
a61af66fc99e Initial load
duke
parents:
diff changeset
423 LIR_OprList _mapping_from_opr;
a61af66fc99e Initial load
duke
parents:
diff changeset
424 IntervalList _mapping_to;
a61af66fc99e Initial load
duke
parents:
diff changeset
425 bool _multiple_reads_allowed;
a61af66fc99e Initial load
duke
parents:
diff changeset
426 int _register_blocked[LinearScan::nof_regs];
a61af66fc99e Initial load
duke
parents:
diff changeset
427
a61af66fc99e Initial load
duke
parents:
diff changeset
428 int register_blocked(int reg) { assert(reg >= 0 && reg < LinearScan::nof_regs, "out of bounds"); return _register_blocked[reg]; }
a61af66fc99e Initial load
duke
parents:
diff changeset
429 void set_register_blocked(int reg, int direction) { assert(reg >= 0 && reg < LinearScan::nof_regs, "out of bounds"); assert(direction == 1 || direction == -1, "out of bounds"); _register_blocked[reg] += direction; }
a61af66fc99e Initial load
duke
parents:
diff changeset
430
a61af66fc99e Initial load
duke
parents:
diff changeset
431 void block_registers(Interval* it);
a61af66fc99e Initial load
duke
parents:
diff changeset
432 void unblock_registers(Interval* it);
a61af66fc99e Initial load
duke
parents:
diff changeset
433 bool save_to_process_move(Interval* from, Interval* to);
a61af66fc99e Initial load
duke
parents:
diff changeset
434
a61af66fc99e Initial load
duke
parents:
diff changeset
435 void create_insertion_buffer(LIR_List* list);
a61af66fc99e Initial load
duke
parents:
diff changeset
436 void append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
437 void insert_move(Interval* from_interval, Interval* to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
438 void insert_move(LIR_Opr from_opr, Interval* to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
439
a61af66fc99e Initial load
duke
parents:
diff changeset
440 DEBUG_ONLY(void verify_before_resolve();)
a61af66fc99e Initial load
duke
parents:
diff changeset
441 void resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
442 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
443 MoveResolver(LinearScan* allocator);
a61af66fc99e Initial load
duke
parents:
diff changeset
444
a61af66fc99e Initial load
duke
parents:
diff changeset
445 DEBUG_ONLY(void check_empty();)
a61af66fc99e Initial load
duke
parents:
diff changeset
446 void set_multiple_reads_allowed() { _multiple_reads_allowed = true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
447 void set_insert_position(LIR_List* insert_list, int insert_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
448 void move_insert_position(LIR_List* insert_list, int insert_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
449 void add_mapping(Interval* from, Interval* to);
a61af66fc99e Initial load
duke
parents:
diff changeset
450 void add_mapping(LIR_Opr from, Interval* to);
a61af66fc99e Initial load
duke
parents:
diff changeset
451 void resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
452
a61af66fc99e Initial load
duke
parents:
diff changeset
453 LinearScan* allocator() { return _allocator; }
a61af66fc99e Initial load
duke
parents:
diff changeset
454 bool has_mappings() { return _mapping_from.length() > 0; }
a61af66fc99e Initial load
duke
parents:
diff changeset
455 };
a61af66fc99e Initial load
duke
parents:
diff changeset
456
a61af66fc99e Initial load
duke
parents:
diff changeset
457
a61af66fc99e Initial load
duke
parents:
diff changeset
458 class Range : public CompilationResourceObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
459 friend class Interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
460
a61af66fc99e Initial load
duke
parents:
diff changeset
461 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
462 static Range* _end; // sentinel (from == to == max_jint)
a61af66fc99e Initial load
duke
parents:
diff changeset
463
a61af66fc99e Initial load
duke
parents:
diff changeset
464 int _from; // from (inclusive)
a61af66fc99e Initial load
duke
parents:
diff changeset
465 int _to; // to (exclusive)
a61af66fc99e Initial load
duke
parents:
diff changeset
466 Range* _next; // linear list of Ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
467
a61af66fc99e Initial load
duke
parents:
diff changeset
468 // used only by class Interval, so hide them
a61af66fc99e Initial load
duke
parents:
diff changeset
469 bool intersects(Range* r) const { return intersects_at(r) != -1; }
a61af66fc99e Initial load
duke
parents:
diff changeset
470 int intersects_at(Range* r) const;
a61af66fc99e Initial load
duke
parents:
diff changeset
471
a61af66fc99e Initial load
duke
parents:
diff changeset
472 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
473 Range(int from, int to, Range* next);
a61af66fc99e Initial load
duke
parents:
diff changeset
474
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
475 static void initialize(Arena* arena);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
476 static Range* end() { return _end; }
a61af66fc99e Initial load
duke
parents:
diff changeset
477
a61af66fc99e Initial load
duke
parents:
diff changeset
478 int from() const { return _from; }
a61af66fc99e Initial load
duke
parents:
diff changeset
479 int to() const { return _to; }
a61af66fc99e Initial load
duke
parents:
diff changeset
480 Range* next() const { return _next; }
a61af66fc99e Initial load
duke
parents:
diff changeset
481 void set_from(int from) { _from = from; }
a61af66fc99e Initial load
duke
parents:
diff changeset
482 void set_to(int to) { _to = to; }
a61af66fc99e Initial load
duke
parents:
diff changeset
483 void set_next(Range* next) { _next = next; }
a61af66fc99e Initial load
duke
parents:
diff changeset
484
a61af66fc99e Initial load
duke
parents:
diff changeset
485 // for testing
a61af66fc99e Initial load
duke
parents:
diff changeset
486 void print(outputStream* out = tty) const PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
487 };
a61af66fc99e Initial load
duke
parents:
diff changeset
488
a61af66fc99e Initial load
duke
parents:
diff changeset
489
a61af66fc99e Initial load
duke
parents:
diff changeset
490 // Interval is an ordered list of disjoint ranges.
a61af66fc99e Initial load
duke
parents:
diff changeset
491
a61af66fc99e Initial load
duke
parents:
diff changeset
492 // For pre-colored double word LIR_Oprs, one interval is created for
a61af66fc99e Initial load
duke
parents:
diff changeset
493 // the low word register and one is created for the hi word register.
a61af66fc99e Initial load
duke
parents:
diff changeset
494 // On Intel for FPU double registers only one interval is created. At
a61af66fc99e Initial load
duke
parents:
diff changeset
495 // all times assigned_reg contains the reg. number of the physical
a61af66fc99e Initial load
duke
parents:
diff changeset
496 // register.
a61af66fc99e Initial load
duke
parents:
diff changeset
497
a61af66fc99e Initial load
duke
parents:
diff changeset
498 // For LIR_Opr in virtual registers a single interval can represent
a61af66fc99e Initial load
duke
parents:
diff changeset
499 // single and double word values. When a physical register is
a61af66fc99e Initial load
duke
parents:
diff changeset
500 // assigned to the interval, assigned_reg contains the
a61af66fc99e Initial load
duke
parents:
diff changeset
501 // phys. reg. number and for double word values assigned_regHi the
a61af66fc99e Initial load
duke
parents:
diff changeset
502 // phys. reg. number of the hi word if there is any. For spilled
a61af66fc99e Initial load
duke
parents:
diff changeset
503 // intervals assigned_reg contains the stack index. assigned_regHi is
a61af66fc99e Initial load
duke
parents:
diff changeset
504 // always -1.
a61af66fc99e Initial load
duke
parents:
diff changeset
505
a61af66fc99e Initial load
duke
parents:
diff changeset
506 class Interval : public CompilationResourceObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
507 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
508 static Interval* _end; // sentinel (interval with only range Range::end())
a61af66fc99e Initial load
duke
parents:
diff changeset
509
a61af66fc99e Initial load
duke
parents:
diff changeset
510 int _reg_num;
a61af66fc99e Initial load
duke
parents:
diff changeset
511 BasicType _type; // valid only for virtual registers
a61af66fc99e Initial load
duke
parents:
diff changeset
512 Range* _first; // sorted list of Ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
513 intStack _use_pos_and_kinds; // sorted list of use-positions and their according use-kinds
a61af66fc99e Initial load
duke
parents:
diff changeset
514
a61af66fc99e Initial load
duke
parents:
diff changeset
515 Range* _current; // interval iteration: the current Range
a61af66fc99e Initial load
duke
parents:
diff changeset
516 Interval* _next; // interval iteration: sorted list of Intervals (ends with sentinel)
a61af66fc99e Initial load
duke
parents:
diff changeset
517 IntervalState _state; // interval iteration: to which set belongs this interval
a61af66fc99e Initial load
duke
parents:
diff changeset
518
a61af66fc99e Initial load
duke
parents:
diff changeset
519
a61af66fc99e Initial load
duke
parents:
diff changeset
520 int _assigned_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
521 int _assigned_regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
522
a61af66fc99e Initial load
duke
parents:
diff changeset
523 int _cached_to; // cached value: to of last range (-1: not cached)
a61af66fc99e Initial load
duke
parents:
diff changeset
524 LIR_Opr _cached_opr;
a61af66fc99e Initial load
duke
parents:
diff changeset
525 VMReg _cached_vm_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
526
a61af66fc99e Initial load
duke
parents:
diff changeset
527 Interval* _split_parent; // the original interval where this interval is derived from
a61af66fc99e Initial load
duke
parents:
diff changeset
528 IntervalList _split_children; // list of all intervals that are split off from this interval (only available for split parents)
a61af66fc99e Initial load
duke
parents:
diff changeset
529 Interval* _current_split_child; // the current split child that has been active or inactive last (always stored in split parents)
a61af66fc99e Initial load
duke
parents:
diff changeset
530
a61af66fc99e Initial load
duke
parents:
diff changeset
531 int _canonical_spill_slot; // the stack slot where all split parts of this interval are spilled to (always stored in split parents)
a61af66fc99e Initial load
duke
parents:
diff changeset
532 bool _insert_move_when_activated; // true if move is inserted between _current_split_child and this interval when interval gets active the first time
a61af66fc99e Initial load
duke
parents:
diff changeset
533 IntervalSpillState _spill_state; // for spill move optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
534 int _spill_definition_pos; // position where the interval is defined (if defined only once)
a61af66fc99e Initial load
duke
parents:
diff changeset
535 Interval* _register_hint; // this interval should be in the same register as the hint interval
a61af66fc99e Initial load
duke
parents:
diff changeset
536
a61af66fc99e Initial load
duke
parents:
diff changeset
537 int calc_to();
a61af66fc99e Initial load
duke
parents:
diff changeset
538 Interval* new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
539 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
540 Interval(int reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
541
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
542 static void initialize(Arena* arena);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
543 static Interval* end() { return _end; }
a61af66fc99e Initial load
duke
parents:
diff changeset
544
a61af66fc99e Initial load
duke
parents:
diff changeset
545 // accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
546 int reg_num() const { return _reg_num; }
a61af66fc99e Initial load
duke
parents:
diff changeset
547 void set_reg_num(int r) { assert(_reg_num == -1, "cannot change reg_num"); _reg_num = r; }
a61af66fc99e Initial load
duke
parents:
diff changeset
548 BasicType type() const { assert(_reg_num == -1 || _reg_num >= LIR_OprDesc::vreg_base, "cannot access type for fixed interval"); return _type; }
a61af66fc99e Initial load
duke
parents:
diff changeset
549 void set_type(BasicType type) { assert(_reg_num < LIR_OprDesc::vreg_base || _type == T_ILLEGAL || _type == type, "overwriting existing type"); _type = type; }
a61af66fc99e Initial load
duke
parents:
diff changeset
550
a61af66fc99e Initial load
duke
parents:
diff changeset
551 Range* first() const { return _first; }
a61af66fc99e Initial load
duke
parents:
diff changeset
552 int from() const { return _first->from(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
553 int to() { if (_cached_to == -1) _cached_to = calc_to(); assert(_cached_to == calc_to(), "invalid cached value"); return _cached_to; }
a61af66fc99e Initial load
duke
parents:
diff changeset
554 int num_use_positions() const { return _use_pos_and_kinds.length() / 2; }
a61af66fc99e Initial load
duke
parents:
diff changeset
555
a61af66fc99e Initial load
duke
parents:
diff changeset
556 Interval* next() const { return _next; }
a61af66fc99e Initial load
duke
parents:
diff changeset
557 Interval** next_addr() { return &_next; }
a61af66fc99e Initial load
duke
parents:
diff changeset
558 void set_next(Interval* next) { _next = next; }
a61af66fc99e Initial load
duke
parents:
diff changeset
559
a61af66fc99e Initial load
duke
parents:
diff changeset
560 int assigned_reg() const { return _assigned_reg; }
a61af66fc99e Initial load
duke
parents:
diff changeset
561 int assigned_regHi() const { return _assigned_regHi; }
a61af66fc99e Initial load
duke
parents:
diff changeset
562 void assign_reg(int reg) { _assigned_reg = reg; _assigned_regHi = LinearScan::any_reg; }
a61af66fc99e Initial load
duke
parents:
diff changeset
563 void assign_reg(int reg,int regHi) { _assigned_reg = reg; _assigned_regHi = regHi; }
a61af66fc99e Initial load
duke
parents:
diff changeset
564
a61af66fc99e Initial load
duke
parents:
diff changeset
565 Interval* register_hint(bool search_split_child = true) const; // calculation needed
a61af66fc99e Initial load
duke
parents:
diff changeset
566 void set_register_hint(Interval* i) { _register_hint = i; }
a61af66fc99e Initial load
duke
parents:
diff changeset
567
a61af66fc99e Initial load
duke
parents:
diff changeset
568 int state() const { return _state; }
a61af66fc99e Initial load
duke
parents:
diff changeset
569 void set_state(IntervalState s) { _state = s; }
a61af66fc99e Initial load
duke
parents:
diff changeset
570
a61af66fc99e Initial load
duke
parents:
diff changeset
571 // access to split parent and split children
a61af66fc99e Initial load
duke
parents:
diff changeset
572 bool is_split_parent() const { return _split_parent == this; }
a61af66fc99e Initial load
duke
parents:
diff changeset
573 bool is_split_child() const { return _split_parent != this; }
a61af66fc99e Initial load
duke
parents:
diff changeset
574 Interval* split_parent() const { assert(_split_parent->is_split_parent(), "must be"); return _split_parent; }
a61af66fc99e Initial load
duke
parents:
diff changeset
575 Interval* split_child_at_op_id(int op_id, LIR_OpVisitState::OprMode mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
576 Interval* split_child_before_op_id(int op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
577 bool split_child_covers(int op_id, LIR_OpVisitState::OprMode mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
578 DEBUG_ONLY(void check_split_children();)
a61af66fc99e Initial load
duke
parents:
diff changeset
579
a61af66fc99e Initial load
duke
parents:
diff changeset
580 // information stored in split parent, but available for all children
a61af66fc99e Initial load
duke
parents:
diff changeset
581 int canonical_spill_slot() const { return split_parent()->_canonical_spill_slot; }
a61af66fc99e Initial load
duke
parents:
diff changeset
582 void set_canonical_spill_slot(int slot) { assert(split_parent()->_canonical_spill_slot == -1, "overwriting existing value"); split_parent()->_canonical_spill_slot = slot; }
a61af66fc99e Initial load
duke
parents:
diff changeset
583 Interval* current_split_child() const { return split_parent()->_current_split_child; }
a61af66fc99e Initial load
duke
parents:
diff changeset
584 void make_current_split_child() { split_parent()->_current_split_child = this; }
a61af66fc99e Initial load
duke
parents:
diff changeset
585
a61af66fc99e Initial load
duke
parents:
diff changeset
586 bool insert_move_when_activated() const { return _insert_move_when_activated; }
a61af66fc99e Initial load
duke
parents:
diff changeset
587 void set_insert_move_when_activated(bool b) { _insert_move_when_activated = b; }
a61af66fc99e Initial load
duke
parents:
diff changeset
588
a61af66fc99e Initial load
duke
parents:
diff changeset
589 // for spill optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
590 IntervalSpillState spill_state() const { return split_parent()->_spill_state; }
a61af66fc99e Initial load
duke
parents:
diff changeset
591 int spill_definition_pos() const { return split_parent()->_spill_definition_pos; }
a61af66fc99e Initial load
duke
parents:
diff changeset
592 void set_spill_state(IntervalSpillState state) { assert(state >= spill_state(), "state cannot decrease"); split_parent()->_spill_state = state; }
a61af66fc99e Initial load
duke
parents:
diff changeset
593 void set_spill_definition_pos(int pos) { assert(spill_definition_pos() == -1, "cannot set the position twice"); split_parent()->_spill_definition_pos = pos; }
a61af66fc99e Initial load
duke
parents:
diff changeset
594 // returns true if this interval has a shadow copy on the stack that is always correct
a61af66fc99e Initial load
duke
parents:
diff changeset
595 bool always_in_memory() const { return split_parent()->_spill_state == storeAtDefinition || split_parent()->_spill_state == startInMemory; }
a61af66fc99e Initial load
duke
parents:
diff changeset
596
a61af66fc99e Initial load
duke
parents:
diff changeset
597 // caching of values that take time to compute and are used multiple times
a61af66fc99e Initial load
duke
parents:
diff changeset
598 LIR_Opr cached_opr() const { return _cached_opr; }
a61af66fc99e Initial load
duke
parents:
diff changeset
599 VMReg cached_vm_reg() const { return _cached_vm_reg; }
a61af66fc99e Initial load
duke
parents:
diff changeset
600 void set_cached_opr(LIR_Opr opr) { _cached_opr = opr; }
a61af66fc99e Initial load
duke
parents:
diff changeset
601 void set_cached_vm_reg(VMReg reg) { _cached_vm_reg = reg; }
a61af66fc99e Initial load
duke
parents:
diff changeset
602
a61af66fc99e Initial load
duke
parents:
diff changeset
603 // access to use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
604 int first_usage(IntervalUseKind min_use_kind) const; // id of the first operation requiring this interval in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
605 int next_usage(IntervalUseKind min_use_kind, int from) const; // id of next usage seen from the given position
a61af66fc99e Initial load
duke
parents:
diff changeset
606 int next_usage_exact(IntervalUseKind exact_use_kind, int from) const;
a61af66fc99e Initial load
duke
parents:
diff changeset
607 int previous_usage(IntervalUseKind min_use_kind, int from) const;
a61af66fc99e Initial load
duke
parents:
diff changeset
608
a61af66fc99e Initial load
duke
parents:
diff changeset
609 // manipulating intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
610 void add_use_pos(int pos, IntervalUseKind use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
611 void add_range(int from, int to);
a61af66fc99e Initial load
duke
parents:
diff changeset
612 Interval* split(int split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
613 Interval* split_from_start(int split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
614 void remove_first_use_pos() { _use_pos_and_kinds.truncate(_use_pos_and_kinds.length() - 2); }
a61af66fc99e Initial load
duke
parents:
diff changeset
615
a61af66fc99e Initial load
duke
parents:
diff changeset
616 // test intersection
a61af66fc99e Initial load
duke
parents:
diff changeset
617 bool covers(int op_id, LIR_OpVisitState::OprMode mode) const;
a61af66fc99e Initial load
duke
parents:
diff changeset
618 bool has_hole_between(int from, int to);
a61af66fc99e Initial load
duke
parents:
diff changeset
619 bool intersects(Interval* i) const { return _first->intersects(i->_first); }
a61af66fc99e Initial load
duke
parents:
diff changeset
620 int intersects_at(Interval* i) const { return _first->intersects_at(i->_first); }
a61af66fc99e Initial load
duke
parents:
diff changeset
621
a61af66fc99e Initial load
duke
parents:
diff changeset
622 // range iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
623 void rewind_range() { _current = _first; }
a61af66fc99e Initial load
duke
parents:
diff changeset
624 void next_range() { assert(this != _end, "not allowed on sentinel"); _current = _current->next(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
625 int current_from() const { return _current->from(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
626 int current_to() const { return _current->to(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
627 bool current_at_end() const { return _current == Range::end(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
628 bool current_intersects(Interval* it) { return _current->intersects(it->_current); };
a61af66fc99e Initial load
duke
parents:
diff changeset
629 int current_intersects_at(Interval* it) { return _current->intersects_at(it->_current); };
a61af66fc99e Initial load
duke
parents:
diff changeset
630
a61af66fc99e Initial load
duke
parents:
diff changeset
631 // printing
a61af66fc99e Initial load
duke
parents:
diff changeset
632 void print(outputStream* out = tty) const PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
633 };
a61af66fc99e Initial load
duke
parents:
diff changeset
634
a61af66fc99e Initial load
duke
parents:
diff changeset
635
a61af66fc99e Initial load
duke
parents:
diff changeset
636 class IntervalWalker : public CompilationResourceObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
637 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
638 Compilation* _compilation;
a61af66fc99e Initial load
duke
parents:
diff changeset
639 LinearScan* _allocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
640
a61af66fc99e Initial load
duke
parents:
diff changeset
641 Interval* _unhandled_first[nofKinds]; // sorted list of intervals, not life before the current position
a61af66fc99e Initial load
duke
parents:
diff changeset
642 Interval* _active_first [nofKinds]; // sorted list of intervals, life at the current position
a61af66fc99e Initial load
duke
parents:
diff changeset
643 Interval* _inactive_first [nofKinds]; // sorted list of intervals, intervals in a life time hole at the current position
a61af66fc99e Initial load
duke
parents:
diff changeset
644
a61af66fc99e Initial load
duke
parents:
diff changeset
645 Interval* _current; // the current interval coming from unhandled list
a61af66fc99e Initial load
duke
parents:
diff changeset
646 int _current_position; // the current position (intercept point through the intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
647 IntervalKind _current_kind; // and whether it is fixed_kind or any_kind.
a61af66fc99e Initial load
duke
parents:
diff changeset
648
a61af66fc99e Initial load
duke
parents:
diff changeset
649
a61af66fc99e Initial load
duke
parents:
diff changeset
650 Compilation* compilation() const { return _compilation; }
a61af66fc99e Initial load
duke
parents:
diff changeset
651 LinearScan* allocator() const { return _allocator; }
a61af66fc99e Initial load
duke
parents:
diff changeset
652
a61af66fc99e Initial load
duke
parents:
diff changeset
653 // unified bailout support
a61af66fc99e Initial load
duke
parents:
diff changeset
654 void bailout(const char* msg) const { compilation()->bailout(msg); }
a61af66fc99e Initial load
duke
parents:
diff changeset
655 bool bailed_out() const { return compilation()->bailed_out(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
656
a61af66fc99e Initial load
duke
parents:
diff changeset
657 void check_bounds(IntervalKind kind) { assert(kind >= fixedKind && kind <= anyKind, "invalid interval_kind"); }
a61af66fc99e Initial load
duke
parents:
diff changeset
658
a61af66fc99e Initial load
duke
parents:
diff changeset
659 Interval** unhandled_first_addr(IntervalKind kind) { check_bounds(kind); return &_unhandled_first[kind]; }
a61af66fc99e Initial load
duke
parents:
diff changeset
660 Interval** active_first_addr(IntervalKind kind) { check_bounds(kind); return &_active_first[kind]; }
a61af66fc99e Initial load
duke
parents:
diff changeset
661 Interval** inactive_first_addr(IntervalKind kind) { check_bounds(kind); return &_inactive_first[kind]; }
a61af66fc99e Initial load
duke
parents:
diff changeset
662
a61af66fc99e Initial load
duke
parents:
diff changeset
663 void append_unsorted(Interval** first, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
664 void append_sorted(Interval** first, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
665 void append_to_unhandled(Interval** list, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
666
a61af66fc99e Initial load
duke
parents:
diff changeset
667 bool remove_from_list(Interval** list, Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
668 void remove_from_list(Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
669
a61af66fc99e Initial load
duke
parents:
diff changeset
670 void next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
671 Interval* current() const { return _current; }
a61af66fc99e Initial load
duke
parents:
diff changeset
672 IntervalKind current_kind() const { return _current_kind; }
a61af66fc99e Initial load
duke
parents:
diff changeset
673
a61af66fc99e Initial load
duke
parents:
diff changeset
674 void walk_to(IntervalState state, int from);
a61af66fc99e Initial load
duke
parents:
diff changeset
675
a61af66fc99e Initial load
duke
parents:
diff changeset
676 // activate_current() is called when an unhandled interval becomes active (in current(), current_kind()).
a61af66fc99e Initial load
duke
parents:
diff changeset
677 // Return false if current() should not be moved the the active interval list.
a61af66fc99e Initial load
duke
parents:
diff changeset
678 // It is safe to append current to any interval list but the unhandled list.
a61af66fc99e Initial load
duke
parents:
diff changeset
679 virtual bool activate_current() { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
680
a61af66fc99e Initial load
duke
parents:
diff changeset
681 // interval_moved() is called whenever an interval moves from one interval list to another.
a61af66fc99e Initial load
duke
parents:
diff changeset
682 // In the implementation of this method it is prohibited to move the interval to any list.
a61af66fc99e Initial load
duke
parents:
diff changeset
683 virtual void interval_moved(Interval* interval, IntervalKind kind, IntervalState from, IntervalState to);
a61af66fc99e Initial load
duke
parents:
diff changeset
684
a61af66fc99e Initial load
duke
parents:
diff changeset
685 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
686 IntervalWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first);
a61af66fc99e Initial load
duke
parents:
diff changeset
687
a61af66fc99e Initial load
duke
parents:
diff changeset
688 Interval* unhandled_first(IntervalKind kind) { check_bounds(kind); return _unhandled_first[kind]; }
a61af66fc99e Initial load
duke
parents:
diff changeset
689 Interval* active_first(IntervalKind kind) { check_bounds(kind); return _active_first[kind]; }
a61af66fc99e Initial load
duke
parents:
diff changeset
690 Interval* inactive_first(IntervalKind kind) { check_bounds(kind); return _inactive_first[kind]; }
a61af66fc99e Initial load
duke
parents:
diff changeset
691
a61af66fc99e Initial load
duke
parents:
diff changeset
692 // active contains the intervals that are live after the lir_op
a61af66fc99e Initial load
duke
parents:
diff changeset
693 void walk_to(int lir_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
694 // active contains the intervals that are live before the lir_op
a61af66fc99e Initial load
duke
parents:
diff changeset
695 void walk_before(int lir_op_id) { walk_to(lir_op_id-1); }
a61af66fc99e Initial load
duke
parents:
diff changeset
696 // walk through all intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
697 void walk() { walk_to(max_jint); }
a61af66fc99e Initial load
duke
parents:
diff changeset
698
a61af66fc99e Initial load
duke
parents:
diff changeset
699 int current_position() { return _current_position; }
a61af66fc99e Initial load
duke
parents:
diff changeset
700 };
a61af66fc99e Initial load
duke
parents:
diff changeset
701
a61af66fc99e Initial load
duke
parents:
diff changeset
702
a61af66fc99e Initial load
duke
parents:
diff changeset
703 // The actual linear scan register allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
704 class LinearScanWalker : public IntervalWalker {
a61af66fc99e Initial load
duke
parents:
diff changeset
705 enum {
a61af66fc99e Initial load
duke
parents:
diff changeset
706 any_reg = LinearScan::any_reg
a61af66fc99e Initial load
duke
parents:
diff changeset
707 };
a61af66fc99e Initial load
duke
parents:
diff changeset
708
a61af66fc99e Initial load
duke
parents:
diff changeset
709 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
710 int _first_reg; // the reg. number of the first phys. register
a61af66fc99e Initial load
duke
parents:
diff changeset
711 int _last_reg; // the reg. nmber of the last phys. register
a61af66fc99e Initial load
duke
parents:
diff changeset
712 int _num_phys_regs; // required by current interval
a61af66fc99e Initial load
duke
parents:
diff changeset
713 bool _adjacent_regs; // have lo/hi words of phys. regs be adjacent
a61af66fc99e Initial load
duke
parents:
diff changeset
714
a61af66fc99e Initial load
duke
parents:
diff changeset
715 int _use_pos[LinearScan::nof_regs];
a61af66fc99e Initial load
duke
parents:
diff changeset
716 int _block_pos[LinearScan::nof_regs];
a61af66fc99e Initial load
duke
parents:
diff changeset
717 IntervalList* _spill_intervals[LinearScan::nof_regs];
a61af66fc99e Initial load
duke
parents:
diff changeset
718
a61af66fc99e Initial load
duke
parents:
diff changeset
719 MoveResolver _move_resolver; // for ordering spill moves
a61af66fc99e Initial load
duke
parents:
diff changeset
720
a61af66fc99e Initial load
duke
parents:
diff changeset
721 // accessors mapped to same functions in class LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
722 int block_count() const { return allocator()->block_count(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
723 BlockBegin* block_at(int idx) const { return allocator()->block_at(idx); }
a61af66fc99e Initial load
duke
parents:
diff changeset
724 BlockBegin* block_of_op_with_id(int op_id) const { return allocator()->block_of_op_with_id(op_id); }
a61af66fc99e Initial load
duke
parents:
diff changeset
725
a61af66fc99e Initial load
duke
parents:
diff changeset
726 void init_use_lists(bool only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
727 void exclude_from_use(int reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
728 void exclude_from_use(Interval* i);
a61af66fc99e Initial load
duke
parents:
diff changeset
729 void set_use_pos(int reg, Interval* i, int use_pos, bool only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
730 void set_use_pos(Interval* i, int use_pos, bool only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
731 void set_block_pos(int reg, Interval* i, int block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
732 void set_block_pos(Interval* i, int block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
733
a61af66fc99e Initial load
duke
parents:
diff changeset
734 void free_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
735 void free_exclude_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
736 void free_collect_inactive_fixed(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
737 void free_collect_inactive_any(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
738 void free_collect_unhandled(IntervalKind kind, Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
739 void spill_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
740 void spill_block_unhandled_fixed(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
741 void spill_block_inactive_fixed(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
742 void spill_collect_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
743 void spill_collect_inactive_any(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
744
a61af66fc99e Initial load
duke
parents:
diff changeset
745 void insert_move(int op_id, Interval* src_it, Interval* dst_it);
a61af66fc99e Initial load
duke
parents:
diff changeset
746 int find_optimal_split_pos(BlockBegin* min_block, BlockBegin* max_block, int max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
747 int find_optimal_split_pos(Interval* it, int min_split_pos, int max_split_pos, bool do_loop_optimization);
a61af66fc99e Initial load
duke
parents:
diff changeset
748 void split_before_usage(Interval* it, int min_split_pos, int max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
749 void split_for_spilling(Interval* it);
a61af66fc99e Initial load
duke
parents:
diff changeset
750 void split_stack_interval(Interval* it);
a61af66fc99e Initial load
duke
parents:
diff changeset
751 void split_when_partial_register_available(Interval* it, int register_available_until);
a61af66fc99e Initial load
duke
parents:
diff changeset
752 void split_and_spill_interval(Interval* it);
a61af66fc99e Initial load
duke
parents:
diff changeset
753
a61af66fc99e Initial load
duke
parents:
diff changeset
754 int find_free_reg(int reg_needed_until, int interval_to, int hint_reg, int ignore_reg, bool* need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
755 int find_free_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
756 bool alloc_free_reg(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
757
a61af66fc99e Initial load
duke
parents:
diff changeset
758 int find_locked_reg(int reg_needed_until, int interval_to, int hint_reg, int ignore_reg, bool* need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
759 int find_locked_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
760 void split_and_spill_intersecting_intervals(int reg, int regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
761 void alloc_locked_reg(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
762
a61af66fc99e Initial load
duke
parents:
diff changeset
763 bool no_allocation_possible(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
764 void update_phys_reg_range(bool requires_cpu_register);
a61af66fc99e Initial load
duke
parents:
diff changeset
765 void init_vars_for_alloc(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
766 bool pd_init_regs_for_alloc(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
767
a61af66fc99e Initial load
duke
parents:
diff changeset
768 void combine_spilled_intervals(Interval* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
769 bool is_move(LIR_Op* op, Interval* from, Interval* to);
a61af66fc99e Initial load
duke
parents:
diff changeset
770
a61af66fc99e Initial load
duke
parents:
diff changeset
771 bool activate_current();
a61af66fc99e Initial load
duke
parents:
diff changeset
772
a61af66fc99e Initial load
duke
parents:
diff changeset
773 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
774 LinearScanWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first);
a61af66fc99e Initial load
duke
parents:
diff changeset
775
a61af66fc99e Initial load
duke
parents:
diff changeset
776 // must be called when all intervals are allocated
a61af66fc99e Initial load
duke
parents:
diff changeset
777 void finish_allocation() { _move_resolver.resolve_and_append_moves(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
778 };
a61af66fc99e Initial load
duke
parents:
diff changeset
779
a61af66fc99e Initial load
duke
parents:
diff changeset
780
a61af66fc99e Initial load
duke
parents:
diff changeset
781
a61af66fc99e Initial load
duke
parents:
diff changeset
782 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
783 When a block has more than one predecessor, and all predecessors end with
a61af66fc99e Initial load
duke
parents:
diff changeset
784 the same sequence of move-instructions, than this moves can be placed once
a61af66fc99e Initial load
duke
parents:
diff changeset
785 at the beginning of the block instead of multiple times in the predecessors.
a61af66fc99e Initial load
duke
parents:
diff changeset
786
a61af66fc99e Initial load
duke
parents:
diff changeset
787 Similarly, when a block has more than one successor, then equal sequences of
a61af66fc99e Initial load
duke
parents:
diff changeset
788 moves at the beginning of the successors can be placed once at the end of
a61af66fc99e Initial load
duke
parents:
diff changeset
789 the block. But because the moves must be inserted before all branch
a61af66fc99e Initial load
duke
parents:
diff changeset
790 instructions, this works only when there is exactly one conditional branch
a61af66fc99e Initial load
duke
parents:
diff changeset
791 at the end of the block (because the moves must be inserted before all
a61af66fc99e Initial load
duke
parents:
diff changeset
792 branches, but after all compares).
a61af66fc99e Initial load
duke
parents:
diff changeset
793
a61af66fc99e Initial load
duke
parents:
diff changeset
794 This optimization affects all kind of moves (reg->reg, reg->stack and
a61af66fc99e Initial load
duke
parents:
diff changeset
795 stack->reg). Because this optimization works best when a block contains only
a61af66fc99e Initial load
duke
parents:
diff changeset
796 few moves, it has a huge impact on the number of blocks that are totally
a61af66fc99e Initial load
duke
parents:
diff changeset
797 empty.
a61af66fc99e Initial load
duke
parents:
diff changeset
798 */
a61af66fc99e Initial load
duke
parents:
diff changeset
799 class EdgeMoveOptimizer : public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
800 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
801 // the class maintains a list with all lir-instruction-list of the
a61af66fc99e Initial load
duke
parents:
diff changeset
802 // successors (predecessors) and the current index into the lir-lists
a61af66fc99e Initial load
duke
parents:
diff changeset
803 LIR_OpListStack _edge_instructions;
a61af66fc99e Initial load
duke
parents:
diff changeset
804 intStack _edge_instructions_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
805
a61af66fc99e Initial load
duke
parents:
diff changeset
806 void init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
807 void append_instructions(LIR_OpList* instructions, int instructions_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
808 LIR_Op* instruction_at(int edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
809 void remove_cur_instruction(int edge, bool decrement_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
810
a61af66fc99e Initial load
duke
parents:
diff changeset
811 bool operations_different(LIR_Op* op1, LIR_Op* op2);
a61af66fc99e Initial load
duke
parents:
diff changeset
812
a61af66fc99e Initial load
duke
parents:
diff changeset
813 void optimize_moves_at_block_end(BlockBegin* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
814 void optimize_moves_at_block_begin(BlockBegin* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
815
a61af66fc99e Initial load
duke
parents:
diff changeset
816 EdgeMoveOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
817
a61af66fc99e Initial load
duke
parents:
diff changeset
818 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
819 static void optimize(BlockList* code);
a61af66fc99e Initial load
duke
parents:
diff changeset
820 };
a61af66fc99e Initial load
duke
parents:
diff changeset
821
a61af66fc99e Initial load
duke
parents:
diff changeset
822
a61af66fc99e Initial load
duke
parents:
diff changeset
823
a61af66fc99e Initial load
duke
parents:
diff changeset
824 class ControlFlowOptimizer : public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
825 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
826 BlockList _original_preds;
a61af66fc99e Initial load
duke
parents:
diff changeset
827
a61af66fc99e Initial load
duke
parents:
diff changeset
828 enum {
a61af66fc99e Initial load
duke
parents:
diff changeset
829 ShortLoopSize = 5
a61af66fc99e Initial load
duke
parents:
diff changeset
830 };
a61af66fc99e Initial load
duke
parents:
diff changeset
831 void reorder_short_loop(BlockList* code, BlockBegin* header_block, int header_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
832 void reorder_short_loops(BlockList* code);
a61af66fc99e Initial load
duke
parents:
diff changeset
833
a61af66fc99e Initial load
duke
parents:
diff changeset
834 bool can_delete_block(BlockBegin* cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
835 void substitute_branch_target(BlockBegin* cur, BlockBegin* target_from, BlockBegin* target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
836 void delete_empty_blocks(BlockList* code);
a61af66fc99e Initial load
duke
parents:
diff changeset
837
a61af66fc99e Initial load
duke
parents:
diff changeset
838 void delete_unnecessary_jumps(BlockList* code);
a61af66fc99e Initial load
duke
parents:
diff changeset
839 void delete_jumps_to_return(BlockList* code);
a61af66fc99e Initial load
duke
parents:
diff changeset
840
a61af66fc99e Initial load
duke
parents:
diff changeset
841 DEBUG_ONLY(void verify(BlockList* code);)
a61af66fc99e Initial load
duke
parents:
diff changeset
842
a61af66fc99e Initial load
duke
parents:
diff changeset
843 ControlFlowOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
844 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
845 static void optimize(BlockList* code);
a61af66fc99e Initial load
duke
parents:
diff changeset
846 };
a61af66fc99e Initial load
duke
parents:
diff changeset
847
a61af66fc99e Initial load
duke
parents:
diff changeset
848
a61af66fc99e Initial load
duke
parents:
diff changeset
849 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
850
a61af66fc99e Initial load
duke
parents:
diff changeset
851 // Helper class for collecting statistics of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
852 class LinearScanStatistic : public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
853 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
854 enum Counter {
a61af66fc99e Initial load
duke
parents:
diff changeset
855 // general counters
a61af66fc99e Initial load
duke
parents:
diff changeset
856 counter_method,
a61af66fc99e Initial load
duke
parents:
diff changeset
857 counter_fpu_method,
a61af66fc99e Initial load
duke
parents:
diff changeset
858 counter_loop_method,
a61af66fc99e Initial load
duke
parents:
diff changeset
859 counter_exception_method,
a61af66fc99e Initial load
duke
parents:
diff changeset
860 counter_loop,
a61af66fc99e Initial load
duke
parents:
diff changeset
861 counter_block,
a61af66fc99e Initial load
duke
parents:
diff changeset
862 counter_loop_block,
a61af66fc99e Initial load
duke
parents:
diff changeset
863 counter_exception_block,
a61af66fc99e Initial load
duke
parents:
diff changeset
864 counter_interval,
a61af66fc99e Initial load
duke
parents:
diff changeset
865 counter_fixed_interval,
a61af66fc99e Initial load
duke
parents:
diff changeset
866 counter_range,
a61af66fc99e Initial load
duke
parents:
diff changeset
867 counter_fixed_range,
a61af66fc99e Initial load
duke
parents:
diff changeset
868 counter_use_pos,
a61af66fc99e Initial load
duke
parents:
diff changeset
869 counter_fixed_use_pos,
a61af66fc99e Initial load
duke
parents:
diff changeset
870 counter_spill_slots,
a61af66fc99e Initial load
duke
parents:
diff changeset
871 blank_line_1,
a61af66fc99e Initial load
duke
parents:
diff changeset
872
a61af66fc99e Initial load
duke
parents:
diff changeset
873 // counter for classes of lir instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
874 counter_instruction,
a61af66fc99e Initial load
duke
parents:
diff changeset
875 counter_label,
a61af66fc99e Initial load
duke
parents:
diff changeset
876 counter_entry,
a61af66fc99e Initial load
duke
parents:
diff changeset
877 counter_return,
a61af66fc99e Initial load
duke
parents:
diff changeset
878 counter_call,
a61af66fc99e Initial load
duke
parents:
diff changeset
879 counter_move,
a61af66fc99e Initial load
duke
parents:
diff changeset
880 counter_cmp,
a61af66fc99e Initial load
duke
parents:
diff changeset
881 counter_cond_branch,
a61af66fc99e Initial load
duke
parents:
diff changeset
882 counter_uncond_branch,
a61af66fc99e Initial load
duke
parents:
diff changeset
883 counter_stub_branch,
a61af66fc99e Initial load
duke
parents:
diff changeset
884 counter_alu,
a61af66fc99e Initial load
duke
parents:
diff changeset
885 counter_alloc,
a61af66fc99e Initial load
duke
parents:
diff changeset
886 counter_sync,
a61af66fc99e Initial load
duke
parents:
diff changeset
887 counter_throw,
a61af66fc99e Initial load
duke
parents:
diff changeset
888 counter_unwind,
a61af66fc99e Initial load
duke
parents:
diff changeset
889 counter_typecheck,
a61af66fc99e Initial load
duke
parents:
diff changeset
890 counter_fpu_stack,
a61af66fc99e Initial load
duke
parents:
diff changeset
891 counter_misc_inst,
a61af66fc99e Initial load
duke
parents:
diff changeset
892 counter_other_inst,
a61af66fc99e Initial load
duke
parents:
diff changeset
893 blank_line_2,
a61af66fc99e Initial load
duke
parents:
diff changeset
894
a61af66fc99e Initial load
duke
parents:
diff changeset
895 // counter for different types of moves
a61af66fc99e Initial load
duke
parents:
diff changeset
896 counter_move_total,
a61af66fc99e Initial load
duke
parents:
diff changeset
897 counter_move_reg_reg,
a61af66fc99e Initial load
duke
parents:
diff changeset
898 counter_move_reg_stack,
a61af66fc99e Initial load
duke
parents:
diff changeset
899 counter_move_stack_reg,
a61af66fc99e Initial load
duke
parents:
diff changeset
900 counter_move_stack_stack,
a61af66fc99e Initial load
duke
parents:
diff changeset
901 counter_move_reg_mem,
a61af66fc99e Initial load
duke
parents:
diff changeset
902 counter_move_mem_reg,
a61af66fc99e Initial load
duke
parents:
diff changeset
903 counter_move_const_any,
a61af66fc99e Initial load
duke
parents:
diff changeset
904
a61af66fc99e Initial load
duke
parents:
diff changeset
905 number_of_counters,
a61af66fc99e Initial load
duke
parents:
diff changeset
906 invalid_counter = -1
a61af66fc99e Initial load
duke
parents:
diff changeset
907 };
a61af66fc99e Initial load
duke
parents:
diff changeset
908
a61af66fc99e Initial load
duke
parents:
diff changeset
909 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
910 int _counters_sum[number_of_counters];
a61af66fc99e Initial load
duke
parents:
diff changeset
911 int _counters_max[number_of_counters];
a61af66fc99e Initial load
duke
parents:
diff changeset
912
a61af66fc99e Initial load
duke
parents:
diff changeset
913 void inc_counter(Counter idx, int value = 1) { _counters_sum[idx] += value; }
a61af66fc99e Initial load
duke
parents:
diff changeset
914
a61af66fc99e Initial load
duke
parents:
diff changeset
915 const char* counter_name(int counter_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
916 Counter base_counter(int counter_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
917
a61af66fc99e Initial load
duke
parents:
diff changeset
918 void sum_up(LinearScanStatistic &method_statistic);
a61af66fc99e Initial load
duke
parents:
diff changeset
919 void collect(LinearScan* allocator);
a61af66fc99e Initial load
duke
parents:
diff changeset
920
a61af66fc99e Initial load
duke
parents:
diff changeset
921 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
922 LinearScanStatistic();
a61af66fc99e Initial load
duke
parents:
diff changeset
923 void print(const char* title);
a61af66fc99e Initial load
duke
parents:
diff changeset
924 static void compute(LinearScan* allocator, LinearScanStatistic &global_statistic);
a61af66fc99e Initial load
duke
parents:
diff changeset
925 };
a61af66fc99e Initial load
duke
parents:
diff changeset
926
a61af66fc99e Initial load
duke
parents:
diff changeset
927
a61af66fc99e Initial load
duke
parents:
diff changeset
928 // Helper class for collecting compilation time of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
929 class LinearScanTimers : public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
930 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
931 enum Timer {
a61af66fc99e Initial load
duke
parents:
diff changeset
932 timer_do_nothing,
a61af66fc99e Initial load
duke
parents:
diff changeset
933 timer_number_instructions,
a61af66fc99e Initial load
duke
parents:
diff changeset
934 timer_compute_local_live_sets,
a61af66fc99e Initial load
duke
parents:
diff changeset
935 timer_compute_global_live_sets,
a61af66fc99e Initial load
duke
parents:
diff changeset
936 timer_build_intervals,
a61af66fc99e Initial load
duke
parents:
diff changeset
937 timer_sort_intervals_before,
a61af66fc99e Initial load
duke
parents:
diff changeset
938 timer_allocate_registers,
a61af66fc99e Initial load
duke
parents:
diff changeset
939 timer_resolve_data_flow,
a61af66fc99e Initial load
duke
parents:
diff changeset
940 timer_sort_intervals_after,
a61af66fc99e Initial load
duke
parents:
diff changeset
941 timer_eliminate_spill_moves,
a61af66fc99e Initial load
duke
parents:
diff changeset
942 timer_assign_reg_num,
a61af66fc99e Initial load
duke
parents:
diff changeset
943 timer_allocate_fpu_stack,
a61af66fc99e Initial load
duke
parents:
diff changeset
944 timer_optimize_lir,
a61af66fc99e Initial load
duke
parents:
diff changeset
945
a61af66fc99e Initial load
duke
parents:
diff changeset
946 number_of_timers
a61af66fc99e Initial load
duke
parents:
diff changeset
947 };
a61af66fc99e Initial load
duke
parents:
diff changeset
948
a61af66fc99e Initial load
duke
parents:
diff changeset
949 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
950 elapsedTimer _timers[number_of_timers];
a61af66fc99e Initial load
duke
parents:
diff changeset
951 const char* timer_name(int idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
952
a61af66fc99e Initial load
duke
parents:
diff changeset
953 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
954 LinearScanTimers();
a61af66fc99e Initial load
duke
parents:
diff changeset
955
a61af66fc99e Initial load
duke
parents:
diff changeset
956 void begin_method(); // called for each method when register allocation starts
a61af66fc99e Initial load
duke
parents:
diff changeset
957 void end_method(LinearScan* allocator); // called for each method when register allocation completed
a61af66fc99e Initial load
duke
parents:
diff changeset
958 void print(double total_time); // called before termination of VM to print global summary
a61af66fc99e Initial load
duke
parents:
diff changeset
959
a61af66fc99e Initial load
duke
parents:
diff changeset
960 elapsedTimer* timer(int idx) { return &(_timers[idx]); }
a61af66fc99e Initial load
duke
parents:
diff changeset
961 };
a61af66fc99e Initial load
duke
parents:
diff changeset
962
a61af66fc99e Initial load
duke
parents:
diff changeset
963
a61af66fc99e Initial load
duke
parents:
diff changeset
964 #endif // ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
965
a61af66fc99e Initial load
duke
parents:
diff changeset
966
a61af66fc99e Initial load
duke
parents:
diff changeset
967 // Pick up platform-dependent implementation details
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
968 #ifdef TARGET_ARCH_x86
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
969 # include "c1_LinearScan_x86.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
970 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
971 #ifdef TARGET_ARCH_sparc
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
972 # include "c1_LinearScan_sparc.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
973 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
974
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
975
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
976 #endif // SHARE_VM_C1_C1_LINEARSCAN_HPP