Mercurial > hg > truffle
annotate src/share/vm/c1/c1_GraphBuilder.hpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | b812ff5abc73 |
children | d5d065957597 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
470
diff
changeset
|
2 * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
470
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
470
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:
470
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 class MemoryBuffer; | |
26 | |
27 class GraphBuilder VALUE_OBJ_CLASS_SPEC { | |
28 private: | |
29 // Per-scope data. These are pushed and popped as we descend into | |
30 // inlined methods. Currently in order to generate good code in the | |
31 // inliner we have to attempt to inline methods directly into the | |
32 // basic block we are parsing; this adds complexity. | |
33 class ScopeData: public CompilationResourceObj { | |
34 private: | |
35 ScopeData* _parent; | |
36 // bci-to-block mapping | |
37 BlockList* _bci2block; | |
38 // Scope | |
39 IRScope* _scope; | |
40 // Whether this scope or any parent scope has exception handlers | |
41 bool _has_handler; | |
42 // The bytecodes | |
43 ciBytecodeStream* _stream; | |
44 | |
45 // Work list | |
46 BlockList* _work_list; | |
47 | |
48 // Maximum inline size for this scope | |
49 intx _max_inline_size; | |
50 // Expression stack depth at point where inline occurred | |
51 int _caller_stack_size; | |
52 | |
53 // The continuation point for the inline. Currently only used in | |
54 // multi-block inlines, but eventually would like to use this for | |
55 // all inlines for uniformity and simplicity; in this case would | |
56 // get the continuation point from the BlockList instead of | |
57 // fabricating it anew because Invokes would be considered to be | |
58 // BlockEnds. | |
59 BlockBegin* _continuation; | |
60 | |
61 // Without return value of inlined method on stack | |
62 ValueStack* _continuation_state; | |
63 | |
64 // Was this ScopeData created only for the parsing and inlining of | |
65 // a jsr? | |
66 bool _parsing_jsr; | |
67 // We track the destination bci of the jsr only to determine | |
68 // bailout conditions, since we only handle a subset of all of the | |
69 // possible jsr-ret control structures. Recursive invocations of a | |
70 // jsr are disallowed by the verifier. | |
71 int _jsr_entry_bci; | |
72 // We need to track the local variable in which the return address | |
73 // was stored to ensure we can handle inlining the jsr, because we | |
74 // don't handle arbitrary jsr/ret constructs. | |
75 int _jsr_ret_addr_local; | |
76 // If we are parsing a jsr, the continuation point for rets | |
77 BlockBegin* _jsr_continuation; | |
78 // Cloned XHandlers for jsr-related ScopeDatas | |
79 XHandlers* _jsr_xhandlers; | |
80 | |
81 // Number of returns seen in this scope | |
82 int _num_returns; | |
83 | |
84 // In order to generate profitable code for inlining, we currently | |
85 // have to perform an optimization for single-block inlined | |
86 // methods where we continue parsing into the same block. This | |
87 // allows us to perform CSE across inlined scopes and to avoid | |
88 // storing parameters to the stack. Having a global register | |
89 // allocator and being able to perform global CSE would allow this | |
90 // code to be removed and thereby simplify the inliner. | |
91 BlockBegin* _cleanup_block; // The block to which the return was added | |
92 Instruction* _cleanup_return_prev; // Instruction before return instruction | |
93 ValueStack* _cleanup_state; // State of that block (not yet pinned) | |
94 | |
95 public: | |
96 ScopeData(ScopeData* parent); | |
97 | |
98 ScopeData* parent() const { return _parent; } | |
99 | |
100 BlockList* bci2block() const { return _bci2block; } | |
101 void set_bci2block(BlockList* bci2block) { _bci2block = bci2block; } | |
102 | |
103 // NOTE: this has a different effect when parsing jsrs | |
104 BlockBegin* block_at(int bci); | |
105 | |
106 IRScope* scope() const { return _scope; } | |
107 // Has side-effect of setting has_handler flag | |
108 void set_scope(IRScope* scope); | |
109 | |
110 // Whether this or any parent scope has exception handlers | |
111 bool has_handler() const { return _has_handler; } | |
112 void set_has_handler() { _has_handler = true; } | |
113 | |
114 // Exception handlers list to be used for this scope | |
115 XHandlers* xhandlers() const; | |
116 | |
117 // How to get a block to be parsed | |
118 void add_to_work_list(BlockBegin* block); | |
119 // How to remove the next block to be parsed; returns NULL if none left | |
120 BlockBegin* remove_from_work_list(); | |
121 // Indicates parse is over | |
122 bool is_work_list_empty() const; | |
123 | |
124 ciBytecodeStream* stream() { return _stream; } | |
125 void set_stream(ciBytecodeStream* stream) { _stream = stream; } | |
126 | |
127 intx max_inline_size() const { return _max_inline_size; } | |
128 int caller_stack_size() const; | |
129 | |
130 BlockBegin* continuation() const { return _continuation; } | |
131 void set_continuation(BlockBegin* cont) { _continuation = cont; } | |
132 | |
133 ValueStack* continuation_state() const { return _continuation_state; } | |
134 void set_continuation_state(ValueStack* s) { _continuation_state = s; } | |
135 | |
136 // Indicates whether this ScopeData was pushed only for the | |
137 // parsing and inlining of a jsr | |
138 bool parsing_jsr() const { return _parsing_jsr; } | |
139 void set_parsing_jsr() { _parsing_jsr = true; } | |
140 int jsr_entry_bci() const { return _jsr_entry_bci; } | |
141 void set_jsr_entry_bci(int bci) { _jsr_entry_bci = bci; } | |
142 void set_jsr_return_address_local(int local_no){ _jsr_ret_addr_local = local_no; } | |
143 int jsr_return_address_local() const { return _jsr_ret_addr_local; } | |
144 // Must be called after scope is set up for jsr ScopeData | |
145 void setup_jsr_xhandlers(); | |
146 | |
147 // The jsr continuation is only used when parsing_jsr is true, and | |
148 // is different from the "normal" continuation since we can end up | |
149 // doing a return (rather than a ret) from within a subroutine | |
150 BlockBegin* jsr_continuation() const { return _jsr_continuation; } | |
151 void set_jsr_continuation(BlockBegin* cont) { _jsr_continuation = cont; } | |
152 | |
153 int num_returns(); | |
154 void incr_num_returns(); | |
155 | |
156 void set_inline_cleanup_info(BlockBegin* block, | |
157 Instruction* return_prev, | |
158 ValueStack* return_state); | |
159 BlockBegin* inline_cleanup_block() const { return _cleanup_block; } | |
160 Instruction* inline_cleanup_return_prev() const{ return _cleanup_return_prev; } | |
161 ValueStack* inline_cleanup_state() const { return _cleanup_state; } | |
162 }; | |
163 | |
164 // for all GraphBuilders | |
165 static bool _can_trap[Bytecodes::number_of_java_codes]; | |
166 static bool _is_async[Bytecodes::number_of_java_codes]; | |
167 | |
168 // for each instance of GraphBuilder | |
169 ScopeData* _scope_data; // Per-scope data; used for inlining | |
170 Compilation* _compilation; // the current compilation | |
171 ValueMap* _vmap; // the map of values encountered (for CSE) | |
172 MemoryBuffer* _memory; | |
173 const char* _inline_bailout_msg; // non-null if most recent inline attempt failed | |
174 int _instruction_count; // for bailing out in pathological jsr/ret cases | |
175 BlockBegin* _start; // the start block | |
176 BlockBegin* _osr_entry; // the osr entry block block | |
177 ValueStack* _initial_state; // The state for the start block | |
178 | |
179 // for each call to connect_to_end; can also be set by inliner | |
180 BlockBegin* _block; // the current block | |
181 ValueStack* _state; // the current execution state | |
182 ValueStack* _exception_state; // state that will be used by handle_exception | |
183 Instruction* _last; // the last instruction added | |
184 bool _skip_block; // skip processing of the rest of this block | |
185 | |
186 // accessors | |
187 ScopeData* scope_data() const { return _scope_data; } | |
188 Compilation* compilation() const { return _compilation; } | |
189 BlockList* bci2block() const { return scope_data()->bci2block(); } | |
190 ValueMap* vmap() const { assert(UseLocalValueNumbering, "should not access otherwise"); return _vmap; } | |
191 bool has_handler() const { return scope_data()->has_handler(); } | |
192 | |
193 BlockBegin* block() const { return _block; } | |
194 ValueStack* state() const { return _state; } | |
195 void set_state(ValueStack* state) { _state = state; } | |
196 IRScope* scope() const { return scope_data()->scope(); } | |
197 ValueStack* exception_state() const { return _exception_state; } | |
198 void set_exception_state(ValueStack* s) { _exception_state = s; } | |
199 ciMethod* method() const { return scope()->method(); } | |
200 ciBytecodeStream* stream() const { return scope_data()->stream(); } | |
201 Instruction* last() const { return _last; } | |
202 Bytecodes::Code code() const { return stream()->cur_bc(); } | |
203 int bci() const { return stream()->cur_bci(); } | |
204 int next_bci() const { return stream()->next_bci(); } | |
205 | |
206 // unified bailout support | |
207 void bailout(const char* msg) const { compilation()->bailout(msg); } | |
208 bool bailed_out() const { return compilation()->bailed_out(); } | |
209 | |
210 // stack manipulation helpers | |
211 void ipush(Value t) const { state()->ipush(t); } | |
212 void lpush(Value t) const { state()->lpush(t); } | |
213 void fpush(Value t) const { state()->fpush(t); } | |
214 void dpush(Value t) const { state()->dpush(t); } | |
215 void apush(Value t) const { state()->apush(t); } | |
216 void push(ValueType* type, Value t) const { state()-> push(type, t); } | |
217 | |
218 Value ipop() { return state()->ipop(); } | |
219 Value lpop() { return state()->lpop(); } | |
220 Value fpop() { return state()->fpop(); } | |
221 Value dpop() { return state()->dpop(); } | |
222 Value apop() { return state()->apop(); } | |
223 Value pop(ValueType* type) { return state()-> pop(type); } | |
224 | |
225 // instruction helpers | |
226 void load_constant(); | |
227 void load_local(ValueType* type, int index); | |
228 void store_local(ValueType* type, int index); | |
229 void store_local(ValueStack* state, Value value, ValueType* type, int index); | |
230 void load_indexed (BasicType type); | |
231 void store_indexed(BasicType type); | |
232 void stack_op(Bytecodes::Code code); | |
233 void arithmetic_op(ValueType* type, Bytecodes::Code code, ValueStack* lock_stack = NULL); | |
234 void negate_op(ValueType* type); | |
235 void shift_op(ValueType* type, Bytecodes::Code code); | |
236 void logic_op(ValueType* type, Bytecodes::Code code); | |
237 void compare_op(ValueType* type, Bytecodes::Code code); | |
238 void convert(Bytecodes::Code op, BasicType from, BasicType to); | |
239 void increment(); | |
240 void _goto(int from_bci, int to_bci); | |
241 void if_node(Value x, If::Condition cond, Value y, ValueStack* stack_before); | |
242 void if_zero(ValueType* type, If::Condition cond); | |
243 void if_null(ValueType* type, If::Condition cond); | |
244 void if_same(ValueType* type, If::Condition cond); | |
245 void jsr(int dest); | |
246 void ret(int local_index); | |
247 void table_switch(); | |
248 void lookup_switch(); | |
249 void method_return(Value x); | |
250 void call_register_finalizer(); | |
251 void access_field(Bytecodes::Code code); | |
252 void invoke(Bytecodes::Code code); | |
253 void new_instance(int klass_index); | |
254 void new_type_array(); | |
255 void new_object_array(); | |
256 void check_cast(int klass_index); | |
257 void instance_of(int klass_index); | |
258 void monitorenter(Value x, int bci); | |
259 void monitorexit(Value x, int bci); | |
260 void new_multi_array(int dimensions); | |
261 void throw_op(int bci); | |
262 Value round_fp(Value fp_value); | |
263 | |
264 // stack/code manipulation helpers | |
265 Instruction* append_with_bci(Instruction* instr, int bci); | |
266 Instruction* append(Instruction* instr); | |
267 Instruction* append_split(StateSplit* instr); | |
268 | |
269 // other helpers | |
270 static bool is_async(Bytecodes::Code code) { | |
271 assert(0 <= code && code < Bytecodes::number_of_java_codes, "illegal bytecode"); | |
272 return _is_async[code]; | |
273 } | |
274 BlockBegin* block_at(int bci) { return scope_data()->block_at(bci); } | |
275 XHandlers* handle_exception(int bci); | |
276 void connect_to_end(BlockBegin* beg); | |
277 void null_check(Value value); | |
278 void eliminate_redundant_phis(BlockBegin* start); | |
279 BlockEnd* iterate_bytecodes_for_block(int bci); | |
280 void iterate_all_blocks(bool start_in_current_block_for_inlining = false); | |
281 Dependencies* dependency_recorder() const; // = compilation()->dependencies() | |
282 bool direct_compare(ciKlass* k); | |
283 | |
284 void kill_all(); | |
285 | |
286 ValueStack* lock_stack(); | |
287 | |
288 // | |
289 // Inlining support | |
290 // | |
291 | |
292 // accessors | |
293 bool parsing_jsr() const { return scope_data()->parsing_jsr(); } | |
294 BlockBegin* continuation() const { return scope_data()->continuation(); } | |
295 ValueStack* continuation_state() const { return scope_data()->continuation_state(); } | |
296 BlockBegin* jsr_continuation() const { return scope_data()->jsr_continuation(); } | |
297 int caller_stack_size() const { return scope_data()->caller_stack_size(); } | |
298 void set_continuation(BlockBegin* continuation) { scope_data()->set_continuation(continuation); } | |
299 void set_inline_cleanup_info(BlockBegin* block, | |
300 Instruction* return_prev, | |
301 ValueStack* return_state) { scope_data()->set_inline_cleanup_info(block, | |
302 return_prev, | |
303 return_state); } | |
304 BlockBegin* inline_cleanup_block() const { return scope_data()->inline_cleanup_block(); } | |
305 Instruction* inline_cleanup_return_prev() const { return scope_data()->inline_cleanup_return_prev(); } | |
306 ValueStack* inline_cleanup_state() const { return scope_data()->inline_cleanup_state(); } | |
307 void incr_num_returns() { scope_data()->incr_num_returns(); } | |
308 int num_returns() const { return scope_data()->num_returns(); } | |
309 intx max_inline_size() const { return scope_data()->max_inline_size(); } | |
310 int inline_level() const { return scope()->level(); } | |
311 int recursive_inline_level(ciMethod* callee) const; | |
312 | |
313 // inlining of synchronized methods | |
314 void inline_sync_entry(Value lock, BlockBegin* sync_handler); | |
315 void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false); | |
316 | |
317 // inliners | |
318 bool try_inline(ciMethod* callee, bool holder_known); | |
319 bool try_inline_intrinsics(ciMethod* callee); | |
320 bool try_inline_full (ciMethod* callee, bool holder_known); | |
321 bool try_inline_jsr(int jsr_dest_bci); | |
322 | |
323 // helpers | |
324 void inline_bailout(const char* msg); | |
325 BlockBegin* header_block(BlockBegin* entry, BlockBegin::Flag f, ValueStack* state); | |
326 BlockBegin* setup_start_block(int osr_bci, BlockBegin* std_entry, BlockBegin* osr_entry, ValueStack* init_state); | |
327 void setup_osr_entry_block(); | |
328 void clear_inline_bailout(); | |
329 ValueStack* state_at_entry(); | |
330 void push_root_scope(IRScope* scope, BlockList* bci2block, BlockBegin* start); | |
331 void push_scope(ciMethod* callee, BlockBegin* continuation); | |
332 void push_scope_for_jsr(BlockBegin* jsr_continuation, int jsr_dest_bci); | |
333 void pop_scope(); | |
334 void pop_scope_for_jsr(); | |
335 | |
336 bool append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile); | |
337 bool append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile); | |
338 bool append_unsafe_get_raw(ciMethod* callee, BasicType t); | |
339 bool append_unsafe_put_raw(ciMethod* callee, BasicType t); | |
340 bool append_unsafe_prefetch(ciMethod* callee, bool is_store, bool is_static); | |
341 void append_unsafe_CAS(ciMethod* callee); | |
342 | |
343 NOT_PRODUCT(void print_inline_result(ciMethod* callee, bool res);) | |
344 | |
345 // methodDataOop profiling helpers | |
346 void profile_call(Value recv, ciKlass* predicted_holder); | |
347 void profile_invocation(ciMethod* method); | |
348 void profile_bci(int bci); | |
349 | |
350 // Helpers for generation of profile information | |
351 bool profile_branches() { | |
352 return _compilation->env()->comp_level() == CompLevel_fast_compile && | |
353 Tier1UpdateMethodData && Tier1ProfileBranches; | |
354 } | |
355 bool profile_calls() { | |
356 return _compilation->env()->comp_level() == CompLevel_fast_compile && | |
357 Tier1UpdateMethodData && Tier1ProfileCalls; | |
358 } | |
359 bool profile_inlined_calls() { | |
360 return profile_calls() && Tier1ProfileInlinedCalls; | |
361 } | |
362 bool profile_checkcasts() { | |
363 return _compilation->env()->comp_level() == CompLevel_fast_compile && | |
364 Tier1UpdateMethodData && Tier1ProfileCheckcasts; | |
365 } | |
366 | |
367 public: | |
368 NOT_PRODUCT(void print_stats();) | |
369 | |
370 // initialization | |
371 static void initialize(); | |
372 | |
373 // public | |
374 static bool can_trap(ciMethod* method, Bytecodes::Code code) { | |
375 assert(0 <= code && code < Bytecodes::number_of_java_codes, "illegal bytecode"); | |
376 if (_can_trap[code]) return true; | |
377 // special handling for finalizer registration | |
378 return code == Bytecodes::_return && method->intrinsic_id() == vmIntrinsics::_Object_init; | |
379 } | |
380 | |
381 // creation | |
382 GraphBuilder(Compilation* compilation, IRScope* scope); | |
383 static void sort_top_into_worklist(BlockList* worklist, BlockBegin* top); | |
384 | |
385 BlockBegin* start() const { return _start; } | |
386 }; |