Mercurial > hg > truffle
annotate src/share/vm/oops/generateOopMap.hpp @ 4181:319860ae697a
Simplify FrameMap: make offsets of spill slots and outgoing parameters independent so that they can be allocated at the same time, eliminating the separate phases. This makes the separate StackBlock unnecesary. Change CiStackSlot to use byte offsets instead of spill slot index. This makes CiTarget.spillSlotSize unnecessary.
author | Christian Wimmer <Christian.Wimmer@Oracle.com> |
---|---|
date | Mon, 02 Jan 2012 14:16:08 -0800 |
parents | 1d1603768966 |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
2426
1d1603768966
7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents:
2177
diff
changeset
|
2 * Copyright (c) 1997, 2011, 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:
605
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
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:
605
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_OOPS_GENERATEOOPMAP_HPP |
26 #define SHARE_VM_OOPS_GENERATEOOPMAP_HPP | |
27 | |
28 #include "interpreter/bytecodeStream.hpp" | |
29 #include "memory/allocation.inline.hpp" | |
30 #include "memory/universe.inline.hpp" | |
31 #include "oops/methodOop.hpp" | |
32 #include "oops/oopsHierarchy.hpp" | |
33 #include "runtime/signature.hpp" | |
34 | |
0 | 35 // Forward definition |
36 class MethodOopMap; | |
37 class GenerateOopMap; | |
38 class BasicBlock; | |
39 class CellTypeState; | |
40 class StackMap; | |
41 | |
42 // These two should be removed. But requires som code to be cleaned up | |
43 #define MAXARGSIZE 256 // This should be enough | |
44 #define MAX_LOCAL_VARS 65536 // 16-bit entry | |
45 | |
46 typedef void (*jmpFct_t)(GenerateOopMap *c, int bcpDelta, int* data); | |
47 | |
48 | |
49 // RetTable | |
50 // | |
51 // Contains maping between jsr targets and there return addresses. One-to-many mapping | |
52 // | |
53 class RetTableEntry : public ResourceObj { | |
54 private: | |
55 static int _init_nof_jsrs; // Default size of jsrs list | |
56 int _target_bci; // Target PC address of jump (bytecode index) | |
57 GrowableArray<intptr_t> * _jsrs; // List of return addresses (bytecode index) | |
58 RetTableEntry *_next; // Link to next entry | |
59 public: | |
60 RetTableEntry(int target, RetTableEntry *next) { _target_bci=target; _jsrs = new GrowableArray<intptr_t>(_init_nof_jsrs); _next = next; } | |
61 | |
62 // Query | |
63 int target_bci() const { return _target_bci; } | |
64 int nof_jsrs() const { return _jsrs->length(); } | |
65 int jsrs(int i) const { assert(i>=0 && i<nof_jsrs(), "Index out of bounds"); return _jsrs->at(i); } | |
66 | |
67 // Update entry | |
68 void add_jsr (int return_bci) { _jsrs->append(return_bci); } | |
69 void add_delta (int bci, int delta); | |
70 RetTableEntry * next() const { return _next; } | |
71 }; | |
72 | |
73 | |
74 class RetTable VALUE_OBJ_CLASS_SPEC { | |
75 private: | |
76 RetTableEntry *_first; | |
77 static int _init_nof_entries; | |
78 | |
79 void add_jsr(int return_bci, int target_bci); // Adds entry to list | |
80 public: | |
81 RetTable() { _first = NULL; } | |
82 void compute_ret_table(methodHandle method); | |
83 void update_ret_table(int bci, int delta); | |
84 RetTableEntry* find_jsrs_for_target(int targBci); | |
85 }; | |
86 | |
87 // | |
88 // CellTypeState | |
89 // | |
90 class CellTypeState VALUE_OBJ_CLASS_SPEC { | |
91 private: | |
92 unsigned int _state; | |
93 | |
94 // Masks for separating the BITS and INFO portions of a CellTypeState | |
95 enum { info_mask = right_n_bits(28), | |
96 bits_mask = (int)(~info_mask) }; | |
97 | |
98 // These constant are used for manipulating the BITS portion of a | |
99 // CellTypeState | |
100 enum { uninit_bit = (int)(nth_bit(31)), | |
101 ref_bit = nth_bit(30), | |
102 val_bit = nth_bit(29), | |
103 addr_bit = nth_bit(28), | |
104 live_bits_mask = (int)(bits_mask & ~uninit_bit) }; | |
105 | |
106 // These constants are used for manipulating the INFO portion of a | |
107 // CellTypeState | |
108 enum { top_info_bit = nth_bit(27), | |
109 not_bottom_info_bit = nth_bit(26), | |
110 info_data_mask = right_n_bits(26), | |
111 info_conflict = info_mask }; | |
112 | |
113 // Within the INFO data, these values are used to distinguish different | |
114 // kinds of references. | |
115 enum { ref_not_lock_bit = nth_bit(25), // 0 if this reference is locked as a monitor | |
116 ref_slot_bit = nth_bit(24), // 1 if this reference is a "slot" reference, | |
117 // 0 if it is a "line" reference. | |
118 ref_data_mask = right_n_bits(24) }; | |
119 | |
120 | |
121 // These values are used to initialize commonly used CellTypeState | |
122 // constants. | |
123 enum { bottom_value = 0, | |
124 uninit_value = (int)(uninit_bit | info_conflict), | |
125 ref_value = ref_bit, | |
126 ref_conflict = ref_bit | info_conflict, | |
127 val_value = val_bit | info_conflict, | |
128 addr_value = addr_bit, | |
129 addr_conflict = addr_bit | info_conflict }; | |
130 | |
131 public: | |
132 | |
133 // Since some C++ constructors generate poor code for declarations of the | |
134 // form... | |
135 // | |
136 // CellTypeState vector[length]; | |
137 // | |
138 // ...we avoid making a constructor for this class. CellTypeState values | |
139 // should be constructed using one of the make_* methods: | |
140 | |
141 static CellTypeState make_any(int state) { | |
142 CellTypeState s; | |
143 s._state = state; | |
144 // Causes SS10 warning. | |
145 // assert(s.is_valid_state(), "check to see if CellTypeState is valid"); | |
146 return s; | |
147 } | |
148 | |
149 static CellTypeState make_bottom() { | |
150 return make_any(0); | |
151 } | |
152 | |
153 static CellTypeState make_top() { | |
154 return make_any(AllBits); | |
155 } | |
156 | |
157 static CellTypeState make_addr(int bci) { | |
158 assert((bci >= 0) && (bci < info_data_mask), "check to see if ret addr is valid"); | |
159 return make_any(addr_bit | not_bottom_info_bit | (bci & info_data_mask)); | |
160 } | |
161 | |
162 static CellTypeState make_slot_ref(int slot_num) { | |
163 assert(slot_num >= 0 && slot_num < ref_data_mask, "slot out of range"); | |
164 return make_any(ref_bit | not_bottom_info_bit | ref_not_lock_bit | ref_slot_bit | | |
165 (slot_num & ref_data_mask)); | |
166 } | |
167 | |
168 static CellTypeState make_line_ref(int bci) { | |
169 assert(bci >= 0 && bci < ref_data_mask, "line out of range"); | |
170 return make_any(ref_bit | not_bottom_info_bit | ref_not_lock_bit | | |
171 (bci & ref_data_mask)); | |
172 } | |
173 | |
174 static CellTypeState make_lock_ref(int bci) { | |
175 assert(bci >= 0 && bci < ref_data_mask, "line out of range"); | |
176 return make_any(ref_bit | not_bottom_info_bit | (bci & ref_data_mask)); | |
177 } | |
178 | |
179 // Query methods: | |
180 bool is_bottom() const { return _state == 0; } | |
181 bool is_live() const { return ((_state & live_bits_mask) != 0); } | |
182 bool is_valid_state() const { | |
183 // Uninitialized and value cells must contain no data in their info field: | |
184 if ((can_be_uninit() || can_be_value()) && !is_info_top()) { | |
185 return false; | |
186 } | |
187 // The top bit is only set when all info bits are set: | |
188 if (is_info_top() && ((_state & info_mask) != info_mask)) { | |
189 return false; | |
190 } | |
191 // The not_bottom_bit must be set when any other info bit is set: | |
192 if (is_info_bottom() && ((_state & info_mask) != 0)) { | |
193 return false; | |
194 } | |
195 return true; | |
196 } | |
197 | |
198 bool is_address() const { return ((_state & bits_mask) == addr_bit); } | |
199 bool is_reference() const { return ((_state & bits_mask) == ref_bit); } | |
200 bool is_value() const { return ((_state & bits_mask) == val_bit); } | |
201 bool is_uninit() const { return ((_state & bits_mask) == (uint)uninit_bit); } | |
202 | |
203 bool can_be_address() const { return ((_state & addr_bit) != 0); } | |
204 bool can_be_reference() const { return ((_state & ref_bit) != 0); } | |
205 bool can_be_value() const { return ((_state & val_bit) != 0); } | |
206 bool can_be_uninit() const { return ((_state & uninit_bit) != 0); } | |
207 | |
208 bool is_info_bottom() const { return ((_state & not_bottom_info_bit) == 0); } | |
209 bool is_info_top() const { return ((_state & top_info_bit) != 0); } | |
210 int get_info() const { | |
211 assert((!is_info_top() && !is_info_bottom()), | |
212 "check to make sure top/bottom info is not used"); | |
213 return (_state & info_data_mask); | |
214 } | |
215 | |
216 bool is_good_address() const { return is_address() && !is_info_top(); } | |
217 bool is_lock_reference() const { | |
218 return ((_state & (bits_mask | top_info_bit | ref_not_lock_bit)) == ref_bit); | |
219 } | |
220 bool is_nonlock_reference() const { | |
221 return ((_state & (bits_mask | top_info_bit | ref_not_lock_bit)) == (ref_bit | ref_not_lock_bit)); | |
222 } | |
223 | |
224 bool equal(CellTypeState a) const { return _state == a._state; } | |
225 bool equal_kind(CellTypeState a) const { | |
226 return (_state & bits_mask) == (a._state & bits_mask); | |
227 } | |
228 | |
229 char to_char() const; | |
230 | |
231 // Merge | |
232 CellTypeState merge (CellTypeState cts, int slot) const; | |
233 | |
234 // Debugging output | |
235 void print(outputStream *os); | |
236 | |
237 // Default values of common values | |
238 static CellTypeState bottom; | |
239 static CellTypeState uninit; | |
240 static CellTypeState ref; | |
241 static CellTypeState value; | |
242 static CellTypeState refUninit; | |
243 static CellTypeState varUninit; | |
244 static CellTypeState top; | |
245 static CellTypeState addr; | |
246 }; | |
247 | |
248 | |
249 // | |
250 // BasicBlockStruct | |
251 // | |
252 class BasicBlock: ResourceObj { | |
253 private: | |
254 bool _changed; // Reached a fixpoint or not | |
255 public: | |
256 enum Constants { | |
257 _dead_basic_block = -2, | |
258 _unreached = -1 // Alive but not yet reached by analysis | |
259 // >=0 // Alive and has a merged state | |
260 }; | |
261 | |
262 int _bci; // Start of basic block | |
263 int _end_bci; // Bci of last instruction in basicblock | |
264 int _max_locals; // Determines split between vars and stack | |
265 int _max_stack; // Determines split between stack and monitors | |
266 CellTypeState* _state; // State (vars, stack) at entry. | |
267 int _stack_top; // -1 indicates bottom stack value. | |
268 int _monitor_top; // -1 indicates bottom monitor stack value. | |
269 | |
270 CellTypeState* vars() { return _state; } | |
271 CellTypeState* stack() { return _state + _max_locals; } | |
272 | |
273 bool changed() { return _changed; } | |
274 void set_changed(bool s) { _changed = s; } | |
275 | |
276 bool is_reachable() const { return _stack_top >= 0; } // Analysis has reached this basicblock | |
277 | |
278 // All basicblocks that are unreachable are going to have a _stack_top == _dead_basic_block. | |
279 // This info. is setup in a pre-parse before the real abstract interpretation starts. | |
280 bool is_dead() const { return _stack_top == _dead_basic_block; } | |
281 bool is_alive() const { return _stack_top != _dead_basic_block; } | |
282 void mark_as_alive() { assert(is_dead(), "must be dead"); _stack_top = _unreached; } | |
283 }; | |
284 | |
285 | |
286 // | |
287 // GenerateOopMap | |
288 // | |
289 // Main class used to compute the pointer-maps in a MethodOop | |
290 // | |
291 class GenerateOopMap VALUE_OBJ_CLASS_SPEC { | |
292 protected: | |
293 | |
294 // _monitor_top is set to this constant to indicate that a monitor matching | |
295 // problem was encountered prior to this point in control flow. | |
296 enum { bad_monitors = -1 }; | |
297 | |
298 // Main variables | |
299 methodHandle _method; // The method we are examine | |
300 RetTable _rt; // Contains the return address mappings | |
301 int _max_locals; // Cached value of no. of locals | |
302 int _max_stack; // Cached value of max. stack depth | |
303 int _max_monitors; // Cached value of max. monitor stack depth | |
304 int _has_exceptions; // True, if exceptions exist for method | |
605 | 305 bool _got_error; // True, if an error occurred during interpretation. |
0 | 306 Handle _exception; // Exception if got_error is true. |
307 bool _did_rewriting; // was bytecodes rewritten | |
308 bool _did_relocation; // was relocation neccessary | |
309 bool _monitor_safe; // The monitors in this method have been determined | |
310 // to be safe. | |
311 | |
312 // Working Cell type state | |
313 int _state_len; // Size of states | |
314 CellTypeState *_state; // list of states | |
315 char *_state_vec_buf; // Buffer used to print a readable version of a state | |
316 int _stack_top; | |
317 int _monitor_top; | |
318 | |
319 // Timing and statistics | |
320 static elapsedTimer _total_oopmap_time; // Holds cumulative oopmap generation time | |
321 static long _total_byte_count; // Holds cumulative number of bytes inspected | |
322 | |
323 // Cell type methods | |
324 void init_state(); | |
325 void make_context_uninitialized (); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
326 int methodsig_to_effect (Symbol* signature, bool isStatic, CellTypeState* effect); |
0 | 327 bool merge_local_state_vectors (CellTypeState* cts, CellTypeState* bbts); |
328 bool merge_monitor_state_vectors(CellTypeState* cts, CellTypeState* bbts); | |
329 void copy_state (CellTypeState *dst, CellTypeState *src); | |
330 void merge_state_into_bb (BasicBlock *bb); | |
331 static void merge_state (GenerateOopMap *gom, int bcidelta, int* data); | |
332 void set_var (int localNo, CellTypeState cts); | |
333 CellTypeState get_var (int localNo); | |
334 CellTypeState pop (); | |
335 void push (CellTypeState cts); | |
336 CellTypeState monitor_pop (); | |
337 void monitor_push (CellTypeState cts); | |
338 CellTypeState * vars () { return _state; } | |
339 CellTypeState * stack () { return _state+_max_locals; } | |
340 CellTypeState * monitors () { return _state+_max_locals+_max_stack; } | |
341 | |
342 void replace_all_CTS_matches (CellTypeState match, | |
343 CellTypeState replace); | |
344 void print_states (outputStream *os, CellTypeState *vector, int num); | |
345 void print_current_state (outputStream *os, | |
346 BytecodeStream *itr, | |
347 bool detailed); | |
348 void report_monitor_mismatch (const char *msg); | |
349 | |
350 // Basicblock info | |
351 BasicBlock * _basic_blocks; // Array of basicblock info | |
352 int _gc_points; | |
353 int _bb_count; | |
342 | 354 BitMap _bb_hdr_bits; |
0 | 355 |
356 // Basicblocks methods | |
357 void initialize_bb (); | |
358 void mark_bbheaders_and_count_gc_points(); | |
342 | 359 bool is_bb_header (int bci) const { |
360 return _bb_hdr_bits.at(bci); | |
361 } | |
0 | 362 int gc_points () const { return _gc_points; } |
363 int bb_count () const { return _bb_count; } | |
342 | 364 void set_bbmark_bit (int bci) { |
365 _bb_hdr_bits.at_put(bci, true); | |
366 } | |
367 void clear_bbmark_bit (int bci) { | |
368 _bb_hdr_bits.at_put(bci, false); | |
369 } | |
0 | 370 BasicBlock * get_basic_block_at (int bci) const; |
371 BasicBlock * get_basic_block_containing (int bci) const; | |
372 void interp_bb (BasicBlock *bb); | |
373 void restore_state (BasicBlock *bb); | |
374 int next_bb_start_pc (BasicBlock *bb); | |
375 void update_basic_blocks (int bci, int delta, int new_method_size); | |
376 static void bb_mark_fct (GenerateOopMap *c, int deltaBci, int *data); | |
377 | |
378 // Dead code detection | |
379 void mark_reachable_code(); | |
380 static void reachable_basicblock (GenerateOopMap *c, int deltaBci, int *data); | |
381 | |
382 // Interpretation methods (primary) | |
383 void do_interpretation (); | |
384 void init_basic_blocks (); | |
385 void setup_method_entry_state (); | |
386 void interp_all (); | |
387 | |
388 // Interpretation methods (secondary) | |
389 void interp1 (BytecodeStream *itr); | |
390 void do_exception_edge (BytecodeStream *itr); | |
391 void check_type (CellTypeState expected, CellTypeState actual); | |
392 void ppstore (CellTypeState *in, int loc_no); | |
393 void ppload (CellTypeState *out, int loc_no); | |
394 void ppush1 (CellTypeState in); | |
395 void ppush (CellTypeState *in); | |
396 void ppop1 (CellTypeState out); | |
397 void ppop (CellTypeState *out); | |
398 void ppop_any (int poplen); | |
399 void pp (CellTypeState *in, CellTypeState *out); | |
400 void pp_new_ref (CellTypeState *in, int bci); | |
401 void ppdupswap (int poplen, const char *out); | |
1910
d1896d1dda3e
6981788: GC map generator sometimes picks up the wrong kind of instruction operand
jrose
parents:
1552
diff
changeset
|
402 void do_ldc (int bci); |
0 | 403 void do_astore (int idx); |
404 void do_jsr (int delta); | |
405 void do_field (int is_get, int is_static, int idx, int bci); | |
406 void do_method (int is_static, int is_interface, int idx, int bci); | |
407 void do_multianewarray (int dims, int bci); | |
408 void do_monitorenter (int bci); | |
409 void do_monitorexit (int bci); | |
410 void do_return_monitor_check (); | |
411 void do_checkcast (); | |
412 CellTypeState *sigchar_to_effect (char sigch, int bci, CellTypeState *out); | |
413 int copy_cts (CellTypeState *dst, CellTypeState *src); | |
414 | |
415 // Error handling | |
416 void error_work (const char *format, va_list ap); | |
417 void report_error (const char *format, ...); | |
418 void verify_error (const char *format, ...); | |
419 bool got_error() { return _got_error; } | |
420 | |
421 // Create result set | |
422 bool _report_result; | |
423 bool _report_result_for_send; // Unfortunatly, stackmaps for sends are special, so we need some extra | |
424 BytecodeStream *_itr_send; // variables to handle them properly. | |
425 | |
426 void report_result (); | |
427 | |
428 // Initvars | |
429 GrowableArray<intptr_t> * _init_vars; | |
430 | |
431 void initialize_vars (); | |
432 void add_to_ref_init_set (int localNo); | |
433 | |
434 // Conflicts rewrite logic | |
605 | 435 bool _conflict; // True, if a conflict occurred during interpretation |
0 | 436 int _nof_refval_conflicts; // No. of conflicts that require rewrites |
437 int * _new_var_map; | |
438 | |
439 void record_refval_conflict (int varNo); | |
440 void rewrite_refval_conflicts (); | |
441 void rewrite_refval_conflict (int from, int to); | |
442 bool rewrite_refval_conflict_inst (BytecodeStream *i, int from, int to); | |
443 bool rewrite_load_or_store (BytecodeStream *i, Bytecodes::Code bc, Bytecodes::Code bc0, unsigned int varNo); | |
444 | |
445 void expand_current_instr (int bci, int ilen, int newIlen, u_char inst_buffer[]); | |
446 bool is_astore (BytecodeStream *itr, int *index); | |
447 bool is_aload (BytecodeStream *itr, int *index); | |
448 | |
449 // List of bci's where a return address is on top of the stack | |
450 GrowableArray<intptr_t> *_ret_adr_tos; | |
451 | |
452 bool stack_top_holds_ret_addr (int bci); | |
453 void compute_ret_adr_at_TOS (); | |
454 void update_ret_adr_at_TOS (int bci, int delta); | |
455 | |
456 int binsToHold (int no) { return ((no+(BitsPerWord-1))/BitsPerWord); } | |
457 char *state_vec_to_string (CellTypeState* vec, int len); | |
458 | |
459 // Helper method. Can be used in subclasses to fx. calculate gc_points. If the current instuction | |
460 // is a control transfer, then calls the jmpFct all possible destinations. | |
461 void ret_jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int varNo,int *data); | |
462 bool jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int *data); | |
463 | |
464 friend class RelocCallback; | |
465 public: | |
466 GenerateOopMap(methodHandle method); | |
467 | |
468 // Compute the map. | |
469 void compute_map(TRAPS); | |
470 void result_for_basicblock(int bci); // Do a callback on fill_stackmap_for_opcodes for basicblock containing bci | |
471 | |
472 // Query | |
473 int max_locals() const { return _max_locals; } | |
474 methodOop method() const { return _method(); } | |
475 methodHandle method_as_handle() const { return _method; } | |
476 | |
477 bool did_rewriting() { return _did_rewriting; } | |
478 bool did_relocation() { return _did_relocation; } | |
479 | |
480 static void print_time(); | |
481 | |
482 // Monitor query | |
483 bool monitor_safe() { return _monitor_safe; } | |
484 | |
485 // Specialization methods. Intended use: | |
486 // - possible_gc_point must return true for every bci for which the stackmaps must be returned | |
487 // - fill_stackmap_prolog is called just before the result is reported. The arguments tells the estimated | |
488 // number of gc points | |
489 // - fill_stackmap_for_opcodes is called once for each bytecode index in order (0...code_length-1) | |
490 // - fill_stackmap_epilog is called after all results has been reported. Note: Since the algorithm does not report | |
491 // stackmaps for deadcode, fewer gc_points might have been encounted than assumed during the epilog. It is the | |
492 // responsibility of the subclass to count the correct number. | |
493 // - fill_init_vars are called once with the result of the init_vars computation | |
494 // | |
495 // All these methods are used during a call to: compute_map. Note: Non of the return results are valid | |
496 // after compute_map returns, since all values are allocated as resource objects. | |
497 // | |
498 // All virtual method must be implemented in subclasses | |
499 virtual bool allow_rewrites () const { return false; } | |
500 virtual bool report_results () const { return true; } | |
501 virtual bool report_init_vars () const { return true; } | |
502 virtual bool possible_gc_point (BytecodeStream *bcs) { ShouldNotReachHere(); return false; } | |
503 virtual void fill_stackmap_prolog (int nof_gc_points) { ShouldNotReachHere(); } | |
504 virtual void fill_stackmap_epilog () { ShouldNotReachHere(); } | |
505 virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, | |
506 CellTypeState* vars, | |
507 CellTypeState* stack, | |
508 int stackTop) { ShouldNotReachHere(); } | |
509 virtual void fill_init_vars (GrowableArray<intptr_t> *init_vars) { ShouldNotReachHere();; } | |
510 }; | |
511 | |
512 // | |
513 // Subclass of the GenerateOopMap Class that just do rewrites of the method, if needed. | |
514 // It does not store any oopmaps. | |
515 // | |
516 class ResolveOopMapConflicts: public GenerateOopMap { | |
517 private: | |
518 | |
519 bool _must_clear_locals; | |
520 | |
521 virtual bool report_results() const { return false; } | |
522 virtual bool report_init_vars() const { return true; } | |
523 virtual bool allow_rewrites() const { return true; } | |
524 virtual bool possible_gc_point (BytecodeStream *bcs) { return false; } | |
525 virtual void fill_stackmap_prolog (int nof_gc_points) {} | |
526 virtual void fill_stackmap_epilog () {} | |
527 virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, | |
528 CellTypeState* vars, | |
529 CellTypeState* stack, | |
530 int stack_top) {} | |
531 virtual void fill_init_vars (GrowableArray<intptr_t> *init_vars) { _must_clear_locals = init_vars->length() > 0; } | |
532 | |
533 #ifndef PRODUCT | |
534 // Statistics | |
535 static int _nof_invocations; | |
536 static int _nof_rewrites; | |
537 static int _nof_relocations; | |
538 #endif | |
539 | |
540 public: | |
541 ResolveOopMapConflicts(methodHandle method) : GenerateOopMap(method) { _must_clear_locals = false; }; | |
542 | |
543 methodHandle do_potential_rewrite(TRAPS); | |
544 bool must_clear_locals() const { return _must_clear_locals; } | |
545 }; | |
546 | |
547 | |
548 // | |
549 // Subclass used by the compiler to generate pairing infomation | |
550 // | |
551 class GeneratePairingInfo: public GenerateOopMap { | |
552 private: | |
553 | |
554 virtual bool report_results() const { return false; } | |
555 virtual bool report_init_vars() const { return false; } | |
556 virtual bool allow_rewrites() const { return false; } | |
557 virtual bool possible_gc_point (BytecodeStream *bcs) { return false; } | |
558 virtual void fill_stackmap_prolog (int nof_gc_points) {} | |
559 virtual void fill_stackmap_epilog () {} | |
560 virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, | |
561 CellTypeState* vars, | |
562 CellTypeState* stack, | |
563 int stack_top) {} | |
564 virtual void fill_init_vars (GrowableArray<intptr_t> *init_vars) {} | |
565 public: | |
566 GeneratePairingInfo(methodHandle method) : GenerateOopMap(method) {}; | |
567 | |
568 // Call compute_map(CHECK) to generate info. | |
569 }; | |
1972 | 570 |
571 #endif // SHARE_VM_OOPS_GENERATEOOPMAP_HPP |