1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/compiler/oopMap.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,662 @@ 1.4 +/* 1.5 + * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +# include "incls/_precompiled.incl" 1.29 +# include "incls/_oopMap.cpp.incl" 1.30 + 1.31 +// OopMapStream 1.32 + 1.33 +OopMapStream::OopMapStream(OopMap* oop_map) { 1.34 + if(oop_map->omv_data() == NULL) { 1.35 + _stream = new CompressedReadStream(oop_map->write_stream()->buffer()); 1.36 + } else { 1.37 + _stream = new CompressedReadStream(oop_map->omv_data()); 1.38 + } 1.39 + _mask = OopMapValue::type_mask_in_place; 1.40 + _size = oop_map->omv_count(); 1.41 + _position = 0; 1.42 + _valid_omv = false; 1.43 +} 1.44 + 1.45 + 1.46 +OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) { 1.47 + if(oop_map->omv_data() == NULL) { 1.48 + _stream = new CompressedReadStream(oop_map->write_stream()->buffer()); 1.49 + } else { 1.50 + _stream = new CompressedReadStream(oop_map->omv_data()); 1.51 + } 1.52 + _mask = oop_types_mask; 1.53 + _size = oop_map->omv_count(); 1.54 + _position = 0; 1.55 + _valid_omv = false; 1.56 +} 1.57 + 1.58 + 1.59 +void OopMapStream::find_next() { 1.60 + while(_position++ < _size) { 1.61 + _omv.read_from(_stream); 1.62 + if(((int)_omv.type() & _mask) > 0) { 1.63 + _valid_omv = true; 1.64 + return; 1.65 + } 1.66 + } 1.67 + _valid_omv = false; 1.68 +} 1.69 + 1.70 + 1.71 +// OopMap 1.72 + 1.73 +// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd 1.74 +// slots to hold 4-byte values like ints and floats in the LP64 build. 1.75 +OopMap::OopMap(int frame_size, int arg_count) { 1.76 + // OopMaps are usually quite so small, so pick a small initial size 1.77 + set_write_stream(new CompressedWriteStream(32)); 1.78 + set_omv_data(NULL); 1.79 + set_omv_count(0); 1.80 + 1.81 +#ifdef ASSERT 1.82 + _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count; 1.83 + _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length); 1.84 + for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value; 1.85 +#endif 1.86 +} 1.87 + 1.88 + 1.89 +OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) { 1.90 + // This constructor does a deep copy 1.91 + // of the source OopMap. 1.92 + set_write_stream(new CompressedWriteStream(source->omv_count() * 2)); 1.93 + set_omv_data(NULL); 1.94 + set_omv_count(0); 1.95 + set_offset(source->offset()); 1.96 + 1.97 +#ifdef ASSERT 1.98 + _locs_length = source->_locs_length; 1.99 + _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length); 1.100 + for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value; 1.101 +#endif 1.102 + 1.103 + // We need to copy the entries too. 1.104 + for (OopMapStream oms(source); !oms.is_done(); oms.next()) { 1.105 + OopMapValue omv = oms.current(); 1.106 + omv.write_on(write_stream()); 1.107 + increment_count(); 1.108 + } 1.109 +} 1.110 + 1.111 + 1.112 +OopMap* OopMap::deep_copy() { 1.113 + return new OopMap(_deep_copy_token, this); 1.114 +} 1.115 + 1.116 + 1.117 +void OopMap::copy_to(address addr) { 1.118 + memcpy(addr,this,sizeof(OopMap)); 1.119 + memcpy(addr + sizeof(OopMap),write_stream()->buffer(),write_stream()->position()); 1.120 + OopMap* new_oop = (OopMap*)addr; 1.121 + new_oop->set_omv_data_size(write_stream()->position()); 1.122 + new_oop->set_omv_data((unsigned char *)(addr + sizeof(OopMap))); 1.123 + new_oop->set_write_stream(NULL); 1.124 +} 1.125 + 1.126 + 1.127 +int OopMap::heap_size() const { 1.128 + int size = sizeof(OopMap); 1.129 + int align = sizeof(void *) - 1; 1.130 + if(write_stream() != NULL) { 1.131 + size += write_stream()->position(); 1.132 + } else { 1.133 + size += omv_data_size(); 1.134 + } 1.135 + // Align to a reasonable ending point 1.136 + size = ((size+align) & ~align); 1.137 + return size; 1.138 +} 1.139 + 1.140 +// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd 1.141 +// slots to hold 4-byte values like ints and floats in the LP64 build. 1.142 +void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) { 1.143 + 1.144 + assert(reg->value() < _locs_length, "too big reg value for stack size"); 1.145 + assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" ); 1.146 + debug_only( _locs_used[reg->value()] = x; ) 1.147 + 1.148 + OopMapValue o(reg, x); 1.149 + 1.150 + if(x == OopMapValue::callee_saved_value) { 1.151 + // This can never be a stack location, so we don't need to transform it. 1.152 + assert(optional->is_reg(), "Trying to callee save a stack location"); 1.153 + o.set_content_reg(optional); 1.154 + } else if(x == OopMapValue::derived_oop_value) { 1.155 + o.set_content_reg(optional); 1.156 + } 1.157 + 1.158 + o.write_on(write_stream()); 1.159 + increment_count(); 1.160 +} 1.161 + 1.162 + 1.163 +void OopMap::set_oop(VMReg reg) { 1.164 + set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad()); 1.165 +} 1.166 + 1.167 + 1.168 +void OopMap::set_value(VMReg reg) { 1.169 + // At this time, we only need value entries in our OopMap when ZapDeadCompiledLocals is active. 1.170 + if (ZapDeadCompiledLocals) 1.171 + set_xxx(reg, OopMapValue::value_value, VMRegImpl::Bad()); 1.172 +} 1.173 + 1.174 + 1.175 +void OopMap::set_dead(VMReg reg) { 1.176 + // At this time, we only need dead entries in our OopMap when ZapDeadCompiledLocals is active. 1.177 + if (ZapDeadCompiledLocals) { 1.178 + set_xxx(reg, OopMapValue::dead_value, VMRegImpl::Bad()); 1.179 + } 1.180 +} 1.181 + 1.182 + 1.183 +void OopMap::set_callee_saved(VMReg reg, VMReg caller_machine_register ) { 1.184 + set_xxx(reg, OopMapValue::callee_saved_value, caller_machine_register); 1.185 +} 1.186 + 1.187 + 1.188 +void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) { 1.189 + if( reg == derived_from_local_register ) { 1.190 + // Actually an oop, derived shares storage with base, 1.191 + set_oop(reg); 1.192 + } else { 1.193 + set_xxx(reg, OopMapValue::derived_oop_value, derived_from_local_register); 1.194 + } 1.195 +} 1.196 + 1.197 +void OopMap::set_stack_obj(VMReg reg) { 1.198 + set_xxx(reg, OopMapValue::stack_obj, VMRegImpl::Bad()); 1.199 +} 1.200 + 1.201 +// OopMapSet 1.202 + 1.203 +OopMapSet::OopMapSet() { 1.204 + set_om_size(MinOopMapAllocation); 1.205 + set_om_count(0); 1.206 + OopMap** temp = NEW_RESOURCE_ARRAY(OopMap*, om_size()); 1.207 + set_om_data(temp); 1.208 +} 1.209 + 1.210 + 1.211 +void OopMapSet::grow_om_data() { 1.212 + int new_size = om_size() * 2; 1.213 + OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size); 1.214 + memcpy(new_data,om_data(),om_size() * sizeof(OopMap*)); 1.215 + set_om_size(new_size); 1.216 + set_om_data(new_data); 1.217 +} 1.218 + 1.219 + 1.220 +void OopMapSet::copy_to(address addr) { 1.221 + address temp = addr; 1.222 + int align = sizeof(void *) - 1; 1.223 + // Copy this 1.224 + memcpy(addr,this,sizeof(OopMapSet)); 1.225 + temp += sizeof(OopMapSet); 1.226 + temp = (address)((intptr_t)(temp + align) & ~align); 1.227 + // Do the needed fixups to the new OopMapSet 1.228 + OopMapSet* new_set = (OopMapSet*)addr; 1.229 + new_set->set_om_data((OopMap**)temp); 1.230 + // Allow enough space for the OopMap pointers 1.231 + temp += (om_count() * sizeof(OopMap*)); 1.232 + 1.233 + for(int i=0; i < om_count(); i++) { 1.234 + OopMap* map = at(i); 1.235 + map->copy_to((address)temp); 1.236 + new_set->set(i,(OopMap*)temp); 1.237 + temp += map->heap_size(); 1.238 + } 1.239 + // This "locks" the OopMapSet 1.240 + new_set->set_om_size(-1); 1.241 +} 1.242 + 1.243 + 1.244 +void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) { 1.245 + assert(om_size() != -1,"Cannot grow a fixed OopMapSet"); 1.246 + 1.247 + if(om_count() >= om_size()) { 1.248 + grow_om_data(); 1.249 + } 1.250 + map->set_offset(pc_offset); 1.251 + 1.252 +#ifdef ASSERT 1.253 + if(om_count() > 0) { 1.254 + OopMap* last = at(om_count()-1); 1.255 + if (last->offset() == map->offset() ) { 1.256 + fatal("OopMap inserted twice"); 1.257 + } 1.258 + if(last->offset() > map->offset()) { 1.259 + tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d", 1.260 + om_count(),last->offset(),om_count()+1,map->offset()); 1.261 + } 1.262 + } 1.263 +#endif // ASSERT 1.264 + 1.265 + set(om_count(),map); 1.266 + increment_count(); 1.267 +} 1.268 + 1.269 + 1.270 +int OopMapSet::heap_size() const { 1.271 + // The space we use 1.272 + int size = sizeof(OopMap); 1.273 + int align = sizeof(void *) - 1; 1.274 + size = ((size+align) & ~align); 1.275 + size += om_count() * sizeof(OopMap*); 1.276 + 1.277 + // Now add in the space needed for the indivdiual OopMaps 1.278 + for(int i=0; i < om_count(); i++) { 1.279 + size += at(i)->heap_size(); 1.280 + } 1.281 + // We don't need to align this, it will be naturally pointer aligned 1.282 + return size; 1.283 +} 1.284 + 1.285 + 1.286 +OopMap* OopMapSet::singular_oop_map() { 1.287 + guarantee(om_count() == 1, "Make sure we only have a single gc point"); 1.288 + return at(0); 1.289 +} 1.290 + 1.291 + 1.292 +OopMap* OopMapSet::find_map_at_offset(int pc_offset) const { 1.293 + int i, len = om_count(); 1.294 + assert( len > 0, "must have pointer maps" ); 1.295 + 1.296 + // Scan through oopmaps. Stop when current offset is either equal or greater 1.297 + // than the one we are looking for. 1.298 + for( i = 0; i < len; i++) { 1.299 + if( at(i)->offset() >= pc_offset ) 1.300 + break; 1.301 + } 1.302 + 1.303 + assert( i < len, "oopmap not found" ); 1.304 + 1.305 + OopMap* m = at(i); 1.306 + assert( m->offset() == pc_offset, "oopmap not found" ); 1.307 + return m; 1.308 +} 1.309 + 1.310 +class DoNothingClosure: public OopClosure { 1.311 +public: void do_oop(oop* p) {} 1.312 +}; 1.313 +static DoNothingClosure do_nothing; 1.314 + 1.315 +static void add_derived_oop(oop* base, oop* derived) { 1.316 +#ifndef TIERED 1.317 + COMPILER1_PRESENT(ShouldNotReachHere();) 1.318 +#endif // TIERED 1.319 +#ifdef COMPILER2 1.320 + DerivedPointerTable::add(derived, base); 1.321 +#endif // COMPILER2 1.322 +} 1.323 + 1.324 + 1.325 +#ifndef PRODUCT 1.326 +static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) { 1.327 + // Print oopmap and regmap 1.328 + tty->print_cr("------ "); 1.329 + CodeBlob* cb = fr->cb(); 1.330 + OopMapSet* maps = cb->oop_maps(); 1.331 + OopMap* map = cb->oop_map_for_return_address(fr->pc()); 1.332 + map->print(); 1.333 + if( cb->is_nmethod() ) { 1.334 + nmethod* nm = (nmethod*)cb; 1.335 + // native wrappers have no scope data, it is implied 1.336 + if (nm->is_native_method()) { 1.337 + tty->print("bci: 0 (native)"); 1.338 + } else { 1.339 + ScopeDesc* scope = nm->scope_desc_at(fr->pc()); 1.340 + tty->print("bci: %d ",scope->bci()); 1.341 + } 1.342 + } 1.343 + tty->cr(); 1.344 + fr->print_on(tty); 1.345 + tty->print(" "); 1.346 + cb->print_value_on(tty); tty->cr(); 1.347 + reg_map->print(); 1.348 + tty->print_cr("------ "); 1.349 + 1.350 +} 1.351 +#endif // PRODUCT 1.352 + 1.353 +void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) { 1.354 + // add derived oops to a table 1.355 + all_do(fr, reg_map, f, add_derived_oop, &do_nothing, &do_nothing); 1.356 +} 1.357 + 1.358 + 1.359 +void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, 1.360 + OopClosure* oop_fn, void derived_oop_fn(oop*, oop*), 1.361 + OopClosure* value_fn, OopClosure* dead_fn) { 1.362 + CodeBlob* cb = fr->cb(); 1.363 + { 1.364 + assert(cb != NULL, "no codeblob"); 1.365 + } 1.366 + 1.367 + NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);) 1.368 + 1.369 + OopMapSet* maps = cb->oop_maps(); 1.370 + OopMap* map = cb->oop_map_for_return_address(fr->pc()); 1.371 + assert(map != NULL, " no ptr map found"); 1.372 + 1.373 + // handle derived pointers first (otherwise base pointer may be 1.374 + // changed before derived pointer offset has been collected) 1.375 + OopMapValue omv; 1.376 + { 1.377 + OopMapStream oms(map,OopMapValue::derived_oop_value); 1.378 + if (!oms.is_done()) { 1.379 +#ifndef TIERED 1.380 + COMPILER1_PRESENT(ShouldNotReachHere();) 1.381 +#endif // !TIERED 1.382 + // Protect the operation on the derived pointers. This 1.383 + // protects the addition of derived pointers to the shared 1.384 + // derived pointer table in DerivedPointerTable::add(). 1.385 + MutexLockerEx x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag); 1.386 + do { 1.387 + omv = oms.current(); 1.388 + oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); 1.389 + if ( loc != NULL ) { 1.390 + oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map); 1.391 + oop *derived_loc = loc; 1.392 + derived_oop_fn(base_loc, derived_loc); 1.393 + } 1.394 + oms.next(); 1.395 + } while (!oms.is_done()); 1.396 + } 1.397 + } 1.398 + 1.399 + // We want dead, value and oop oop_types 1.400 + int mask = OopMapValue::oop_value | OopMapValue::value_value | OopMapValue::dead_value; 1.401 + { 1.402 + for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) { 1.403 + omv = oms.current(); 1.404 + oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); 1.405 + if ( loc != NULL ) { 1.406 + if ( omv.type() == OopMapValue::oop_value ) { 1.407 +#ifdef ASSERT 1.408 + if (COMPILER2_PRESENT(!DoEscapeAnalysis &&) !Universe::heap()->is_in_or_null(*loc)) { 1.409 + tty->print_cr("# Found non oop pointer. Dumping state at failure"); 1.410 + // try to dump out some helpful debugging information 1.411 + trace_codeblob_maps(fr, reg_map); 1.412 + omv.print(); 1.413 + tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc); 1.414 + // do the real assert. 1.415 + assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer"); 1.416 + } 1.417 +#endif // ASSERT 1.418 + oop_fn->do_oop(loc); 1.419 + } else if ( omv.type() == OopMapValue::value_value ) { 1.420 + value_fn->do_oop(loc); 1.421 + } else if ( omv.type() == OopMapValue::dead_value ) { 1.422 + dead_fn->do_oop(loc); 1.423 + } 1.424 + } 1.425 + } 1.426 + } 1.427 + 1.428 +#ifdef COMPILER2 1.429 + if (DoEscapeAnalysis) { 1.430 + for (OopMapStream oms(map, OopMapValue::stack_obj); !oms.is_done(); oms.next()) { 1.431 + omv = oms.current(); 1.432 + assert(omv.is_stack_loc(), "should refer to stack location"); 1.433 + oop loc = (oop) fr->oopmapreg_to_location(omv.reg(),reg_map); 1.434 + oop_fn->do_oop(&loc); 1.435 + } 1.436 + } 1.437 +#endif // COMPILER2 1.438 +} 1.439 + 1.440 + 1.441 +// Update callee-saved register info for the following frame 1.442 +void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) { 1.443 + ResourceMark rm; 1.444 + CodeBlob* cb = fr->cb(); 1.445 + assert(cb != NULL, "no codeblob"); 1.446 + 1.447 + // Any reg might be saved by a safepoint handler (see generate_handler_blob). 1.448 + const int max_saved_on_entry_reg_count = ConcreteRegisterImpl::number_of_registers; 1.449 + assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id), 1.450 + "already updated this map; do not 'update' it twice!" ); 1.451 + debug_only(reg_map->_update_for_id = fr->id()); 1.452 + 1.453 + // Check if caller must update oop argument 1.454 + assert((reg_map->include_argument_oops() || 1.455 + !cb->caller_must_gc_arguments(reg_map->thread())), 1.456 + "include_argument_oops should already be set"); 1.457 + 1.458 + int nof_callee = 0; 1.459 + oop* locs[2*max_saved_on_entry_reg_count+1]; 1.460 + VMReg regs[2*max_saved_on_entry_reg_count+1]; 1.461 + // ("+1" because max_saved_on_entry_reg_count might be zero) 1.462 + 1.463 + // Scan through oopmap and find location of all callee-saved registers 1.464 + // (we do not do update in place, since info could be overwritten) 1.465 + 1.466 + address pc = fr->pc(); 1.467 + 1.468 + OopMap* map = cb->oop_map_for_return_address(pc); 1.469 + 1.470 + assert(map != NULL, " no ptr map found"); 1.471 + 1.472 + OopMapValue omv; 1.473 + for(OopMapStream oms(map,OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) { 1.474 + omv = oms.current(); 1.475 + assert(nof_callee < 2*max_saved_on_entry_reg_count, "overflow"); 1.476 + regs[nof_callee] = omv.content_reg(); 1.477 + locs[nof_callee] = fr->oopmapreg_to_location(omv.reg(),reg_map); 1.478 + nof_callee++; 1.479 + } 1.480 + 1.481 + // Check that runtime stubs save all callee-saved registers 1.482 +#ifdef COMPILER2 1.483 + assert(cb->is_compiled_by_c1() || !cb->is_runtime_stub() || 1.484 + (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT), 1.485 + "must save all"); 1.486 +#endif // COMPILER2 1.487 + 1.488 + // Copy found callee-saved register to reg_map 1.489 + for(int i = 0; i < nof_callee; i++) { 1.490 + reg_map->set_location(regs[i], (address)locs[i]); 1.491 + } 1.492 +} 1.493 + 1.494 +//============================================================================= 1.495 +// Non-Product code 1.496 + 1.497 +#ifndef PRODUCT 1.498 + 1.499 +bool OopMap::has_derived_pointer() const { 1.500 +#ifndef TIERED 1.501 + COMPILER1_PRESENT(return false); 1.502 +#endif // !TIERED 1.503 +#ifdef COMPILER2 1.504 + OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value); 1.505 + return oms.is_done(); 1.506 +#else 1.507 + return false; 1.508 +#endif // COMPILER2 1.509 +} 1.510 + 1.511 + 1.512 +void print_register_type(OopMapValue::oop_types x, VMReg optional) { 1.513 + switch( x ) { 1.514 + case OopMapValue::oop_value: 1.515 + tty->print("Oop"); 1.516 + break; 1.517 + case OopMapValue::value_value: 1.518 + tty->print("Value" ); 1.519 + break; 1.520 + case OopMapValue::dead_value: 1.521 + tty->print("Dead" ); 1.522 + break; 1.523 + case OopMapValue::callee_saved_value: 1.524 + tty->print("Callers_" ); 1.525 + optional->print(); 1.526 + break; 1.527 + case OopMapValue::derived_oop_value: 1.528 + tty->print("Derived_oop_" ); 1.529 + optional->print(); 1.530 + break; 1.531 + case OopMapValue::stack_obj: 1.532 + tty->print("Stack"); 1.533 + break; 1.534 + default: 1.535 + ShouldNotReachHere(); 1.536 + } 1.537 +} 1.538 + 1.539 + 1.540 +void OopMapValue::print() const { 1.541 + reg()->print(); 1.542 + tty->print("="); 1.543 + print_register_type(type(),content_reg()); 1.544 + tty->print(" "); 1.545 +} 1.546 + 1.547 + 1.548 +void OopMap::print_on(outputStream* st) const { 1.549 + OopMapValue omv; 1.550 + for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) { 1.551 + omv = oms.current(); 1.552 + omv.print_on(st); 1.553 + } 1.554 +} 1.555 + 1.556 + 1.557 +void OopMapSet::print_on(outputStream* st) const { 1.558 + int i, len = om_count(); 1.559 + 1.560 + st->print_cr("OopMapSet contains %d OopMaps\n",len); 1.561 + 1.562 + for( i = 0; i < len; i++) { 1.563 + OopMap* m = at(i); 1.564 + st->print_cr("OopMap #%d offset:%p",i,m->offset()); 1.565 + m->print_on(st); 1.566 + st->print_cr("\n"); 1.567 + } 1.568 +} 1.569 +#endif // !PRODUCT 1.570 + 1.571 + 1.572 +//------------------------------DerivedPointerTable--------------------------- 1.573 + 1.574 +#ifdef COMPILER2 1.575 + 1.576 +class DerivedPointerEntry : public CHeapObj { 1.577 + private: 1.578 + oop* _location; // Location of derived pointer (also pointing to the base) 1.579 + intptr_t _offset; // Offset from base pointer 1.580 + public: 1.581 + DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; } 1.582 + oop* location() { return _location; } 1.583 + intptr_t offset() { return _offset; } 1.584 +}; 1.585 + 1.586 + 1.587 +GrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL; 1.588 +bool DerivedPointerTable::_active = false; 1.589 + 1.590 + 1.591 +void DerivedPointerTable::clear() { 1.592 + // The first time, we create the list. Otherwise it should be 1.593 + // empty. If not, then we have probably forgotton to call 1.594 + // update_pointers after last GC/Scavenge. 1.595 + assert (!_active, "should not be active"); 1.596 + assert(_list == NULL || _list->length() == 0, "table not empty"); 1.597 + if (_list == NULL) { 1.598 + _list = new (ResourceObj::C_HEAP) GrowableArray<DerivedPointerEntry*>(10, true); // Allocated on C heap 1.599 + } 1.600 + _active = true; 1.601 +} 1.602 + 1.603 + 1.604 +// Returns value of location as an int 1.605 +intptr_t value_of_loc(oop *pointer) { return (intptr_t)(*pointer); } 1.606 + 1.607 + 1.608 +void DerivedPointerTable::add(oop *derived_loc, oop *base_loc) { 1.609 + assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop"); 1.610 + assert(derived_loc != base_loc, "Base and derived in same location"); 1.611 + if (_active) { 1.612 + assert(*derived_loc != (oop)base_loc, "location already added"); 1.613 + assert(_list != NULL, "list must exist"); 1.614 + intptr_t offset = value_of_loc(derived_loc) - value_of_loc(base_loc); 1.615 + assert(offset >= -1000000, "wrong derived pointer info"); 1.616 + 1.617 + if (TraceDerivedPointers) { 1.618 + tty->print_cr( 1.619 + "Add derived pointer@" INTPTR_FORMAT 1.620 + " - Derived: " INTPTR_FORMAT 1.621 + " Base: " INTPTR_FORMAT " (@" INTPTR_FORMAT ") (Offset: %d)", 1.622 + derived_loc, (address)*derived_loc, (address)*base_loc, base_loc, offset 1.623 + ); 1.624 + } 1.625 + // Set derived oop location to point to base. 1.626 + *derived_loc = (oop)base_loc; 1.627 + assert_lock_strong(DerivedPointerTableGC_lock); 1.628 + DerivedPointerEntry *entry = new DerivedPointerEntry(derived_loc, offset); 1.629 + _list->append(entry); 1.630 + } 1.631 +} 1.632 + 1.633 + 1.634 +void DerivedPointerTable::update_pointers() { 1.635 + assert(_list != NULL, "list must exist"); 1.636 + for(int i = 0; i < _list->length(); i++) { 1.637 + DerivedPointerEntry* entry = _list->at(i); 1.638 + oop* derived_loc = entry->location(); 1.639 + intptr_t offset = entry->offset(); 1.640 + // The derived oop was setup to point to location of base 1.641 + oop base = **(oop**)derived_loc; 1.642 + assert(Universe::heap()->is_in_or_null(base), "must be an oop"); 1.643 + 1.644 + *derived_loc = (oop)(((address)base) + offset); 1.645 + assert(value_of_loc(derived_loc) - value_of_loc(&base) == offset, "sanity check"); 1.646 + 1.647 + if (TraceDerivedPointers) { 1.648 + tty->print_cr("Updating derived pointer@" INTPTR_FORMAT 1.649 + " - Derived: " INTPTR_FORMAT " Base: " INTPTR_FORMAT " (Offset: %d)", 1.650 + derived_loc, (address)*derived_loc, (address)base, offset); 1.651 + } 1.652 + 1.653 + // Delete entry 1.654 + delete entry; 1.655 + _list->at_put(i, NULL); 1.656 + } 1.657 + // Clear list, so it is ready for next traversal (this is an invariant) 1.658 + if (TraceDerivedPointers && !_list->is_empty()) { 1.659 + tty->print_cr("--------------------------"); 1.660 + } 1.661 + _list->clear(); 1.662 + _active = false; 1.663 +} 1.664 + 1.665 +#endif // COMPILER2