1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/code/oopRecorder.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,159 @@ 1.4 +/* 1.5 + * Copyright (c) 1998, 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "ci/ciEnv.hpp" 1.30 +#include "ci/ciInstance.hpp" 1.31 +#include "ci/ciMetadata.hpp" 1.32 +#include "code/oopRecorder.hpp" 1.33 +#include "memory/allocation.inline.hpp" 1.34 +#include "oops/oop.inline.hpp" 1.35 + 1.36 +#ifdef ASSERT 1.37 +template <class T> int ValueRecorder<T>::_find_index_calls = 0; 1.38 +template <class T> int ValueRecorder<T>::_hit_indexes = 0; 1.39 +template <class T> int ValueRecorder<T>::_missed_indexes = 0; 1.40 +#endif //ASSERT 1.41 + 1.42 + 1.43 +template <class T> ValueRecorder<T>::ValueRecorder(Arena* arena) { 1.44 + _handles = NULL; 1.45 + _indexes = NULL; 1.46 + _arena = arena; 1.47 + _complete = false; 1.48 +} 1.49 + 1.50 +template <class T> template <class X> ValueRecorder<T>::IndexCache<X>::IndexCache() { 1.51 + assert(first_index > 0, "initial zero state of cache must be invalid index"); 1.52 + Copy::zero_to_bytes(&_cache[0], sizeof(_cache)); 1.53 +} 1.54 + 1.55 +template <class T> int ValueRecorder<T>::size() { 1.56 + _complete = true; 1.57 + if (_handles == NULL) return 0; 1.58 + return _handles->length() * sizeof(T); 1.59 +} 1.60 + 1.61 +template <class T> void ValueRecorder<T>::copy_values_to(nmethod* nm) { 1.62 + assert(_complete, "must be frozen"); 1.63 + maybe_initialize(); // get non-null handles, even if we have no oops 1.64 + nm->copy_values(_handles); 1.65 +} 1.66 + 1.67 +template <class T> void ValueRecorder<T>::maybe_initialize() { 1.68 + if (_handles == NULL) { 1.69 + if (_arena != NULL) { 1.70 + _handles = new(_arena) GrowableArray<T>(_arena, 10, 0, 0); 1.71 + _no_finds = new(_arena) GrowableArray<int>( _arena, 10, 0, 0); 1.72 + } else { 1.73 + _handles = new GrowableArray<T>(10, 0, 0); 1.74 + _no_finds = new GrowableArray<int>( 10, 0, 0); 1.75 + } 1.76 + } 1.77 +} 1.78 + 1.79 + 1.80 +template <class T> T ValueRecorder<T>::at(int index) { 1.81 + // there is always a NULL virtually present as first object 1.82 + if (index == null_index) return NULL; 1.83 + return _handles->at(index - first_index); 1.84 +} 1.85 + 1.86 + 1.87 +template <class T> int ValueRecorder<T>::add_handle(T h, bool make_findable) { 1.88 + assert(!_complete, "cannot allocate more elements after size query"); 1.89 + maybe_initialize(); 1.90 + // indexing uses 1 as an origin--0 means null 1.91 + int index = _handles->length() + first_index; 1.92 + _handles->append(h); 1.93 + 1.94 + // Support correct operation of find_index(). 1.95 + assert(!(make_findable && !is_real(h)), "nulls are not findable"); 1.96 + if (make_findable) { 1.97 + // This index may be returned from find_index(). 1.98 + if (_indexes != NULL) { 1.99 + int* cloc = _indexes->cache_location(h); 1.100 + _indexes->set_cache_location_index(cloc, index); 1.101 + } else if (index == index_cache_threshold && _arena != NULL) { 1.102 + _indexes = new(_arena) IndexCache<T>(); 1.103 + for (int i = 0; i < _handles->length(); i++) { 1.104 + // Load the cache with pre-existing elements. 1.105 + int index0 = i + first_index; 1.106 + if (_no_finds->contains(index0)) continue; 1.107 + int* cloc = _indexes->cache_location(_handles->at(i)); 1.108 + _indexes->set_cache_location_index(cloc, index0); 1.109 + } 1.110 + } 1.111 + } else if (is_real(h)) { 1.112 + // Remember that this index is not to be returned from find_index(). 1.113 + // This case is rare, because most or all uses of allocate_index pass 1.114 + // an argument of NULL or Universe::non_oop_word. 1.115 + // Thus, the expected length of _no_finds is zero. 1.116 + _no_finds->append(index); 1.117 + } 1.118 + 1.119 + return index; 1.120 +} 1.121 + 1.122 + 1.123 +template <class T> int ValueRecorder<T>::maybe_find_index(T h) { 1.124 + debug_only(_find_index_calls++); 1.125 + assert(!_complete, "cannot allocate more elements after size query"); 1.126 + maybe_initialize(); 1.127 + if (h == NULL) return null_index; 1.128 + assert(is_real(h), "must be valid"); 1.129 + int* cloc = (_indexes == NULL)? NULL: _indexes->cache_location(h); 1.130 + if (cloc != NULL) { 1.131 + int cindex = _indexes->cache_location_index(cloc); 1.132 + if (cindex == 0) { 1.133 + return -1; // We know this handle is completely new. 1.134 + } 1.135 + if (cindex >= first_index && _handles->at(cindex - first_index) == h) { 1.136 + debug_only(_hit_indexes++); 1.137 + return cindex; 1.138 + } 1.139 + if (!_indexes->cache_location_collision(cloc)) { 1.140 + return -1; // We know the current cache occupant is unique to that cloc. 1.141 + } 1.142 + } 1.143 + 1.144 + // Not found in cache, due to a cache collision. (Or, no cache at all.) 1.145 + // Do a linear search, most recent to oldest. 1.146 + for (int i = _handles->length() - 1; i >= 0; i--) { 1.147 + if (_handles->at(i) == h) { 1.148 + int findex = i + first_index; 1.149 + if (_no_finds->contains(findex)) continue; // oops; skip this one 1.150 + if (cloc != NULL) { 1.151 + _indexes->set_cache_location_index(cloc, findex); 1.152 + } 1.153 + debug_only(_missed_indexes++); 1.154 + return findex; 1.155 + } 1.156 + } 1.157 + return -1; 1.158 +} 1.159 + 1.160 +// Explicitly instantiate these types 1.161 +template class ValueRecorder<Metadata*>; 1.162 +template class ValueRecorder<jobject>;