oopMap.cpp revision 9111:a41fe5ffa839
14910Swollman/* 24910Swollman * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 34910Swollman * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 44910Swollman * 54910Swollman * This code is free software; you can redistribute it and/or modify it 625944Sjoerg * under the terms of the GNU General Public License version 2 only, as 74910Swollman * published by the Free Software Foundation. 825944Sjoerg * 925944Sjoerg * This code is distributed in the hope that it will be useful, but WITHOUT 1025944Sjoerg * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 114910Swollman * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 124910Swollman * version 2 for more details (a copy is included in the LICENSE file that 134910Swollman * accompanied this code). 144910Swollman * 154910Swollman * You should have received a copy of the GNU General Public License version 164910Swollman * 2 along with this work; if not, write to the Free Software Foundation, 174910Swollman * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1825944Sjoerg * 1916288Sgpalmer * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2028088Skjc * or visit www.oracle.com if you need additional information or have any 214910Swollman * questions. 224910Swollman * 234910Swollman */ 244952Sbde 254952Sbde#include "precompiled.hpp" 2624204Sbde#include "code/codeBlob.hpp" 274910Swollman#include "code/codeCache.hpp" 2825706Sjoerg#include "code/nmethod.hpp" 294910Swollman#include "code/scopeDesc.hpp" 304910Swollman#include "compiler/oopMap.hpp" 314910Swollman#include "gc/shared/collectedHeap.hpp" 324910Swollman#include "memory/allocation.inline.hpp" 334910Swollman#include "memory/resourceArea.hpp" 344910Swollman#include "runtime/frame.inline.hpp" 354910Swollman#include "runtime/signature.hpp" 364910Swollman#ifdef COMPILER1 374910Swollman#include "c1/c1_Defs.hpp" 384910Swollman#endif 394910Swollman#ifdef COMPILER2 404910Swollman#include "opto/optoreg.hpp" 414910Swollman#endif 424910Swollman#ifdef SPARC 434910Swollman#include "vmreg_sparc.inline.hpp" 4411819Sjulian#endif 4511819Sjulian 4611819Sjulian// OopMapStream 4711819Sjulian 4811819SjulianOopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) { 494910Swollman _stream = new CompressedReadStream(oop_map->write_stream()->buffer()); 504910Swollman _mask = oop_types_mask; 514910Swollman _size = oop_map->omv_count(); 524910Swollman _position = 0; 534910Swollman _valid_omv = false; 544910Swollman} 554910Swollman 564910SwollmanOopMapStream::OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask) { 574910Swollman _stream = new CompressedReadStream(oop_map->data_addr()); 584910Swollman _mask = oop_types_mask; 594910Swollman _size = oop_map->count(); 604910Swollman _position = 0; 614910Swollman _valid_omv = false; 624910Swollman} 634910Swollman 644910Swollmanvoid OopMapStream::find_next() { 6525944Sjoerg while(_position++ < _size) { 6625944Sjoerg _omv.read_from(_stream); 6725944Sjoerg if(((int)_omv.type() & _mask) > 0) { 6825955Sjoerg _valid_omv = true; 6925944Sjoerg return; 7025944Sjoerg } 7125944Sjoerg } 7225955Sjoerg _valid_omv = false; 7325955Sjoerg} 7425955Sjoerg 7525944Sjoerg 7625944Sjoerg// OopMap 7725955Sjoerg 7825955Sjoerg// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd 7925944Sjoerg// slots to hold 4-byte values like ints and floats in the LP64 build. 804910SwollmanOopMap::OopMap(int frame_size, int arg_count) { 814910Swollman // OopMaps are usually quite so small, so pick a small initial size 824910Swollman set_write_stream(new CompressedWriteStream(32)); 834910Swollman set_omv_count(0); 844910Swollman 8512495Speter#ifdef ASSERT 864910Swollman _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count; 874910Swollman _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length); 884910Swollman for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value; 8925944Sjoerg#endif 9025944Sjoerg} 9125944Sjoerg 9225944Sjoerg 9325944SjoergOopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) { 9425944Sjoerg // This constructor does a deep copy 9525944Sjoerg // of the source OopMap. 9625944Sjoerg set_write_stream(new CompressedWriteStream(source->omv_count() * 2)); 9725944Sjoerg set_omv_count(0); 9825944Sjoerg set_offset(source->offset()); 9925944Sjoerg 1004910Swollman#ifdef ASSERT 1014910Swollman _locs_length = source->_locs_length; 1024910Swollman _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length); 1034910Swollman for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value; 1044910Swollman#endif 1054910Swollman 1064910Swollman // We need to copy the entries too. 1074910Swollman for (OopMapStream oms(source); !oms.is_done(); oms.next()) { 1084910Swollman OopMapValue omv = oms.current(); 1094910Swollman omv.write_on(write_stream()); 11025944Sjoerg increment_count(); 11125944Sjoerg } 11225944Sjoerg} 1134910Swollman 1144910Swollman 1154910SwollmanOopMap* OopMap::deep_copy() { 1164910Swollman return new OopMap(_deep_copy_token, this); 1174910Swollman} 1184910Swollman 1194910Swollmanvoid OopMap::copy_data_to(address addr) const { 1204910Swollman memcpy(addr, write_stream()->buffer(), write_stream()->position()); 12125944Sjoerg} 12225944Sjoerg 12325944Sjoergint OopMap::heap_size() const { 12425944Sjoerg int size = sizeof(OopMap); 12525944Sjoerg int align = sizeof(void *) - 1; 12625944Sjoerg size += write_stream()->position(); 12725944Sjoerg // Align to a reasonable ending point 12825944Sjoerg size = ((size+align) & ~align); 12925944Sjoerg return size; 13025944Sjoerg} 13125944Sjoerg 13225944Sjoerg// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd 1334910Swollman// slots to hold 4-byte values like ints and floats in the LP64 build. 13411189Sjkhvoid OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) { 13511189Sjkh 13611189Sjkh assert(reg->value() < _locs_length, "too big reg value for stack size"); 1374910Swollman assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" ); 1384910Swollman debug_only( _locs_used[reg->value()] = x; ) 1394910Swollman 1404910Swollman OopMapValue o(reg, x); 14111189Sjkh 14211189Sjkh if(x == OopMapValue::callee_saved_value) { 14311189Sjkh // This can never be a stack location, so we don't need to transform it. 1444910Swollman assert(optional->is_reg(), "Trying to callee save a stack location"); 1454910Swollman o.set_content_reg(optional); 1464910Swollman } else if(x == OopMapValue::derived_oop_value) { 1474910Swollman o.set_content_reg(optional); 14811189Sjkh } 14911189Sjkh 15011189Sjkh o.write_on(write_stream()); 15111189Sjkh increment_count(); 15211189Sjkh} 15311189Sjkh 1544910Swollman 1554910Swollmanvoid OopMap::set_oop(VMReg reg) { 1564910Swollman set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad()); 15725944Sjoerg} 15825944Sjoerg 15925944Sjoerg 16025944Sjoergvoid OopMap::set_value(VMReg reg) { 16125944Sjoerg // At this time, we don't need value entries in our OopMap. 16225944Sjoerg} 16325944Sjoerg 16425944Sjoerg 16525944Sjoergvoid OopMap::set_narrowoop(VMReg reg) { 16625944Sjoerg set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad()); 16725944Sjoerg} 16825944Sjoerg 16925944Sjoerg 17025944Sjoergvoid OopMap::set_callee_saved(VMReg reg, VMReg caller_machine_register ) { 17125944Sjoerg set_xxx(reg, OopMapValue::callee_saved_value, caller_machine_register); 17225944Sjoerg} 17325944Sjoerg 17425944Sjoerg 17525944Sjoergvoid OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) { 17625944Sjoerg if( reg == derived_from_local_register ) { 17725944Sjoerg // Actually an oop, derived shares storage with base, 17825944Sjoerg set_oop(reg); 17925944Sjoerg } else { 18025944Sjoerg set_xxx(reg, OopMapValue::derived_oop_value, derived_from_local_register); 18125944Sjoerg } 18225944Sjoerg} 18325944Sjoerg 18425944Sjoerg// OopMapSet 18525944Sjoerg 18625944SjoergOopMapSet::OopMapSet() { 18725944Sjoerg set_om_size(MinOopMapAllocation); 18825944Sjoerg set_om_count(0); 18912820Sphk OopMap** temp = NEW_RESOURCE_ARRAY(OopMap*, om_size()); 1904910Swollman set_om_data(temp); 1914910Swollman} 1924910Swollman 1934910Swollman 1944910Swollmanvoid OopMapSet::grow_om_data() { 1954910Swollman int new_size = om_size() * 2; 1964910Swollman OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size); 19711189Sjkh memcpy(new_data,om_data(),om_size() * sizeof(OopMap*)); 1984910Swollman set_om_size(new_size); 1994910Swollman set_om_data(new_data); 2004910Swollman} 2014910Swollman 2024910Swollmanvoid OopMapSet::add_gc_map(int pc_offset, OopMap *map ) { 20325944Sjoerg assert(om_size() != -1,"Cannot grow a fixed OopMapSet"); 20425944Sjoerg 20525944Sjoerg if(om_count() >= om_size()) { 20625944Sjoerg grow_om_data(); 20711189Sjkh } 20825944Sjoerg map->set_offset(pc_offset); 20925944Sjoerg 2104910Swollman#ifdef ASSERT 21125944Sjoerg if(om_count() > 0) { 21225944Sjoerg OopMap* last = at(om_count()-1); 21325944Sjoerg if (last->offset() == map->offset() ) { 21425944Sjoerg fatal("OopMap inserted twice"); 21525944Sjoerg } 21625944Sjoerg if(last->offset() > map->offset()) { 21725944Sjoerg tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d", 21825944Sjoerg om_count(),last->offset(),om_count()+1,map->offset()); 21925944Sjoerg } 22025944Sjoerg } 22125944Sjoerg#endif // ASSERT 22225944Sjoerg 22325944Sjoerg set(om_count(),map); 22425944Sjoerg increment_count(); 22525944Sjoerg} 22625944Sjoerg 22725944Sjoerg 22825944Sjoergint OopMapSet::heap_size() const { 22925944Sjoerg // The space we use 23025944Sjoerg int size = sizeof(OopMap); 23125944Sjoerg int align = sizeof(void *) - 1; 23225944Sjoerg size = ((size+align) & ~align); 23325944Sjoerg size += om_count() * sizeof(OopMap*); 23425944Sjoerg 23525944Sjoerg // Now add in the space needed for the indivdiual OopMaps 23625944Sjoerg for(int i=0; i < om_count(); i++) { 23725944Sjoerg size += at(i)->heap_size(); 23825944Sjoerg } 23925944Sjoerg // We don't need to align this, it will be naturally pointer aligned 24025944Sjoerg return size; 24125944Sjoerg} 24225944Sjoerg 24325944Sjoerg 24425944SjoergOopMap* OopMapSet::singular_oop_map() { 24525944Sjoerg guarantee(om_count() == 1, "Make sure we only have a single gc point"); 24625944Sjoerg return at(0); 24725944Sjoerg} 24825944Sjoerg 24925944Sjoerg 25025944SjoergOopMap* OopMapSet::find_map_at_offset(int pc_offset) const { 25125944Sjoerg int i, len = om_count(); 25225944Sjoerg assert( len > 0, "must have pointer maps" ); 25325944Sjoerg 25425944Sjoerg // Scan through oopmaps. Stop when current offset is either equal or greater 25525944Sjoerg // than the one we are looking for. 25625944Sjoerg for( i = 0; i < len; i++) { 25725944Sjoerg if( at(i)->offset() >= pc_offset ) 25825944Sjoerg break; 25925944Sjoerg } 26025944Sjoerg 26125944Sjoerg assert( i < len, "oopmap not found" ); 26225944Sjoerg 26325944Sjoerg OopMap* m = at(i); 26425944Sjoerg assert( m->offset() == pc_offset, "oopmap not found" ); 26525944Sjoerg return m; 26625944Sjoerg} 26725944Sjoerg 26825944Sjoergclass DoNothingClosure: public OopClosure { 26925944Sjoerg public: 27025944Sjoerg void do_oop(oop* p) {} 27125944Sjoerg void do_oop(narrowOop* p) {} 27225944Sjoerg}; 27325944Sjoergstatic DoNothingClosure do_nothing; 27425944Sjoerg 27525944Sjoergstatic void add_derived_oop(oop* base, oop* derived) { 27625944Sjoerg#ifndef TIERED 27725944Sjoerg COMPILER1_PRESENT(ShouldNotReachHere();) 27825944Sjoerg#if INCLUDE_JVMCI 27925944Sjoerg if (UseJVMCICompiler) { 28025944Sjoerg ShouldNotReachHere(); 28125944Sjoerg } 28225944Sjoerg#endif 28325944Sjoerg#endif // TIERED 28425944Sjoerg#if defined(COMPILER2) || INCLUDE_JVMCI 28525944Sjoerg DerivedPointerTable::add(derived, base); 28625944Sjoerg#endif // COMPILER2 || INCLUDE_JVMCI 28725944Sjoerg} 28825944Sjoerg 28925944Sjoerg 29025944Sjoerg#ifndef PRODUCT 29125944Sjoergstatic void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) { 29225944Sjoerg // Print oopmap and regmap 29325944Sjoerg tty->print_cr("------ "); 29425944Sjoerg CodeBlob* cb = fr->cb(); 29525944Sjoerg const ImmutableOopMapSet* maps = cb->oop_maps(); 29625944Sjoerg const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc()); 29725944Sjoerg map->print(); 29825944Sjoerg if( cb->is_nmethod() ) { 2994910Swollman nmethod* nm = (nmethod*)cb; 3004910Swollman // native wrappers have no scope data, it is implied 3014910Swollman if (nm->is_native_method()) { 3024910Swollman tty->print("bci: 0 (native)"); 3034910Swollman } else { 30425706Sjoerg ScopeDesc* scope = nm->scope_desc_at(fr->pc()); 30525706Sjoerg tty->print("bci: %d ",scope->bci()); 3064910Swollman } 3074910Swollman } 3084910Swollman tty->cr(); 30911189Sjkh fr->print_on(tty); 31025944Sjoerg tty->print(" "); 31125944Sjoerg cb->print_value_on(tty); tty->cr(); 3124910Swollman reg_map->print(); 3134910Swollman tty->print_cr("------ "); 3144910Swollman 3154910Swollman} 3164910Swollman#endif // PRODUCT 3174910Swollman 3184910Swollmanvoid OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) { 31925944Sjoerg // add derived oops to a table 32025706Sjoerg all_do(fr, reg_map, f, add_derived_oop, &do_nothing); 32125706Sjoerg} 32225706Sjoerg 32325944Sjoerg 32425944Sjoergvoid OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, 32525944Sjoerg OopClosure* oop_fn, void derived_oop_fn(oop*, oop*), 3264910Swollman OopClosure* value_fn) { 3274910Swollman CodeBlob* cb = fr->cb(); 3284910Swollman assert(cb != NULL, "no codeblob"); 3294910Swollman 3304910Swollman NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);) 3314910Swollman 3324910Swollman const ImmutableOopMapSet* maps = cb->oop_maps(); 3334910Swollman const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc()); 3344910Swollman assert(map != NULL, "no ptr map found"); 3354910Swollman 3364910Swollman // handle derived pointers first (otherwise base pointer may be 3374910Swollman // changed before derived pointer offset has been collected) 33811189Sjkh OopMapValue omv; 33925944Sjoerg { 34025706Sjoerg OopMapStream oms(map,OopMapValue::derived_oop_value); 34125706Sjoerg if (!oms.is_done()) { 34225706Sjoerg#ifndef TIERED 34325706Sjoerg COMPILER1_PRESENT(ShouldNotReachHere();) 34425706Sjoerg#if INCLUDE_JVMCI 34511189Sjkh if (UseJVMCICompiler) { 34611189Sjkh ShouldNotReachHere(); 3474910Swollman } 3484910Swollman#endif 34925944Sjoerg#endif // !TIERED 35025944Sjoerg // Protect the operation on the derived pointers. This 35111189Sjkh // protects the addition of derived pointers to the shared 3524910Swollman // derived pointer table in DerivedPointerTable::add(). 35325944Sjoerg MutexLockerEx x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag); 35425706Sjoerg do { 35525706Sjoerg omv = oms.current(); 35625706Sjoerg oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); 35725706Sjoerg guarantee(loc != NULL, "missing saved register"); 35825706Sjoerg oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map); 3594910Swollman oop *derived_loc = loc; 3604910Swollman oop val = *base_loc; 3614910Swollman if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { 36225944Sjoerg // Ignore NULL oops and decoded NULL narrow oops which 3634910Swollman // equal to Universe::narrow_oop_base when a narrow oop 3644910Swollman // implicit null check is used in compiled code. 3654910Swollman // The narrow_oop_base could be NULL or be the address 3664910Swollman // of the page below heap depending on compressed oops mode. 36725944Sjoerg } else { 36825944Sjoerg derived_oop_fn(base_loc, derived_loc); 3694910Swollman } 3704910Swollman oms.next(); 3714910Swollman } while (!oms.is_done()); 37225944Sjoerg } 3734910Swollman } 3744910Swollman 3754910Swollman // We want coop and oop oop_types 3764910Swollman int mask = OopMapValue::oop_value | OopMapValue::narrowoop_value; 3774910Swollman { 37812495Speter for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) { 37912495Speter omv = oms.current(); 38012495Speter oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); 38125944Sjoerg // It should be an error if no location can be found for a 38212495Speter // register mentioned as contained an oop of some kind. Maybe 38312495Speter // this was allowed previously because value_value items might 38412495Speter // be missing? 38512495Speter guarantee(loc != NULL, "missing saved register"); 38612495Speter if ( omv.type() == OopMapValue::oop_value ) { 3874910Swollman oop val = *loc; 3884910Swollman if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { 3894910Swollman // Ignore NULL oops and decoded NULL narrow oops which 39025944Sjoerg // equal to Universe::narrow_oop_base when a narrow oop 3914910Swollman // implicit null check is used in compiled code. 3924910Swollman // The narrow_oop_base could be NULL or be the address 3934910Swollman // of the page below heap depending on compressed oops mode. 3944910Swollman continue; 3954910Swollman } 3964910Swollman#ifdef ASSERT 3974910Swollman if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || 3984910Swollman !Universe::heap()->is_in_or_null(*loc)) { 39925944Sjoerg tty->print_cr("# Found non oop pointer. Dumping state at failure"); 4004910Swollman // try to dump out some helpful debugging information 4014910Swollman trace_codeblob_maps(fr, reg_map); 4024910Swollman omv.print(); 4034910Swollman tty->print_cr("register r"); 4044910Swollman omv.reg()->print(); 4054910Swollman tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc); 4064910Swollman // do the real assert. 4074910Swollman assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer"); 4084910Swollman } 4094910Swollman#endif // ASSERT 41011189Sjkh oop_fn->do_oop(loc); 41125944Sjoerg } else if ( omv.type() == OopMapValue::narrowoop_value ) { 41225706Sjoerg narrowOop *nl = (narrowOop*)loc; 41325706Sjoerg#ifndef VM_LITTLE_ENDIAN 41425706Sjoerg VMReg vmReg = omv.reg(); 41525706Sjoerg // Don't do this on SPARC float registers as they can be individually addressed 41625706Sjoerg if (!vmReg->is_stack() SPARC_ONLY(&& !vmReg->is_FloatRegister())) { 41711189Sjkh // compressed oops in registers only take up 4 bytes of an 41811189Sjkh // 8 byte register but they are in the wrong part of the 4194910Swollman // word so adjust loc to point at the right place. 4204910Swollman nl = (narrowOop*)((address)nl + 4); 4214910Swollman } 4224910Swollman#endif 4234910Swollman oop_fn->do_oop(nl); 4244910Swollman } 4254910Swollman } 4264910Swollman } 4274910Swollman} 4284910Swollman 4294910Swollman 4304910Swollman// Update callee-saved register info for the following frame 4314910Swollmanvoid OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) { 4324910Swollman ResourceMark rm; 43312495Speter CodeBlob* cb = fr->cb(); 43412495Speter assert(cb != NULL, "no codeblob"); 43512495Speter 43612495Speter // Any reg might be saved by a safepoint handler (see generate_handler_blob). 43712495Speter assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id), 43812495Speter "already updated this map; do not 'update' it twice!" ); 4394910Swollman debug_only(reg_map->_update_for_id = fr->id()); 4404910Swollman 4414910Swollman // Check if caller must update oop argument 4424910Swollman assert((reg_map->include_argument_oops() || 4434910Swollman !cb->caller_must_gc_arguments(reg_map->thread())), 4444910Swollman "include_argument_oops should already be set"); 4454910Swollman 4464910Swollman // Scan through oopmap and find location of all callee-saved registers 44725944Sjoerg // (we do not do update in place, since info could be overwritten) 44825944Sjoerg 44925944Sjoerg address pc = fr->pc(); 45025944Sjoerg const ImmutableOopMap* map = cb->oop_map_for_return_address(pc); 45125944Sjoerg assert(map != NULL, "no ptr map found"); 45225944Sjoerg DEBUG_ONLY(int nof_callee = 0;) 45325944Sjoerg 45425944Sjoerg for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) { 45525944Sjoerg OopMapValue omv = oms.current(); 4564910Swollman VMReg reg = omv.content_reg(); 4574910Swollman oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map); 4584910Swollman reg_map->set_location(reg, (address) loc); 4594910Swollman DEBUG_ONLY(nof_callee++;) 4604910Swollman } 4614910Swollman 46225944Sjoerg // Check that runtime stubs save all callee-saved registers 4634910Swollman#ifdef COMPILER2 4644910Swollman assert(cb->is_compiled_by_c1() || cb->is_compiled_by_jvmci() || !cb->is_runtime_stub() || 46525944Sjoerg (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT), 46625944Sjoerg "must save all"); 46725944Sjoerg#endif // COMPILER2 46825706Sjoerg} 4694910Swollman 4704910Swollman//============================================================================= 4714910Swollman// Non-Product code 47225944Sjoerg 47325944Sjoerg#ifndef PRODUCT 4744910Swollman 4754910Swollmanbool ImmutableOopMap::has_derived_pointer() const { 4764910Swollman#ifndef TIERED 4774910Swollman COMPILER1_PRESENT(return false); 4784910Swollman#if INCLUDE_JVMCI 47912820Sphk if (UseJVMCICompiler) { 48025706Sjoerg return false; 48125706Sjoerg } 4824910Swollman#endif 4834910Swollman#endif // !TIERED 4844910Swollman#if defined(COMPILER2) || INCLUDE_JVMCI 4854910Swollman OopMapStream oms(this,OopMapValue::derived_oop_value); 48625955Sjoerg return oms.is_done(); 4874910Swollman#else 48825944Sjoerg return false; 48925944Sjoerg#endif // COMPILER2 || INCLUDE_JVMCI 49025944Sjoerg} 49125944Sjoerg 4924910Swollman#endif //PRODUCT 4934910Swollman 4944910Swollman// Printing code is present in product build for -XX:+PrintAssembly. 4954910Swollman 4964910Swollmanstatic 49725944Sjoergvoid print_register_type(OopMapValue::oop_types x, VMReg optional, 49825944Sjoerg outputStream* st) { 49925944Sjoerg switch( x ) { 50025944Sjoerg case OopMapValue::oop_value: 50125944Sjoerg st->print("Oop"); 50225944Sjoerg break; 50325944Sjoerg case OopMapValue::narrowoop_value: 50425944Sjoerg st->print("NarrowOop"); 50525944Sjoerg break; 50625944Sjoerg case OopMapValue::callee_saved_value: 50725944Sjoerg st->print("Callers_"); 5084910Swollman optional->print_on(st); 5094910Swollman break; 5104910Swollman case OopMapValue::derived_oop_value: 5114910Swollman st->print("Derived_oop_"); 5124910Swollman optional->print_on(st); 5134910Swollman break; 51412436Speter default: 51512436Speter ShouldNotReachHere(); 51612436Speter } 5174910Swollman} 51812436Speter 51912436Spetervoid OopMapValue::print_on(outputStream* st) const { 52012436Speter reg()->print_on(st); 52112436Speter st->print("="); 52212436Speter print_register_type(type(),content_reg(),st); 52312436Speter st->print(" "); 52412436Speter} 5254910Swollman 5264910Swollmanvoid ImmutableOopMap::print_on(outputStream* st) const { 5274910Swollman OopMapValue omv; 5284910Swollman st->print("ImmutableOopMap{"); 5294910Swollman for(OopMapStream oms(this); !oms.is_done(); oms.next()) { 5304910Swollman omv = oms.current(); 5314910Swollman omv.print_on(st); 5324910Swollman } 5334910Swollman st->print("}"); 53425706Sjoerg} 5354910Swollman 53625944Sjoergvoid OopMap::print_on(outputStream* st) const { 5374910Swollman OopMapValue omv; 5384910Swollman st->print("OopMap{"); 5394910Swollman for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) { 5404910Swollman omv = oms.current(); 5414910Swollman omv.print_on(st); 54228088Skjc } 5434910Swollman st->print("off=%d}", (int) offset()); 5444910Swollman} 5454910Swollman 5464910Swollmanvoid ImmutableOopMapSet::print_on(outputStream* st) const { 5474910Swollman const ImmutableOopMap* last = NULL; 5484910Swollman for (int i = 0; i < _count; ++i) { 5494910Swollman const ImmutableOopMapPair* pair = pair_at(i); 5504910Swollman const ImmutableOopMap* map = pair->get_from(this); 5514910Swollman if (map != last) { 55211189Sjkh st->cr(); 55311189Sjkh map->print_on(st); 55411189Sjkh st->print("pc offsets: "); 55525955Sjoerg } 55625955Sjoerg last = map; 55725955Sjoerg st->print("%d ", pair->pc_offset()); 55825955Sjoerg } 55925955Sjoerg} 56025955Sjoerg 56125955Sjoergvoid OopMapSet::print_on(outputStream* st) const { 56225955Sjoerg int i, len = om_count(); 56325955Sjoerg 56425955Sjoerg st->print_cr("OopMapSet contains %d OopMaps\n",len); 56525955Sjoerg 56625955Sjoerg for( i = 0; i < len; i++) { 56711189Sjkh OopMap* m = at(i); 5684910Swollman st->print_cr("#%d ",i); 5694910Swollman m->print_on(st); 5704910Swollman st->cr(); 5714910Swollman } 5724910Swollman} 5734910Swollman 5744910Swollmanbool OopMap::equals(const OopMap* other) const { 5754910Swollman if (other->_omv_count != _omv_count) { 57611819Sjulian return false; 57712495Speter } 57811819Sjulian if (other->write_stream()->position() != write_stream()->position()) { 57912495Speter return false; 58011819Sjulian } 58111819Sjulian if (memcmp(other->write_stream()->buffer(), write_stream()->buffer(), write_stream()->position()) != 0) { 5824910Swollman return false; 5834910Swollman } 5844910Swollman return true; 5854910Swollman} 5864910Swollman 5874910Swollmanconst ImmutableOopMap* ImmutableOopMapSet::find_map_at_offset(int pc_offset) const { 58812820Sphk ImmutableOopMapPair* pairs = get_pairs(); 5894910Swollman ImmutableOopMapPair* last = NULL; 5904910Swollman 5914910Swollman for (int i = 0; i < _count; ++i) { 59225944Sjoerg if (pairs[i].pc_offset() >= pc_offset) { 5934910Swollman last = &pairs[i]; 5944910Swollman break; 5954910Swollman } 5964910Swollman } 5974910Swollman 5984910Swollman assert(last->pc_offset() == pc_offset, "oopmap not found"); 5994910Swollman return last->get_from(this); 6004910Swollman} 6014910Swollman 6024910Swollmanconst ImmutableOopMap* ImmutableOopMapPair::get_from(const ImmutableOopMapSet* set) const { 6034910Swollman return set->oopmap_at_offset(_oopmap_offset); 60425944Sjoerg} 6054910Swollman 60625955SjoergImmutableOopMap::ImmutableOopMap(const OopMap* oopmap) : _count(oopmap->count()) { 6074910Swollman address addr = data_addr(); 6084910Swollman oopmap->copy_data_to(addr); 6094910Swollman} 6104910Swollman 6114910Swollman#ifdef ASSERT 6124910Swollmanint ImmutableOopMap::nr_of_bytes() const { 6134910Swollman OopMapStream oms(this); 6144910Swollman 6154910Swollman while (!oms.is_done()) { 6164910Swollman oms.next(); 6174910Swollman } 6184910Swollman return sizeof(ImmutableOopMap) + oms.stream_position(); 6194910Swollman} 6204910Swollman#endif 6214910Swollman 62225706SjoergImmutableOopMapBuilder::ImmutableOopMapBuilder(const OopMapSet* set) : _set(set), _new_set(NULL), _empty(NULL), _last(NULL), _empty_offset(-1), _last_offset(-1), _offset(0), _required(-1) { 62325706Sjoerg _mapping = NEW_RESOURCE_ARRAY(Mapping, _set->size()); 6244910Swollman} 6254910Swollman 6264910Swollmanint ImmutableOopMapBuilder::size_for(const OopMap* map) const { 6274910Swollman return align_size_up(sizeof(ImmutableOopMap) + map->data_size(), 8); 6284910Swollman} 62911189Sjkh 6304910Swollmanint ImmutableOopMapBuilder::heap_size() { 6314910Swollman int base = sizeof(ImmutableOopMapSet); 6324910Swollman base = align_size_up(base, 8); 6334910Swollman 6344910Swollman // all of ours pc / offset pairs 6354910Swollman int pairs = _set->size() * sizeof(ImmutableOopMapPair); 6364910Swollman pairs = align_size_up(pairs, 8); 6374910Swollman 63826018Sjoerg for (int i = 0; i < _set->size(); ++i) { 6394910Swollman int size = 0; 6404910Swollman OopMap* map = _set->at(i); 64111189Sjkh 6424910Swollman if (is_empty(map)) { 64325944Sjoerg /* only keep a single empty map in the set */ 64425944Sjoerg if (has_empty()) { 64525944Sjoerg _mapping[i].set(Mapping::OOPMAP_EMPTY, _empty_offset, 0, map, _empty); 64625944Sjoerg } else { 64725944Sjoerg _empty_offset = _offset; 64825944Sjoerg _empty = map; 6494910Swollman size = size_for(map); 6504910Swollman _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map); 65112820Sphk } 65225706Sjoerg } else if (is_last_duplicate(map)) { 6534910Swollman /* if this entry is identical to the previous one, just point it there */ 6544910Swollman _mapping[i].set(Mapping::OOPMAP_DUPLICATE, _last_offset, 0, map, _last); 65525944Sjoerg } else { 6564910Swollman /* not empty, not an identical copy of the previous entry */ 6574910Swollman size = size_for(map); 6584910Swollman _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map); 6594910Swollman _last_offset = _offset; 6604910Swollman _last = map; 6614910Swollman } 6624910Swollman 6634910Swollman assert(_mapping[i]._map == map, "check"); 6644910Swollman _offset += size; 6654910Swollman } 66611189Sjkh 66725944Sjoerg int total = base + pairs + _offset; 66825944Sjoerg DEBUG_ONLY(total += 8); 66925944Sjoerg _required = total; 6704910Swollman return total; 6714910Swollman} 6724910Swollman 6734910Swollmanvoid ImmutableOopMapBuilder::fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set) { 6744910Swollman assert(offset < set->nr_of_bytes(), "check"); 67525706Sjoerg new ((address) pair) ImmutableOopMapPair(map->offset(), offset); 67625706Sjoerg} 6774910Swollman 6784910Swollmanint ImmutableOopMapBuilder::fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set) { 6794910Swollman fill_pair(pair, map, offset, set); 68025944Sjoerg address addr = (address) pair->get_from(_new_set); // location of the ImmutableOopMap 68125944Sjoerg 68226018Sjoerg new (addr) ImmutableOopMap(map); 6834910Swollman return align_size_up(sizeof(ImmutableOopMap) + map->data_size(), 8); 6844910Swollman} 6854910Swollman 68611189Sjkhvoid ImmutableOopMapBuilder::fill(ImmutableOopMapSet* set, int sz) { 68711189Sjkh ImmutableOopMapPair* pairs = set->get_pairs(); 68812820Sphk 68925706Sjoerg for (int i = 0; i < set->count(); ++i) { 69011189Sjkh const OopMap* map = _mapping[i]._map; 69111189Sjkh ImmutableOopMapPair* pair = NULL; 69225944Sjoerg int size = 0; 69311189Sjkh 69425944Sjoerg if (_mapping[i]._kind == Mapping::OOPMAP_NEW) { 69526018Sjoerg size = fill_map(&pairs[i], map, _mapping[i]._offset, set); 69626018Sjoerg } else if (_mapping[i]._kind == Mapping::OOPMAP_DUPLICATE || _mapping[i]._kind == Mapping::OOPMAP_EMPTY) { 69725944Sjoerg fill_pair(&pairs[i], map, _mapping[i]._offset, set); 69811189Sjkh } 69911189Sjkh 70011189Sjkh const ImmutableOopMap* nv = set->find_map_at_offset(map->offset()); 70111189Sjkh assert(memcmp(map->data(), nv->data_addr(), map->data_size()) == 0, "check identity"); 7024910Swollman } 7034910Swollman} 70425706Sjoerg 70525706Sjoerg#ifdef ASSERT 7064910Swollmanvoid ImmutableOopMapBuilder::verify(address buffer, int size, const ImmutableOopMapSet* set) { 7074910Swollman for (int i = 0; i < 8; ++i) { 7084910Swollman assert(buffer[size - 8 + i] == (unsigned char) 0xff, "overwritten memory check"); 70925944Sjoerg } 7104910Swollman 71125944Sjoerg for (int i = 0; i < set->count(); ++i) { 71226018Sjoerg const ImmutableOopMapPair* pair = set->pair_at(i); 71326018Sjoerg assert(pair->oopmap_offset() < set->nr_of_bytes(), "check size"); 71426018Sjoerg const ImmutableOopMap* map = pair->get_from(set); 71526018Sjoerg int nr_of_bytes = map->nr_of_bytes(); 71626018Sjoerg assert(pair->oopmap_offset() + nr_of_bytes <= set->nr_of_bytes(), "check size + size"); 71726018Sjoerg } 71826018Sjoerg} 71926018Sjoerg#endif 72026018Sjoerg 72126018SjoergImmutableOopMapSet* ImmutableOopMapBuilder::generate_into(address buffer) { 72226018Sjoerg DEBUG_ONLY(memset(&buffer[_required-8], 0xff, 8)); 72326018Sjoerg 72426018Sjoerg _new_set = new (buffer) ImmutableOopMapSet(_set, _required); 72526018Sjoerg fill(_new_set, _required); 72626018Sjoerg 72726018Sjoerg DEBUG_ONLY(verify(buffer, _required, _new_set)); 72826018Sjoerg 72926018Sjoerg return _new_set; 73026018Sjoerg} 73126018Sjoerg 73226018SjoergImmutableOopMapSet* ImmutableOopMapBuilder::build() { 73326018Sjoerg _required = heap_size(); 73426018Sjoerg 73526018Sjoerg // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps 7364910Swollman address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, _required, mtCode); 7374910Swollman return generate_into(buffer); 7384910Swollman} 73925944Sjoerg 7404910SwollmanImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) { 74125944Sjoerg ResourceMark mark; 74225944Sjoerg ImmutableOopMapBuilder builder(oopmap_set); 7434910Swollman return builder.build(); 74425944Sjoerg} 74525944Sjoerg 74625944Sjoerg 7474910Swollman//------------------------------DerivedPointerTable--------------------------- 74825944Sjoerg 74925944Sjoerg#if defined(COMPILER2) || INCLUDE_JVMCI 75025944Sjoerg 75125944Sjoergclass DerivedPointerEntry : public CHeapObj<mtCompiler> { 75225944Sjoerg private: 7534910Swollman oop* _location; // Location of derived pointer (also pointing to the base) 75425944Sjoerg intptr_t _offset; // Offset from base pointer 75525944Sjoerg public: 75625944Sjoerg DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; } 75711189Sjkh oop* location() { return _location; } 75825944Sjoerg intptr_t offset() { return _offset; } 75925944Sjoerg}; 76025944Sjoerg 76125944Sjoerg 76225944SjoergGrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL; 76325944Sjoergbool DerivedPointerTable::_active = false; 76425944Sjoerg 76525944Sjoerg 76625944Sjoergvoid DerivedPointerTable::clear() { 76725944Sjoerg // The first time, we create the list. Otherwise it should be 7684910Swollman // empty. If not, then we have probably forgotton to call 7694910Swollman // update_pointers after last GC/Scavenge. 77025944Sjoerg assert (!_active, "should not be active"); 77125944Sjoerg assert(_list == NULL || _list->length() == 0, "table not empty"); 77225944Sjoerg if (_list == NULL) { 77325944Sjoerg _list = new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<DerivedPointerEntry*>(10, true); // Allocated on C heap 77425944Sjoerg } 77525944Sjoerg _active = true; 77625944Sjoerg} 77726018Sjoerg 77826018Sjoerg 77925944Sjoerg// Returns value of location as an int 78026018Sjoergintptr_t value_of_loc(oop *pointer) { return cast_from_oop<intptr_t>((*pointer)); } 7814910Swollman 7824910Swollman 78311189Sjkhvoid DerivedPointerTable::add(oop *derived_loc, oop *base_loc) { 78425944Sjoerg assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop"); 78525944Sjoerg assert(derived_loc != base_loc, "Base and derived in same location"); 78625944Sjoerg if (_active) { 78725944Sjoerg assert(*derived_loc != (oop)base_loc, "location already added"); 78825944Sjoerg assert(_list != NULL, "list must exist"); 78925944Sjoerg intptr_t offset = value_of_loc(derived_loc) - value_of_loc(base_loc); 79025944Sjoerg // This assert is invalid because derived pointers can be 79125944Sjoerg // arbitrarily far away from their base. 7924910Swollman // assert(offset >= -1000000, "wrong derived pointer info"); 79325944Sjoerg 79425944Sjoerg if (TraceDerivedPointers) { 79525944Sjoerg tty->print_cr( 79625944Sjoerg "Add derived pointer@" INTPTR_FORMAT 79725944Sjoerg " - Derived: " INTPTR_FORMAT 79825944Sjoerg " Base: " INTPTR_FORMAT " (@" INTPTR_FORMAT ") (Offset: " INTX_FORMAT ")", 7994910Swollman p2i(derived_loc), p2i((address)*derived_loc), p2i((address)*base_loc), p2i(base_loc), offset 80025944Sjoerg ); 80125944Sjoerg } 80225944Sjoerg // Set derived oop location to point to base. 80325944Sjoerg *derived_loc = (oop)base_loc; 80411189Sjkh assert_lock_strong(DerivedPointerTableGC_lock); 80525944Sjoerg DerivedPointerEntry *entry = new DerivedPointerEntry(derived_loc, offset); 80625944Sjoerg _list->append(entry); 80725944Sjoerg } 80825944Sjoerg} 8094910Swollman 81025944Sjoerg 81125944Sjoergvoid DerivedPointerTable::update_pointers() { 81225944Sjoerg assert(_list != NULL, "list must exist"); 8134910Swollman for(int i = 0; i < _list->length(); i++) { 81411189Sjkh DerivedPointerEntry* entry = _list->at(i); 81525944Sjoerg oop* derived_loc = entry->location(); 81625944Sjoerg intptr_t offset = entry->offset(); 81725944Sjoerg // The derived oop was setup to point to location of base 8184910Swollman oop base = **(oop**)derived_loc; 81925944Sjoerg assert(Universe::heap()->is_in_or_null(base), "must be an oop"); 82025944Sjoerg 8214910Swollman *derived_loc = (oop)(((address)base) + offset); 8224910Swollman assert(value_of_loc(derived_loc) - value_of_loc(&base) == offset, "sanity check"); 82325944Sjoerg 82425944Sjoerg if (TraceDerivedPointers) { 82525944Sjoerg tty->print_cr("Updating derived pointer@" INTPTR_FORMAT 82625944Sjoerg " - Derived: " INTPTR_FORMAT " Base: " INTPTR_FORMAT " (Offset: " INTX_FORMAT ")", 82725944Sjoerg p2i(derived_loc), p2i((address)*derived_loc), p2i((address)base), offset); 8284910Swollman } 8294910Swollman 8304910Swollman // Delete entry 83112820Sphk delete entry; 83225706Sjoerg _list->at_put(i, NULL); 8334910Swollman } 83425944Sjoerg // Clear list, so it is ready for next traversal (this is an invariant) 8354910Swollman if (TraceDerivedPointers && !_list->is_empty()) { 8364910Swollman tty->print_cr("--------------------------"); 8374910Swollman } 83827929Sitojun _list->clear(); 83925706Sjoerg _active = false; 84025706Sjoerg} 84125706Sjoerg 84225706Sjoerg#endif // COMPILER2 || INCLUDE_JVMCI 8434910Swollman