Mercurial > hg > truffle
annotate src/share/vm/c1/c1_RangeCheckElimination.hpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | 55fb97c4c58d |
children | 4ca6dc0799b6 |
rev | line source |
---|---|
8860 | 1 /* |
17467
55fb97c4c58d
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents:
12882
diff
changeset
|
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. |
8860 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 * | |
23 */ | |
24 | |
25 #ifndef SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP | |
26 #define SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP | |
27 | |
28 #include "c1/c1_Instruction.hpp" | |
29 | |
30 // Base class for range check elimination | |
31 class RangeCheckElimination : AllStatic { | |
32 public: | |
33 static void eliminate(IR *ir); | |
34 }; | |
35 | |
36 // Implementation | |
37 class RangeCheckEliminator VALUE_OBJ_CLASS_SPEC { | |
38 private: | |
39 int _number_of_instructions; | |
40 bool _optimistic; // Insert predicates and deoptimize when they fail | |
41 IR *_ir; | |
42 | |
43 define_array(BlockBeginArray, BlockBegin*) | |
44 define_stack(BlockBeginList, BlockBeginArray) | |
45 define_stack(IntegerStack, intArray) | |
46 define_array(IntegerMap, IntegerStack*) | |
47 | |
48 class Verification : public _ValueObj /*VALUE_OBJ_CLASS_SPEC*/, public BlockClosure { | |
49 private: | |
50 IR *_ir; | |
51 boolArray _used; | |
52 BlockBeginList _current; | |
53 BlockBeginList _successors; | |
54 | |
55 public: | |
56 Verification(IR *ir); | |
57 virtual void block_do(BlockBegin *block); | |
58 bool can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use = NULL); | |
59 bool dominates(BlockBegin *dominator, BlockBegin *block); | |
60 }; | |
61 | |
62 public: | |
63 // Bounds for an instruction in the form x + c which c integer | |
64 // constant and x another instruction | |
65 class Bound : public CompilationResourceObj { | |
66 private: | |
67 int _upper; | |
68 Value _upper_instr; | |
69 int _lower; | |
70 Value _lower_instr; | |
71 | |
72 public: | |
73 Bound(); | |
74 Bound(Value v); | |
75 Bound(Instruction::Condition cond, Value v, int constant = 0); | |
76 Bound(int lower, Value lower_instr, int upper, Value upper_instr); | |
77 ~Bound(); | |
78 | |
79 #ifdef ASSERT | |
80 void add_assertion(Instruction *instruction, Instruction *position, int i, Value instr, Instruction::Condition cond); | |
81 #endif | |
82 int upper(); | |
83 Value upper_instr(); | |
84 int lower(); | |
85 Value lower_instr(); | |
86 void print(); | |
87 bool check_no_overflow(int const_value); | |
88 void or_op(Bound *b); | |
89 void and_op(Bound *b); | |
90 bool has_upper(); | |
91 bool has_lower(); | |
92 void set_upper(int upper, Value upper_instr); | |
93 void set_lower(int lower, Value lower_instr); | |
94 bool is_smaller(Bound *b); | |
95 void remove_upper(); | |
96 void remove_lower(); | |
97 void add_constant(int value); | |
98 Bound *copy(); | |
99 | |
100 private: | |
101 void init(); | |
102 }; | |
103 | |
104 | |
105 class Visitor : public InstructionVisitor { | |
106 private: | |
107 Bound *_bound; | |
108 RangeCheckEliminator *_rce; | |
109 | |
110 public: | |
111 void set_range_check_eliminator(RangeCheckEliminator *rce) { _rce = rce; } | |
112 Bound *bound() const { return _bound; } | |
113 void clear_bound() { _bound = NULL; } | |
114 | |
115 protected: | |
116 // visitor functions | |
117 void do_Constant (Constant* x); | |
118 void do_IfOp (IfOp* x); | |
119 void do_LogicOp (LogicOp* x); | |
120 void do_ArithmeticOp (ArithmeticOp* x); | |
121 void do_Phi (Phi* x); | |
122 | |
123 void do_StoreField (StoreField* x) { /* nothing to do */ }; | |
124 void do_StoreIndexed (StoreIndexed* x) { /* nothing to do */ }; | |
125 void do_MonitorEnter (MonitorEnter* x) { /* nothing to do */ }; | |
126 void do_MonitorExit (MonitorExit* x) { /* nothing to do */ }; | |
127 void do_Invoke (Invoke* x) { /* nothing to do */ }; | |
128 void do_UnsafePutRaw (UnsafePutRaw* x) { /* nothing to do */ }; | |
129 void do_UnsafePutObject(UnsafePutObject* x) { /* nothing to do */ }; | |
130 void do_Intrinsic (Intrinsic* x) { /* nothing to do */ }; | |
131 void do_Local (Local* x) { /* nothing to do */ }; | |
132 void do_LoadField (LoadField* x) { /* nothing to do */ }; | |
133 void do_ArrayLength (ArrayLength* x) { /* nothing to do */ }; | |
134 void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ }; | |
135 void do_NegateOp (NegateOp* x) { /* nothing to do */ }; | |
136 void do_ShiftOp (ShiftOp* x) { /* nothing to do */ }; | |
137 void do_CompareOp (CompareOp* x) { /* nothing to do */ }; | |
138 void do_Convert (Convert* x) { /* nothing to do */ }; | |
139 void do_NullCheck (NullCheck* x) { /* nothing to do */ }; | |
140 void do_TypeCast (TypeCast* x) { /* nothing to do */ }; | |
141 void do_NewInstance (NewInstance* x) { /* nothing to do */ }; | |
142 void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }; | |
143 void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }; | |
144 void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ }; | |
145 void do_CheckCast (CheckCast* x) { /* nothing to do */ }; | |
146 void do_InstanceOf (InstanceOf* x) { /* nothing to do */ }; | |
147 void do_BlockBegin (BlockBegin* x) { /* nothing to do */ }; | |
148 void do_Goto (Goto* x) { /* nothing to do */ }; | |
149 void do_If (If* x) { /* nothing to do */ }; | |
150 void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ }; | |
151 void do_TableSwitch (TableSwitch* x) { /* nothing to do */ }; | |
152 void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ }; | |
153 void do_Return (Return* x) { /* nothing to do */ }; | |
154 void do_Throw (Throw* x) { /* nothing to do */ }; | |
155 void do_Base (Base* x) { /* nothing to do */ }; | |
156 void do_OsrEntry (OsrEntry* x) { /* nothing to do */ }; | |
157 void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }; | |
158 void do_RoundFP (RoundFP* x) { /* nothing to do */ }; | |
159 void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ }; | |
160 void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }; | |
161 void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { /* nothing to do */ }; | |
162 void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ }; | |
163 void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }; | |
164 void do_ProfileCall (ProfileCall* x) { /* nothing to do */ }; | |
12882
ce0cc25bc5e2
8026054: New type profiling points: type of return values at calls
roland
parents:
12875
diff
changeset
|
165 void do_ProfileReturnType (ProfileReturnType* x) { /* nothing to do */ }; |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
9156
diff
changeset
|
166 void do_ProfileInvoke (ProfileInvoke* x) { /* nothing to do */ }; |
8860 | 167 void do_RuntimeCall (RuntimeCall* x) { /* nothing to do */ }; |
168 void do_MemBar (MemBar* x) { /* nothing to do */ }; | |
169 void do_RangeCheckPredicate(RangeCheckPredicate* x) { /* nothing to do */ }; | |
9156
acadb114c818
8011648: C1: optimized build is broken after 7153771
roland
parents:
8860
diff
changeset
|
170 #ifdef ASSERT |
8860 | 171 void do_Assert (Assert* x) { /* nothing to do */ }; |
9156
acadb114c818
8011648: C1: optimized build is broken after 7153771
roland
parents:
8860
diff
changeset
|
172 #endif |
8860 | 173 }; |
174 | |
175 #ifdef ASSERT | |
176 void add_assertions(Bound *bound, Instruction *instruction, Instruction *position); | |
177 #endif | |
178 | |
179 define_array(BoundArray, Bound *) | |
180 define_stack(BoundStack, BoundArray) | |
181 define_array(BoundMap, BoundStack *) | |
182 define_array(AccessIndexedArray, AccessIndexed *) | |
183 define_stack(AccessIndexedList, AccessIndexedArray) | |
184 define_array(InstructionArray, Instruction *) | |
185 define_stack(InstructionList, InstructionArray) | |
186 | |
187 class AccessIndexedInfo : public CompilationResourceObj { | |
188 public: | |
189 AccessIndexedList *_list; | |
190 int _min; | |
191 int _max; | |
192 }; | |
193 | |
194 define_array(AccessIndexedInfoArray, AccessIndexedInfo *) | |
195 BoundMap _bounds; // Mapping from Instruction's id to current bound | |
196 AccessIndexedInfoArray _access_indexed_info; // Mapping from Instruction's id to AccessIndexedInfo for in block motion | |
197 Visitor _visitor; | |
198 | |
199 public: | |
200 RangeCheckEliminator(IR *ir); | |
201 | |
202 IR *ir() const { return _ir; } | |
203 | |
204 // Pass over the dominator tree to identify blocks where there's an oppportunity for optimization | |
205 bool set_process_block_flags(BlockBegin *block); | |
206 // The core of the optimization work: pass over the dominator tree | |
207 // to propagate bound information, insert predicate out of loops, | |
208 // eliminate bound checks when possible and perform in block motion | |
209 void calc_bounds(BlockBegin *block, BlockBegin *loop_header); | |
210 // reorder bound checks within a block in order to eliminate some of them | |
211 void in_block_motion(BlockBegin *block, AccessIndexedList &accessIndexed, InstructionList &arrays); | |
212 | |
213 // update/access current bound | |
214 void update_bound(IntegerStack &pushed, Value v, Instruction::Condition cond, Value value, int constant); | |
215 void update_bound(IntegerStack &pushed, Value v, Bound *bound); | |
216 Bound *get_bound(Value v); | |
217 | |
218 bool loop_invariant(BlockBegin *loop_header, Instruction *instruction); // check for loop invariance | |
219 void add_access_indexed_info(InstructionList &indices, int i, Value instruction, AccessIndexed *ai); // record indexed access for in block motion | |
220 void remove_range_check(AccessIndexed *ai); // Mark this instructions as not needing a range check | |
221 void add_if_condition(IntegerStack &pushed, Value x, Value y, Instruction::Condition condition); // Update bound for an If | |
222 bool in_array_bound(Bound *bound, Value array); // Check whether bound is known to fall within array | |
223 | |
224 // helper functions to work with predicates | |
225 Instruction* insert_after(Instruction* insert_position, Instruction* instr, int bci); | |
226 Instruction* predicate(Instruction* left, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci=-1); | |
227 Instruction* predicate_cmp_with_const(Instruction* instr, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci=1); | |
228 Instruction* predicate_add(Instruction* left, int left_const, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci=-1); | |
229 Instruction* predicate_add_cmp_with_const(Instruction* left, int left_const, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci=-1); | |
230 | |
231 void insert_deoptimization(ValueStack *state, Instruction *insert_position, Instruction *array_instr, // Add predicate | |
232 Instruction *length_instruction, Instruction *lower_instr, int lower, | |
233 Instruction *upper_instr, int upper, AccessIndexed *ai); | |
234 bool is_ok_for_deoptimization(Instruction *insert_position, Instruction *array_instr, // Can we safely add a predicate? | |
235 Instruction *length_instr, Instruction *lower_instr, | |
236 int lower, Instruction *upper_instr, int upper); | |
237 void process_if(IntegerStack &pushed, BlockBegin *block, If *cond); // process If Instruction | |
238 void process_access_indexed(BlockBegin *loop_header, BlockBegin *block, AccessIndexed *ai); // process indexed access | |
239 | |
240 void dump_condition_stack(BlockBegin *cur_block); | |
241 static void print_statistics(); | |
242 }; | |
243 | |
244 #endif // SHARE_VM_C1_C1_RANGECHECKELIMINATION_HPP |