Wed, 02 Jul 2008 12:55:16 -0700
6719955: Update copyright year
Summary: Update copyright year for files that have been modified in 2008
Reviewed-by: ohair, tbell
duke@435 | 1 | /* |
xdono@631 | 2 | * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
duke@435 | 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@435 | 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@435 | 21 | * have any questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
duke@435 | 25 | // Interface for generating the frame map for compiled code. A frame map |
duke@435 | 26 | // describes for a specific pc whether each register and frame stack slot is: |
duke@435 | 27 | // Oop - A GC root for current frame |
duke@435 | 28 | // Value - Live non-oop, non-float value: int, either half of double |
duke@435 | 29 | // Dead - Dead; can be Zapped for debugging |
duke@435 | 30 | // CalleeXX - Callee saved; also describes which caller register is saved |
duke@435 | 31 | // DerivedXX - A derived oop; original oop is described. |
duke@435 | 32 | // |
duke@435 | 33 | // OopMapValue describes a single OopMap entry |
duke@435 | 34 | |
duke@435 | 35 | class frame; |
duke@435 | 36 | class RegisterMap; |
duke@435 | 37 | class DerivedPointerEntry; |
duke@435 | 38 | |
duke@435 | 39 | class OopMapValue: public StackObj { |
duke@435 | 40 | friend class VMStructs; |
duke@435 | 41 | private: |
duke@435 | 42 | short _value; |
duke@435 | 43 | int value() const { return _value; } |
duke@435 | 44 | void set_value(int value) { _value = value; } |
duke@435 | 45 | short _content_reg; |
duke@435 | 46 | |
duke@435 | 47 | public: |
duke@435 | 48 | // Constants |
duke@435 | 49 | enum { type_bits = 6, |
duke@435 | 50 | register_bits = BitsPerShort - type_bits }; |
duke@435 | 51 | |
duke@435 | 52 | enum { type_shift = 0, |
duke@435 | 53 | register_shift = type_bits }; |
duke@435 | 54 | |
duke@435 | 55 | enum { type_mask = right_n_bits(type_bits), |
duke@435 | 56 | type_mask_in_place = type_mask << type_shift, |
duke@435 | 57 | register_mask = right_n_bits(register_bits), |
duke@435 | 58 | register_mask_in_place = register_mask << register_shift }; |
duke@435 | 59 | |
duke@435 | 60 | enum oop_types { // must fit in type_bits |
duke@435 | 61 | unused_value =0, // powers of 2, for masking OopMapStream |
duke@435 | 62 | oop_value = 1, |
duke@435 | 63 | value_value = 2, |
coleenp@548 | 64 | narrowoop_value = 4, |
duke@435 | 65 | callee_saved_value = 8, |
duke@435 | 66 | derived_oop_value= 16, |
duke@435 | 67 | stack_obj = 32 }; |
duke@435 | 68 | |
duke@435 | 69 | // Constructors |
duke@435 | 70 | OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); } |
duke@435 | 71 | OopMapValue (VMReg reg, oop_types t) { set_reg_type(reg,t); } |
duke@435 | 72 | OopMapValue (VMReg reg, oop_types t, VMReg reg2) { set_reg_type(reg,t); set_content_reg(reg2); } |
duke@435 | 73 | OopMapValue (CompressedReadStream* stream) { read_from(stream); } |
duke@435 | 74 | |
duke@435 | 75 | // Archiving |
duke@435 | 76 | void write_on(CompressedWriteStream* stream) { |
duke@435 | 77 | stream->write_int(value()); |
duke@435 | 78 | if(is_callee_saved() || is_derived_oop()) { |
duke@435 | 79 | stream->write_int(content_reg()->value()); |
duke@435 | 80 | } |
duke@435 | 81 | } |
duke@435 | 82 | |
duke@435 | 83 | void read_from(CompressedReadStream* stream) { |
duke@435 | 84 | set_value(stream->read_int()); |
duke@435 | 85 | if(is_callee_saved() || is_derived_oop()) { |
duke@435 | 86 | set_content_reg(VMRegImpl::as_VMReg(stream->read_int(), true)); |
duke@435 | 87 | } |
duke@435 | 88 | } |
duke@435 | 89 | |
duke@435 | 90 | // Querying |
duke@435 | 91 | bool is_oop() { return mask_bits(value(), type_mask_in_place) == oop_value; } |
duke@435 | 92 | bool is_value() { return mask_bits(value(), type_mask_in_place) == value_value; } |
coleenp@548 | 93 | bool is_narrowoop() { return mask_bits(value(), type_mask_in_place) == narrowoop_value; } |
duke@435 | 94 | bool is_callee_saved() { return mask_bits(value(), type_mask_in_place) == callee_saved_value; } |
duke@435 | 95 | bool is_derived_oop() { return mask_bits(value(), type_mask_in_place) == derived_oop_value; } |
duke@435 | 96 | bool is_stack_obj() { return mask_bits(value(), type_mask_in_place) == stack_obj; } |
duke@435 | 97 | |
duke@435 | 98 | void set_oop() { set_value((value() & register_mask_in_place) | oop_value); } |
duke@435 | 99 | void set_value() { set_value((value() & register_mask_in_place) | value_value); } |
coleenp@548 | 100 | void set_narrowoop() { set_value((value() & register_mask_in_place) | narrowoop_value); } |
duke@435 | 101 | void set_callee_saved() { set_value((value() & register_mask_in_place) | callee_saved_value); } |
duke@435 | 102 | void set_derived_oop() { set_value((value() & register_mask_in_place) | derived_oop_value); } |
duke@435 | 103 | void set_stack_obj() { set_value((value() & register_mask_in_place) | stack_obj); } |
duke@435 | 104 | |
duke@435 | 105 | VMReg reg() const { return VMRegImpl::as_VMReg(mask_bits(value(), register_mask_in_place) >> register_shift); } |
duke@435 | 106 | oop_types type() const { return (oop_types)mask_bits(value(), type_mask_in_place); } |
duke@435 | 107 | |
duke@435 | 108 | static bool legal_vm_reg_name(VMReg p) { |
duke@435 | 109 | return (p->value() == (p->value() & register_mask)); |
duke@435 | 110 | } |
duke@435 | 111 | |
duke@435 | 112 | void set_reg_type(VMReg p, oop_types t) { |
duke@435 | 113 | set_value((p->value() << register_shift) | t); |
duke@435 | 114 | assert(reg() == p, "sanity check" ); |
duke@435 | 115 | assert(type() == t, "sanity check" ); |
duke@435 | 116 | } |
duke@435 | 117 | |
duke@435 | 118 | |
duke@435 | 119 | VMReg content_reg() const { return VMRegImpl::as_VMReg(_content_reg, true); } |
duke@435 | 120 | void set_content_reg(VMReg r) { _content_reg = r->value(); } |
duke@435 | 121 | |
duke@435 | 122 | // Physical location queries |
duke@435 | 123 | bool is_register_loc() { return reg()->is_reg(); } |
duke@435 | 124 | bool is_stack_loc() { return reg()->is_stack(); } |
duke@435 | 125 | |
duke@435 | 126 | // Returns offset from sp. |
duke@435 | 127 | int stack_offset() { |
duke@435 | 128 | assert(is_stack_loc(), "must be stack location"); |
duke@435 | 129 | return reg()->reg2stack(); |
duke@435 | 130 | } |
duke@435 | 131 | |
jrose@535 | 132 | void print_on(outputStream* st) const; |
kvn@460 | 133 | void print() const { print_on(tty); } |
duke@435 | 134 | }; |
duke@435 | 135 | |
duke@435 | 136 | |
duke@435 | 137 | class OopMap: public ResourceObj { |
duke@435 | 138 | friend class OopMapStream; |
duke@435 | 139 | friend class VMStructs; |
duke@435 | 140 | private: |
duke@435 | 141 | int _pc_offset; |
duke@435 | 142 | int _omv_count; |
duke@435 | 143 | int _omv_data_size; |
duke@435 | 144 | unsigned char* _omv_data; |
duke@435 | 145 | CompressedWriteStream* _write_stream; |
duke@435 | 146 | |
duke@435 | 147 | debug_only( OopMapValue::oop_types* _locs_used; int _locs_length;) |
duke@435 | 148 | |
duke@435 | 149 | // Accessors |
duke@435 | 150 | unsigned char* omv_data() const { return _omv_data; } |
duke@435 | 151 | void set_omv_data(unsigned char* value) { _omv_data = value; } |
duke@435 | 152 | int omv_data_size() const { return _omv_data_size; } |
duke@435 | 153 | void set_omv_data_size(int value) { _omv_data_size = value; } |
duke@435 | 154 | int omv_count() const { return _omv_count; } |
duke@435 | 155 | void set_omv_count(int value) { _omv_count = value; } |
duke@435 | 156 | void increment_count() { _omv_count++; } |
duke@435 | 157 | CompressedWriteStream* write_stream() const { return _write_stream; } |
duke@435 | 158 | void set_write_stream(CompressedWriteStream* value) { _write_stream = value; } |
duke@435 | 159 | |
duke@435 | 160 | private: |
duke@435 | 161 | enum DeepCopyToken { _deep_copy_token }; |
duke@435 | 162 | OopMap(DeepCopyToken, OopMap* source); // used only by deep_copy |
duke@435 | 163 | |
duke@435 | 164 | public: |
duke@435 | 165 | OopMap(int frame_size, int arg_count); |
duke@435 | 166 | |
duke@435 | 167 | // pc-offset handling |
duke@435 | 168 | int offset() const { return _pc_offset; } |
duke@435 | 169 | void set_offset(int o) { _pc_offset = o; } |
duke@435 | 170 | |
duke@435 | 171 | // Check to avoid double insertion |
duke@435 | 172 | debug_only(OopMapValue::oop_types locs_used( int indx ) { return _locs_used[indx]; }) |
duke@435 | 173 | |
duke@435 | 174 | // Construction |
duke@435 | 175 | // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd |
duke@435 | 176 | // slots to hold 4-byte values like ints and floats in the LP64 build. |
duke@435 | 177 | void set_oop ( VMReg local); |
duke@435 | 178 | void set_value( VMReg local); |
coleenp@548 | 179 | void set_narrowoop(VMReg local); |
duke@435 | 180 | void set_dead ( VMReg local); |
duke@435 | 181 | void set_callee_saved( VMReg local, VMReg caller_machine_register ); |
duke@435 | 182 | void set_derived_oop ( VMReg local, VMReg derived_from_local_register ); |
duke@435 | 183 | void set_stack_obj( VMReg local); |
duke@435 | 184 | void set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional); |
duke@435 | 185 | |
duke@435 | 186 | int heap_size() const; |
duke@435 | 187 | void copy_to(address addr); |
duke@435 | 188 | OopMap* deep_copy(); |
duke@435 | 189 | |
duke@435 | 190 | bool has_derived_pointer() const PRODUCT_RETURN0; |
duke@435 | 191 | |
duke@435 | 192 | bool legal_vm_reg_name(VMReg local) { |
duke@435 | 193 | return OopMapValue::legal_vm_reg_name(local); |
duke@435 | 194 | } |
duke@435 | 195 | |
duke@435 | 196 | // Printing |
jrose@535 | 197 | void print_on(outputStream* st) const; |
duke@435 | 198 | void print() const { print_on(tty); } |
duke@435 | 199 | }; |
duke@435 | 200 | |
duke@435 | 201 | |
duke@435 | 202 | class OopMapSet : public ResourceObj { |
duke@435 | 203 | friend class VMStructs; |
duke@435 | 204 | private: |
duke@435 | 205 | int _om_count; |
duke@435 | 206 | int _om_size; |
duke@435 | 207 | OopMap** _om_data; |
duke@435 | 208 | |
duke@435 | 209 | int om_count() const { return _om_count; } |
duke@435 | 210 | void set_om_count(int value) { _om_count = value; } |
duke@435 | 211 | void increment_count() { _om_count++; } |
duke@435 | 212 | int om_size() const { return _om_size; } |
duke@435 | 213 | void set_om_size(int value) { _om_size = value; } |
duke@435 | 214 | OopMap** om_data() const { return _om_data; } |
duke@435 | 215 | void set_om_data(OopMap** value) { _om_data = value; } |
duke@435 | 216 | void grow_om_data(); |
duke@435 | 217 | void set(int index,OopMap* value) { assert((index == 0) || ((index > 0) && (index < om_size())),"bad index"); _om_data[index] = value; } |
duke@435 | 218 | |
duke@435 | 219 | public: |
duke@435 | 220 | OopMapSet(); |
duke@435 | 221 | |
duke@435 | 222 | // returns the number of OopMaps in this OopMapSet |
duke@435 | 223 | int size() const { return _om_count; } |
duke@435 | 224 | // returns the OopMap at a given index |
duke@435 | 225 | OopMap* at(int index) const { assert((index >= 0) && (index <= om_count()),"bad index"); return _om_data[index]; } |
duke@435 | 226 | |
duke@435 | 227 | // Collect OopMaps. |
duke@435 | 228 | void add_gc_map(int pc, OopMap* map); |
duke@435 | 229 | |
duke@435 | 230 | // Returns the only oop map. Used for reconstructing |
duke@435 | 231 | // Adapter frames during deoptimization |
duke@435 | 232 | OopMap* singular_oop_map(); |
duke@435 | 233 | |
duke@435 | 234 | // returns OopMap in that is anchored to the pc |
duke@435 | 235 | OopMap* find_map_at_offset(int pc_offset) const; |
duke@435 | 236 | |
duke@435 | 237 | int heap_size() const; |
duke@435 | 238 | void copy_to(address addr); |
duke@435 | 239 | |
duke@435 | 240 | // Iterates through frame for a compiled method |
duke@435 | 241 | static void oops_do (const frame* fr, |
duke@435 | 242 | const RegisterMap* reg_map, OopClosure* f); |
duke@435 | 243 | static void update_register_map(const frame* fr, RegisterMap *reg_map); |
duke@435 | 244 | |
duke@435 | 245 | // Iterates through frame for a compiled method for dead ones and values, too |
duke@435 | 246 | static void all_do(const frame* fr, const RegisterMap* reg_map, |
duke@435 | 247 | OopClosure* oop_fn, |
duke@435 | 248 | void derived_oop_fn(oop* base, oop* derived), |
coleenp@548 | 249 | OopClosure* value_fn); |
duke@435 | 250 | |
duke@435 | 251 | // Printing |
jrose@535 | 252 | void print_on(outputStream* st) const; |
duke@435 | 253 | void print() const { print_on(tty); } |
duke@435 | 254 | }; |
duke@435 | 255 | |
duke@435 | 256 | |
duke@435 | 257 | class OopMapStream : public StackObj { |
duke@435 | 258 | private: |
duke@435 | 259 | CompressedReadStream* _stream; |
duke@435 | 260 | int _mask; |
duke@435 | 261 | int _size; |
duke@435 | 262 | int _position; |
duke@435 | 263 | bool _valid_omv; |
duke@435 | 264 | OopMapValue _omv; |
duke@435 | 265 | void find_next(); |
duke@435 | 266 | |
duke@435 | 267 | public: |
duke@435 | 268 | OopMapStream(OopMap* oop_map); |
duke@435 | 269 | OopMapStream(OopMap* oop_map, int oop_types_mask); |
duke@435 | 270 | bool is_done() { if(!_valid_omv) { find_next(); } return !_valid_omv; } |
duke@435 | 271 | void next() { find_next(); } |
duke@435 | 272 | OopMapValue current() { return _omv; } |
duke@435 | 273 | }; |
duke@435 | 274 | |
duke@435 | 275 | |
duke@435 | 276 | // Derived pointer support. This table keeps track of all derived points on a |
duke@435 | 277 | // stack. It is cleared before each scavenge/GC. During the traversal of all |
duke@435 | 278 | // oops, it is filled in with references to all locations that contains a |
duke@435 | 279 | // derived oop (assumed to be very few). When the GC is complete, the derived |
duke@435 | 280 | // pointers are updated based on their base pointers new value and an offset. |
duke@435 | 281 | #ifdef COMPILER2 |
duke@435 | 282 | class DerivedPointerTable : public AllStatic { |
duke@435 | 283 | friend class VMStructs; |
duke@435 | 284 | private: |
duke@435 | 285 | static GrowableArray<DerivedPointerEntry*>* _list; |
duke@435 | 286 | static bool _active; // do not record pointers for verify pass etc. |
duke@435 | 287 | public: |
duke@435 | 288 | static void clear(); // Called before scavenge/GC |
duke@435 | 289 | static void add(oop *derived, oop *base); // Called during scavenge/GC |
duke@435 | 290 | static void update_pointers(); // Called after scavenge/GC |
duke@435 | 291 | static bool is_empty() { return _list == NULL || _list->is_empty(); } |
duke@435 | 292 | static bool is_active() { return _active; } |
duke@435 | 293 | static void set_active(bool value) { _active = value; } |
duke@435 | 294 | }; |
duke@435 | 295 | |
duke@435 | 296 | // A utility class to temporarily "deactivate" the DerivedPointerTable. |
duke@435 | 297 | // (Note: clients are responsible for any MT-safety issues) |
duke@435 | 298 | class DerivedPointerTableDeactivate: public StackObj { |
duke@435 | 299 | private: |
duke@435 | 300 | bool _active; |
duke@435 | 301 | public: |
duke@435 | 302 | DerivedPointerTableDeactivate() { |
duke@435 | 303 | _active = DerivedPointerTable::is_active(); |
duke@435 | 304 | if (_active) { |
duke@435 | 305 | DerivedPointerTable::set_active(false); |
duke@435 | 306 | } |
duke@435 | 307 | } |
duke@435 | 308 | |
duke@435 | 309 | ~DerivedPointerTableDeactivate() { |
duke@435 | 310 | assert(!DerivedPointerTable::is_active(), |
duke@435 | 311 | "Inconsistency: not MT-safe"); |
duke@435 | 312 | if (_active) { |
duke@435 | 313 | DerivedPointerTable::set_active(true); |
duke@435 | 314 | } |
duke@435 | 315 | } |
duke@435 | 316 | }; |
duke@435 | 317 | #endif // COMPILER2 |