1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/prims/methodComparator.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,445 @@ 1.4 +/* 1.5 + * Copyright (c) 2000, 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 "oops/oop.inline.hpp" 1.30 +#include "oops/symbol.hpp" 1.31 +#include "prims/jvmtiRedefineClassesTrace.hpp" 1.32 +#include "prims/methodComparator.hpp" 1.33 +#include "runtime/handles.inline.hpp" 1.34 +#include "utilities/globalDefinitions.hpp" 1.35 + 1.36 +BytecodeStream *MethodComparator::_s_old; 1.37 +BytecodeStream *MethodComparator::_s_new; 1.38 +ConstantPool* MethodComparator::_old_cp; 1.39 +ConstantPool* MethodComparator::_new_cp; 1.40 +BciMap *MethodComparator::_bci_map; 1.41 +bool MethodComparator::_switchable_test; 1.42 +GrowableArray<int> *MethodComparator::_fwd_jmps; 1.43 + 1.44 +bool MethodComparator::methods_EMCP(Method* old_method, Method* new_method) { 1.45 + if (old_method->code_size() != new_method->code_size()) 1.46 + return false; 1.47 + if (check_stack_and_locals_size(old_method, new_method) != 0) { 1.48 + // RC_TRACE macro has an embedded ResourceMark 1.49 + RC_TRACE(0x00800000, ("Methods %s non-comparable with diagnosis %d", 1.50 + old_method->name()->as_C_string(), 1.51 + check_stack_and_locals_size(old_method, new_method))); 1.52 + return false; 1.53 + } 1.54 + 1.55 + _old_cp = old_method->constants(); 1.56 + _new_cp = new_method->constants(); 1.57 + BytecodeStream s_old(old_method); 1.58 + BytecodeStream s_new(new_method); 1.59 + _s_old = &s_old; 1.60 + _s_new = &s_new; 1.61 + _switchable_test = false; 1.62 + Bytecodes::Code c_old, c_new; 1.63 + 1.64 + while ((c_old = s_old.next()) >= 0) { 1.65 + if ((c_new = s_new.next()) < 0 || c_old != c_new) 1.66 + return false; 1.67 + 1.68 + if (! args_same(c_old, c_new)) 1.69 + return false; 1.70 + } 1.71 + return true; 1.72 +} 1.73 + 1.74 + 1.75 +bool MethodComparator::methods_switchable(Method* old_method, Method* new_method, 1.76 + BciMap &bci_map) { 1.77 + if (old_method->code_size() > new_method->code_size()) 1.78 + // Something has definitely been deleted in the new method, compared to the old one. 1.79 + return false; 1.80 + 1.81 + if (! check_stack_and_locals_size(old_method, new_method)) 1.82 + return false; 1.83 + 1.84 + _old_cp = old_method->constants(); 1.85 + _new_cp = new_method->constants(); 1.86 + BytecodeStream s_old(old_method); 1.87 + BytecodeStream s_new(new_method); 1.88 + _s_old = &s_old; 1.89 + _s_new = &s_new; 1.90 + _bci_map = &bci_map; 1.91 + _switchable_test = true; 1.92 + GrowableArray<int> fwd_jmps(16); 1.93 + _fwd_jmps = &fwd_jmps; 1.94 + Bytecodes::Code c_old, c_new; 1.95 + 1.96 + while ((c_old = s_old.next()) >= 0) { 1.97 + if ((c_new = s_new.next()) < 0) 1.98 + return false; 1.99 + if (! (c_old == c_new && args_same(c_old, c_new))) { 1.100 + int old_bci = s_old.bci(); 1.101 + int new_st_bci = s_new.bci(); 1.102 + bool found_match = false; 1.103 + do { 1.104 + c_new = s_new.next(); 1.105 + if (c_new == c_old && args_same(c_old, c_new)) { 1.106 + found_match = true; 1.107 + break; 1.108 + } 1.109 + } while (c_new >= 0); 1.110 + if (! found_match) 1.111 + return false; 1.112 + int new_end_bci = s_new.bci(); 1.113 + bci_map.store_fragment_location(old_bci, new_st_bci, new_end_bci); 1.114 + } 1.115 + } 1.116 + 1.117 + // Now we can test all forward jumps 1.118 + for (int i = 0; i < fwd_jmps.length() / 2; i++) { 1.119 + if (! bci_map.old_and_new_locations_same(fwd_jmps.at(i*2), fwd_jmps.at(i*2+1))) { 1.120 + RC_TRACE(0x00800000, 1.121 + ("Fwd jump miss: old dest = %d, calc new dest = %d, act new dest = %d", 1.122 + fwd_jmps.at(i*2), bci_map.new_bci_for_old(fwd_jmps.at(i*2)), 1.123 + fwd_jmps.at(i*2+1))); 1.124 + return false; 1.125 + } 1.126 + } 1.127 + 1.128 + return true; 1.129 +} 1.130 + 1.131 + 1.132 +bool MethodComparator::args_same(Bytecodes::Code c_old, Bytecodes::Code c_new) { 1.133 + // BytecodeStream returns the correct standard Java bytecodes for various "fast" 1.134 + // bytecode versions, so we don't have to bother about them here.. 1.135 + switch (c_old) { 1.136 + case Bytecodes::_new : // fall through 1.137 + case Bytecodes::_anewarray : // fall through 1.138 + case Bytecodes::_multianewarray : // fall through 1.139 + case Bytecodes::_checkcast : // fall through 1.140 + case Bytecodes::_instanceof : { 1.141 + u2 cpi_old = _s_old->get_index_u2(); 1.142 + u2 cpi_new = _s_new->get_index_u2(); 1.143 + if ((_old_cp->klass_at_noresolve(cpi_old) != _new_cp->klass_at_noresolve(cpi_new))) 1.144 + return false; 1.145 + if (c_old == Bytecodes::_multianewarray && 1.146 + *(jbyte*)(_s_old->bcp() + 3) != *(jbyte*)(_s_new->bcp() + 3)) 1.147 + return false; 1.148 + break; 1.149 + } 1.150 + 1.151 + case Bytecodes::_getstatic : // fall through 1.152 + case Bytecodes::_putstatic : // fall through 1.153 + case Bytecodes::_getfield : // fall through 1.154 + case Bytecodes::_putfield : // fall through 1.155 + case Bytecodes::_invokevirtual : // fall through 1.156 + case Bytecodes::_invokespecial : // fall through 1.157 + case Bytecodes::_invokestatic : // fall through 1.158 + case Bytecodes::_invokeinterface : { 1.159 + int cpci_old = _s_old->get_index_u2_cpcache(); 1.160 + int cpci_new = _s_new->get_index_u2_cpcache(); 1.161 + // Check if the names of classes, field/method names and signatures at these indexes 1.162 + // are the same. Indices which are really into constantpool cache (rather than constant 1.163 + // pool itself) are accepted by the constantpool query routines below. 1.164 + if ((_old_cp->klass_ref_at_noresolve(cpci_old) != _new_cp->klass_ref_at_noresolve(cpci_new)) || 1.165 + (_old_cp->name_ref_at(cpci_old) != _new_cp->name_ref_at(cpci_new)) || 1.166 + (_old_cp->signature_ref_at(cpci_old) != _new_cp->signature_ref_at(cpci_new))) 1.167 + return false; 1.168 + break; 1.169 + } 1.170 + case Bytecodes::_invokedynamic: { 1.171 + int cpci_old = _s_old->get_index_u4(); 1.172 + int cpci_new = _s_new->get_index_u4(); 1.173 + 1.174 + // Check if the names of classes, field/method names and signatures at these indexes 1.175 + // are the same. Indices which are really into constantpool cache (rather than constant 1.176 + // pool itself) are accepted by the constantpool query routines below. 1.177 + if ((_old_cp->name_ref_at(cpci_old) != _new_cp->name_ref_at(cpci_new)) || 1.178 + (_old_cp->signature_ref_at(cpci_old) != _new_cp->signature_ref_at(cpci_new))) 1.179 + return false; 1.180 + 1.181 + // Translate object indexes to constant pool cache indexes. 1.182 + cpci_old = _old_cp->invokedynamic_cp_cache_index(cpci_old); 1.183 + cpci_new = _new_cp->invokedynamic_cp_cache_index(cpci_new); 1.184 + 1.185 + int cpi_old = _old_cp->cache()->entry_at(cpci_old)->constant_pool_index(); 1.186 + int cpi_new = _new_cp->cache()->entry_at(cpci_new)->constant_pool_index(); 1.187 + int bsm_old = _old_cp->invoke_dynamic_bootstrap_method_ref_index_at(cpi_old); 1.188 + int bsm_new = _new_cp->invoke_dynamic_bootstrap_method_ref_index_at(cpi_new); 1.189 + if (!pool_constants_same(bsm_old, bsm_new)) 1.190 + return false; 1.191 + int cnt_old = _old_cp->invoke_dynamic_argument_count_at(cpi_old); 1.192 + int cnt_new = _new_cp->invoke_dynamic_argument_count_at(cpi_new); 1.193 + if (cnt_old != cnt_new) 1.194 + return false; 1.195 + for (int arg_i = 0; arg_i < cnt_old; arg_i++) { 1.196 + int idx_old = _old_cp->invoke_dynamic_argument_index_at(cpi_old, arg_i); 1.197 + int idx_new = _new_cp->invoke_dynamic_argument_index_at(cpi_new, arg_i); 1.198 + if (!pool_constants_same(idx_old, idx_new)) 1.199 + return false; 1.200 + } 1.201 + break; 1.202 + } 1.203 + 1.204 + case Bytecodes::_ldc : // fall through 1.205 + case Bytecodes::_ldc_w : { 1.206 + Bytecode_loadconstant ldc_old(_s_old->method(), _s_old->bci()); 1.207 + Bytecode_loadconstant ldc_new(_s_new->method(), _s_new->bci()); 1.208 + int cpi_old = ldc_old.pool_index(); 1.209 + int cpi_new = ldc_new.pool_index(); 1.210 + if (!pool_constants_same(cpi_old, cpi_new)) 1.211 + return false; 1.212 + break; 1.213 + } 1.214 + 1.215 + case Bytecodes::_ldc2_w : { 1.216 + u2 cpi_old = _s_old->get_index_u2(); 1.217 + u2 cpi_new = _s_new->get_index_u2(); 1.218 + constantTag tag_old = _old_cp->tag_at(cpi_old); 1.219 + constantTag tag_new = _new_cp->tag_at(cpi_new); 1.220 + if (tag_old.value() != tag_new.value()) 1.221 + return false; 1.222 + if (tag_old.is_long()) { 1.223 + if (_old_cp->long_at(cpi_old) != _new_cp->long_at(cpi_new)) 1.224 + return false; 1.225 + } else { 1.226 + // Use jlong_cast to compare the bits rather than numerical values. 1.227 + // This makes a difference for NaN constants. 1.228 + if (jlong_cast(_old_cp->double_at(cpi_old)) != jlong_cast(_new_cp->double_at(cpi_new))) 1.229 + return false; 1.230 + } 1.231 + break; 1.232 + } 1.233 + 1.234 + case Bytecodes::_bipush : 1.235 + if (_s_old->bcp()[1] != _s_new->bcp()[1]) 1.236 + return false; 1.237 + break; 1.238 + 1.239 + case Bytecodes::_sipush : 1.240 + if (_s_old->get_index_u2() != _s_new->get_index_u2()) 1.241 + return false; 1.242 + break; 1.243 + 1.244 + case Bytecodes::_aload : // fall through 1.245 + case Bytecodes::_astore : // fall through 1.246 + case Bytecodes::_dload : // fall through 1.247 + case Bytecodes::_dstore : // fall through 1.248 + case Bytecodes::_fload : // fall through 1.249 + case Bytecodes::_fstore : // fall through 1.250 + case Bytecodes::_iload : // fall through 1.251 + case Bytecodes::_istore : // fall through 1.252 + case Bytecodes::_lload : // fall through 1.253 + case Bytecodes::_lstore : // fall through 1.254 + case Bytecodes::_ret : 1.255 + if (_s_old->is_wide() != _s_new->is_wide()) 1.256 + return false; 1.257 + if (_s_old->get_index() != _s_new->get_index()) 1.258 + return false; 1.259 + break; 1.260 + 1.261 + case Bytecodes::_goto : // fall through 1.262 + case Bytecodes::_if_acmpeq : // fall through 1.263 + case Bytecodes::_if_acmpne : // fall through 1.264 + case Bytecodes::_if_icmpeq : // fall through 1.265 + case Bytecodes::_if_icmpne : // fall through 1.266 + case Bytecodes::_if_icmplt : // fall through 1.267 + case Bytecodes::_if_icmpge : // fall through 1.268 + case Bytecodes::_if_icmpgt : // fall through 1.269 + case Bytecodes::_if_icmple : // fall through 1.270 + case Bytecodes::_ifeq : // fall through 1.271 + case Bytecodes::_ifne : // fall through 1.272 + case Bytecodes::_iflt : // fall through 1.273 + case Bytecodes::_ifge : // fall through 1.274 + case Bytecodes::_ifgt : // fall through 1.275 + case Bytecodes::_ifle : // fall through 1.276 + case Bytecodes::_ifnonnull : // fall through 1.277 + case Bytecodes::_ifnull : // fall through 1.278 + case Bytecodes::_jsr : { 1.279 + int old_ofs = _s_old->bytecode().get_offset_s2(c_old); 1.280 + int new_ofs = _s_new->bytecode().get_offset_s2(c_new); 1.281 + if (_switchable_test) { 1.282 + int old_dest = _s_old->bci() + old_ofs; 1.283 + int new_dest = _s_new->bci() + new_ofs; 1.284 + if (old_ofs < 0 && new_ofs < 0) { 1.285 + if (! _bci_map->old_and_new_locations_same(old_dest, new_dest)) 1.286 + return false; 1.287 + } else if (old_ofs > 0 && new_ofs > 0) { 1.288 + _fwd_jmps->append(old_dest); 1.289 + _fwd_jmps->append(new_dest); 1.290 + } else { 1.291 + return false; 1.292 + } 1.293 + } else { 1.294 + if (old_ofs != new_ofs) 1.295 + return false; 1.296 + } 1.297 + break; 1.298 + } 1.299 + 1.300 + case Bytecodes::_iinc : 1.301 + if (_s_old->is_wide() != _s_new->is_wide()) 1.302 + return false; 1.303 + if (! _s_old->is_wide()) { 1.304 + // We could use get_index_u1 and get_constant_u1, but it's simpler to grab both bytes at once: 1.305 + if (Bytes::get_Java_u2(_s_old->bcp() + 1) != Bytes::get_Java_u2(_s_new->bcp() + 1)) 1.306 + return false; 1.307 + } else { 1.308 + // We could use get_index_u2 and get_constant_u2, but it's simpler to grab all four bytes at once: 1.309 + if (Bytes::get_Java_u4(_s_old->bcp() + 1) != Bytes::get_Java_u4(_s_new->bcp() + 1)) 1.310 + return false; 1.311 + } 1.312 + break; 1.313 + 1.314 + case Bytecodes::_goto_w : // fall through 1.315 + case Bytecodes::_jsr_w : { 1.316 + int old_ofs = _s_old->bytecode().get_offset_s4(c_old); 1.317 + int new_ofs = _s_new->bytecode().get_offset_s4(c_new); 1.318 + if (_switchable_test) { 1.319 + int old_dest = _s_old->bci() + old_ofs; 1.320 + int new_dest = _s_new->bci() + new_ofs; 1.321 + if (old_ofs < 0 && new_ofs < 0) { 1.322 + if (! _bci_map->old_and_new_locations_same(old_dest, new_dest)) 1.323 + return false; 1.324 + } else if (old_ofs > 0 && new_ofs > 0) { 1.325 + _fwd_jmps->append(old_dest); 1.326 + _fwd_jmps->append(new_dest); 1.327 + } else { 1.328 + return false; 1.329 + } 1.330 + } else { 1.331 + if (old_ofs != new_ofs) 1.332 + return false; 1.333 + } 1.334 + break; 1.335 + } 1.336 + 1.337 + case Bytecodes::_lookupswitch : // fall through 1.338 + case Bytecodes::_tableswitch : { 1.339 + if (_switchable_test) { 1.340 + address aligned_bcp_old = (address) round_to((intptr_t)_s_old->bcp() + 1, jintSize); 1.341 + address aligned_bcp_new = (address) round_to((intptr_t)_s_new->bcp() + 1, jintSize); 1.342 + int default_old = (int) Bytes::get_Java_u4(aligned_bcp_old); 1.343 + int default_new = (int) Bytes::get_Java_u4(aligned_bcp_new); 1.344 + _fwd_jmps->append(_s_old->bci() + default_old); 1.345 + _fwd_jmps->append(_s_new->bci() + default_new); 1.346 + if (c_old == Bytecodes::_lookupswitch) { 1.347 + int npairs_old = (int) Bytes::get_Java_u4(aligned_bcp_old + jintSize); 1.348 + int npairs_new = (int) Bytes::get_Java_u4(aligned_bcp_new + jintSize); 1.349 + if (npairs_old != npairs_new) 1.350 + return false; 1.351 + for (int i = 0; i < npairs_old; i++) { 1.352 + int match_old = (int) Bytes::get_Java_u4(aligned_bcp_old + (2+2*i)*jintSize); 1.353 + int match_new = (int) Bytes::get_Java_u4(aligned_bcp_new + (2+2*i)*jintSize); 1.354 + if (match_old != match_new) 1.355 + return false; 1.356 + int ofs_old = (int) Bytes::get_Java_u4(aligned_bcp_old + (2+2*i+1)*jintSize); 1.357 + int ofs_new = (int) Bytes::get_Java_u4(aligned_bcp_new + (2+2*i+1)*jintSize); 1.358 + _fwd_jmps->append(_s_old->bci() + ofs_old); 1.359 + _fwd_jmps->append(_s_new->bci() + ofs_new); 1.360 + } 1.361 + } else if (c_old == Bytecodes::_tableswitch) { 1.362 + int lo_old = (int) Bytes::get_Java_u4(aligned_bcp_old + jintSize); 1.363 + int lo_new = (int) Bytes::get_Java_u4(aligned_bcp_new + jintSize); 1.364 + if (lo_old != lo_new) 1.365 + return false; 1.366 + int hi_old = (int) Bytes::get_Java_u4(aligned_bcp_old + 2*jintSize); 1.367 + int hi_new = (int) Bytes::get_Java_u4(aligned_bcp_new + 2*jintSize); 1.368 + if (hi_old != hi_new) 1.369 + return false; 1.370 + for (int i = 0; i < hi_old - lo_old + 1; i++) { 1.371 + int ofs_old = (int) Bytes::get_Java_u4(aligned_bcp_old + (3+i)*jintSize); 1.372 + int ofs_new = (int) Bytes::get_Java_u4(aligned_bcp_new + (3+i)*jintSize); 1.373 + _fwd_jmps->append(_s_old->bci() + ofs_old); 1.374 + _fwd_jmps->append(_s_new->bci() + ofs_new); 1.375 + } 1.376 + } 1.377 + } else { // !_switchable_test, can use fast rough compare 1.378 + int len_old = _s_old->instruction_size(); 1.379 + int len_new = _s_new->instruction_size(); 1.380 + if (len_old != len_new) 1.381 + return false; 1.382 + if (memcmp(_s_old->bcp(), _s_new->bcp(), len_old) != 0) 1.383 + return false; 1.384 + } 1.385 + break; 1.386 + } 1.387 + } 1.388 + 1.389 + return true; 1.390 +} 1.391 + 1.392 +bool MethodComparator::pool_constants_same(int cpi_old, int cpi_new) { 1.393 + constantTag tag_old = _old_cp->tag_at(cpi_old); 1.394 + constantTag tag_new = _new_cp->tag_at(cpi_new); 1.395 + if (tag_old.is_int() || tag_old.is_float()) { 1.396 + if (tag_old.value() != tag_new.value()) 1.397 + return false; 1.398 + if (tag_old.is_int()) { 1.399 + if (_old_cp->int_at(cpi_old) != _new_cp->int_at(cpi_new)) 1.400 + return false; 1.401 + } else { 1.402 + // Use jint_cast to compare the bits rather than numerical values. 1.403 + // This makes a difference for NaN constants. 1.404 + if (jint_cast(_old_cp->float_at(cpi_old)) != jint_cast(_new_cp->float_at(cpi_new))) 1.405 + return false; 1.406 + } 1.407 + } else if (tag_old.is_string() && tag_new.is_string()) { 1.408 + if (strcmp(_old_cp->string_at_noresolve(cpi_old), 1.409 + _new_cp->string_at_noresolve(cpi_new)) != 0) 1.410 + return false; 1.411 + } else if (tag_old.is_klass() || tag_old.is_unresolved_klass()) { 1.412 + // tag_old should be klass - 4881222 1.413 + if (! (tag_new.is_unresolved_klass() || tag_new.is_klass())) 1.414 + return false; 1.415 + if (_old_cp->klass_at_noresolve(cpi_old) != 1.416 + _new_cp->klass_at_noresolve(cpi_new)) 1.417 + return false; 1.418 + } else if (tag_old.is_method_type() && tag_new.is_method_type()) { 1.419 + int mti_old = _old_cp->method_type_index_at(cpi_old); 1.420 + int mti_new = _new_cp->method_type_index_at(cpi_new); 1.421 + if ((_old_cp->symbol_at(mti_old) != _new_cp->symbol_at(mti_new))) 1.422 + return false; 1.423 + } else if (tag_old.is_method_handle() && tag_new.is_method_handle()) { 1.424 + if (_old_cp->method_handle_ref_kind_at(cpi_old) != 1.425 + _new_cp->method_handle_ref_kind_at(cpi_new)) 1.426 + return false; 1.427 + int mhi_old = _old_cp->method_handle_index_at(cpi_old); 1.428 + int mhi_new = _new_cp->method_handle_index_at(cpi_new); 1.429 + if ((_old_cp->uncached_klass_ref_at_noresolve(mhi_old) != _new_cp->uncached_klass_ref_at_noresolve(mhi_new)) || 1.430 + (_old_cp->uncached_name_ref_at(mhi_old) != _new_cp->uncached_name_ref_at(mhi_new)) || 1.431 + (_old_cp->uncached_signature_ref_at(mhi_old) != _new_cp->uncached_signature_ref_at(mhi_new))) 1.432 + return false; 1.433 + } else { 1.434 + return false; // unknown tag 1.435 + } 1.436 + return true; 1.437 +} 1.438 + 1.439 + 1.440 +int MethodComparator::check_stack_and_locals_size(Method* old_method, Method* new_method) { 1.441 + if (old_method->max_stack() != new_method->max_stack()) { 1.442 + return 1; 1.443 + } else if (old_method->max_locals() != new_method->max_locals()) { 1.444 + return 2; 1.445 + } else if (old_method->size_of_parameters() != new_method->size_of_parameters()) { 1.446 + return 3; 1.447 + } else return 0; 1.448 +}