1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/classfile/stackMapFrame.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,400 @@ 1.4 +/* 1.5 + * Copyright (c) 2003, 2014, 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 "classfile/stackMapFrame.hpp" 1.30 +#include "classfile/verifier.hpp" 1.31 +#include "memory/resourceArea.hpp" 1.32 +#include "oops/oop.inline.hpp" 1.33 +#include "oops/symbol.hpp" 1.34 +#include "runtime/handles.inline.hpp" 1.35 +#include "utilities/globalDefinitions.hpp" 1.36 + 1.37 +StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* v) : 1.38 + _offset(0), _locals_size(0), _stack_size(0), 1.39 + _stack_mark(0), _flags(0), _max_locals(max_locals), 1.40 + _max_stack(max_stack), _verifier(v) { 1.41 + Thread* thr = v->thread(); 1.42 + _locals = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_locals); 1.43 + _stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_stack); 1.44 + int32_t i; 1.45 + for(i = 0; i < max_locals; i++) { 1.46 + _locals[i] = VerificationType::bogus_type(); 1.47 + } 1.48 + for(i = 0; i < max_stack; i++) { 1.49 + _stack[i] = VerificationType::bogus_type(); 1.50 + } 1.51 +} 1.52 + 1.53 +StackMapFrame* StackMapFrame::frame_in_exception_handler(u1 flags) { 1.54 + Thread* thr = _verifier->thread(); 1.55 + VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, 1); 1.56 + StackMapFrame* frame = new StackMapFrame(_offset, flags, _locals_size, 0, _max_locals, _max_stack, _locals, stack, _verifier); 1.57 + return frame; 1.58 +} 1.59 + 1.60 +void StackMapFrame::initialize_object( 1.61 + VerificationType old_object, VerificationType new_object) { 1.62 + int32_t i; 1.63 + for (i = 0; i < _max_locals; i++) { 1.64 + if (_locals[i].equals(old_object)) { 1.65 + _locals[i] = new_object; 1.66 + } 1.67 + } 1.68 + for (i = 0; i < _stack_size; i++) { 1.69 + if (_stack[i].equals(old_object)) { 1.70 + _stack[i] = new_object; 1.71 + } 1.72 + } 1.73 + if (old_object == VerificationType::uninitialized_this_type()) { 1.74 + // "this" has been initialized - reset flags 1.75 + _flags = 0; 1.76 + } 1.77 +} 1.78 + 1.79 +VerificationType StackMapFrame::set_locals_from_arg( 1.80 + const methodHandle m, VerificationType thisKlass, TRAPS) { 1.81 + SignatureStream ss(m->signature()); 1.82 + int init_local_num = 0; 1.83 + if (!m->is_static()) { 1.84 + init_local_num++; 1.85 + // add one extra argument for instance method 1.86 + if (m->name() == vmSymbols::object_initializer_name() && 1.87 + thisKlass.name() != vmSymbols::java_lang_Object()) { 1.88 + _locals[0] = VerificationType::uninitialized_this_type(); 1.89 + _flags |= FLAG_THIS_UNINIT; 1.90 + } else { 1.91 + _locals[0] = thisKlass; 1.92 + } 1.93 + } 1.94 + 1.95 + // local num may be greater than size of parameters because long/double occupies two slots 1.96 + while(!ss.at_return_type()) { 1.97 + init_local_num += _verifier->change_sig_to_verificationType( 1.98 + &ss, &_locals[init_local_num], 1.99 + CHECK_VERIFY_(verifier(), VerificationType::bogus_type())); 1.100 + ss.next(); 1.101 + } 1.102 + _locals_size = init_local_num; 1.103 + 1.104 + switch (ss.type()) { 1.105 + case T_OBJECT: 1.106 + case T_ARRAY: 1.107 + { 1.108 + Symbol* sig = ss.as_symbol(CHECK_(VerificationType::bogus_type())); 1.109 + // Create another symbol to save as signature stream unreferences 1.110 + // this symbol. 1.111 + Symbol* sig_copy = 1.112 + verifier()->create_temporary_symbol(sig, 0, sig->utf8_length(), 1.113 + CHECK_(VerificationType::bogus_type())); 1.114 + assert(sig_copy == sig, "symbols don't match"); 1.115 + return VerificationType::reference_type(sig_copy); 1.116 + } 1.117 + case T_INT: return VerificationType::integer_type(); 1.118 + case T_BYTE: return VerificationType::byte_type(); 1.119 + case T_CHAR: return VerificationType::char_type(); 1.120 + case T_SHORT: return VerificationType::short_type(); 1.121 + case T_BOOLEAN: return VerificationType::boolean_type(); 1.122 + case T_FLOAT: return VerificationType::float_type(); 1.123 + case T_DOUBLE: return VerificationType::double_type(); 1.124 + case T_LONG: return VerificationType::long_type(); 1.125 + case T_VOID: return VerificationType::bogus_type(); 1.126 + default: 1.127 + ShouldNotReachHere(); 1.128 + } 1.129 + return VerificationType::bogus_type(); 1.130 +} 1.131 + 1.132 +void StackMapFrame::copy_locals(const StackMapFrame* src) { 1.133 + int32_t len = src->locals_size() < _locals_size ? 1.134 + src->locals_size() : _locals_size; 1.135 + for (int32_t i = 0; i < len; i++) { 1.136 + _locals[i] = src->locals()[i]; 1.137 + } 1.138 +} 1.139 + 1.140 +void StackMapFrame::copy_stack(const StackMapFrame* src) { 1.141 + int32_t len = src->stack_size() < _stack_size ? 1.142 + src->stack_size() : _stack_size; 1.143 + for (int32_t i = 0; i < len; i++) { 1.144 + _stack[i] = src->stack()[i]; 1.145 + } 1.146 +} 1.147 + 1.148 +// Returns the location of the first mismatch, or 'len' if there are no 1.149 +// mismatches 1.150 +int StackMapFrame::is_assignable_to( 1.151 + VerificationType* from, VerificationType* to, int32_t len, TRAPS) const { 1.152 + int32_t i = 0; 1.153 + for (i = 0; i < len; i++) { 1.154 + if (!to[i].is_assignable_from(from[i], verifier(), false, THREAD)) { 1.155 + break; 1.156 + } 1.157 + } 1.158 + return i; 1.159 +} 1.160 + 1.161 +bool StackMapFrame::has_flag_match_exception( 1.162 + const StackMapFrame* target) const { 1.163 + // We allow flags of {UninitThis} to assign to {} if-and-only-if the 1.164 + // target frame does not depend upon the current type. 1.165 + // This is slightly too strict, as we need only enforce that the 1.166 + // slots that were initialized by the <init> (the things that were 1.167 + // UninitializedThis before initialize_object() converted them) are unused. 1.168 + // However we didn't save that information so we'll enforce this upon 1.169 + // anything that might have been initialized. This is a rare situation 1.170 + // and javac never generates code that would end up here, but some profilers 1.171 + // (such as NetBeans) might, when adding exception handlers in <init> 1.172 + // methods to cover the invokespecial instruction. See 7020118. 1.173 + 1.174 + assert(max_locals() == target->max_locals() && 1.175 + stack_size() == target->stack_size(), "StackMap sizes must match"); 1.176 + 1.177 + VerificationType top = VerificationType::top_type(); 1.178 + VerificationType this_type = verifier()->current_type(); 1.179 + 1.180 + if (!flag_this_uninit() || target->flags() != 0) { 1.181 + return false; 1.182 + } 1.183 + 1.184 + for (int i = 0; i < target->locals_size(); ++i) { 1.185 + if (locals()[i] == this_type && target->locals()[i] != top) { 1.186 + return false; 1.187 + } 1.188 + } 1.189 + 1.190 + for (int i = 0; i < target->stack_size(); ++i) { 1.191 + if (stack()[i] == this_type && target->stack()[i] != top) { 1.192 + return false; 1.193 + } 1.194 + } 1.195 + 1.196 + return true; 1.197 +} 1.198 + 1.199 +bool StackMapFrame::is_assignable_to( 1.200 + const StackMapFrame* target, bool is_exception_handler, 1.201 + ErrorContext* ctx, TRAPS) const { 1.202 + if (_max_locals != target->max_locals()) { 1.203 + *ctx = ErrorContext::locals_size_mismatch( 1.204 + _offset, (StackMapFrame*)this, (StackMapFrame*)target); 1.205 + return false; 1.206 + } 1.207 + if (_stack_size != target->stack_size()) { 1.208 + *ctx = ErrorContext::stack_size_mismatch( 1.209 + _offset, (StackMapFrame*)this, (StackMapFrame*)target); 1.210 + return false; 1.211 + } 1.212 + // Only need to compare type elements up to target->locals() or target->stack(). 1.213 + // The remaining type elements in this state can be ignored because they are 1.214 + // assignable to bogus type. 1.215 + int mismatch_loc; 1.216 + mismatch_loc = is_assignable_to( 1.217 + _locals, target->locals(), target->locals_size(), THREAD); 1.218 + if (mismatch_loc != target->locals_size()) { 1.219 + *ctx = ErrorContext::bad_type(target->offset(), 1.220 + TypeOrigin::local(mismatch_loc, (StackMapFrame*)this), 1.221 + TypeOrigin::sm_local(mismatch_loc, (StackMapFrame*)target)); 1.222 + return false; 1.223 + } 1.224 + mismatch_loc = is_assignable_to(_stack, target->stack(), _stack_size, THREAD); 1.225 + if (mismatch_loc != _stack_size) { 1.226 + *ctx = ErrorContext::bad_type(target->offset(), 1.227 + TypeOrigin::stack(mismatch_loc, (StackMapFrame*)this), 1.228 + TypeOrigin::sm_stack(mismatch_loc, (StackMapFrame*)target)); 1.229 + return false; 1.230 + } 1.231 + 1.232 + bool match_flags = (_flags | target->flags()) == target->flags(); 1.233 + if (match_flags || is_exception_handler && has_flag_match_exception(target)) { 1.234 + return true; 1.235 + } else { 1.236 + *ctx = ErrorContext::bad_flags(target->offset(), 1.237 + (StackMapFrame*)this, (StackMapFrame*)target); 1.238 + return false; 1.239 + } 1.240 +} 1.241 + 1.242 +VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) { 1.243 + if (_stack_size <= 0) { 1.244 + verifier()->verify_error( 1.245 + ErrorContext::stack_underflow(_offset, this), 1.246 + "Operand stack underflow"); 1.247 + return VerificationType::bogus_type(); 1.248 + } 1.249 + VerificationType top = _stack[--_stack_size]; 1.250 + bool subtype = type.is_assignable_from( 1.251 + top, verifier(), false, CHECK_(VerificationType::bogus_type())); 1.252 + if (!subtype) { 1.253 + verifier()->verify_error( 1.254 + ErrorContext::bad_type(_offset, stack_top_ctx(), 1.255 + TypeOrigin::implicit(type)), 1.256 + "Bad type on operand stack"); 1.257 + return VerificationType::bogus_type(); 1.258 + } 1.259 + return top; 1.260 +} 1.261 + 1.262 +VerificationType StackMapFrame::get_local( 1.263 + int32_t index, VerificationType type, TRAPS) { 1.264 + if (index >= _max_locals) { 1.265 + verifier()->verify_error( 1.266 + ErrorContext::bad_local_index(_offset, index), 1.267 + "Local variable table overflow"); 1.268 + return VerificationType::bogus_type(); 1.269 + } 1.270 + bool subtype = type.is_assignable_from(_locals[index], 1.271 + verifier(), false, CHECK_(VerificationType::bogus_type())); 1.272 + if (!subtype) { 1.273 + verifier()->verify_error( 1.274 + ErrorContext::bad_type(_offset, 1.275 + TypeOrigin::local(index, this), 1.276 + TypeOrigin::implicit(type)), 1.277 + "Bad local variable type"); 1.278 + return VerificationType::bogus_type(); 1.279 + } 1.280 + if(index >= _locals_size) { _locals_size = index + 1; } 1.281 + return _locals[index]; 1.282 +} 1.283 + 1.284 +void StackMapFrame::get_local_2( 1.285 + int32_t index, VerificationType type1, VerificationType type2, TRAPS) { 1.286 + assert(type1.is_long() || type1.is_double(), "must be long/double"); 1.287 + assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); 1.288 + if (index >= _locals_size - 1) { 1.289 + verifier()->verify_error( 1.290 + ErrorContext::bad_local_index(_offset, index), 1.291 + "get long/double overflows locals"); 1.292 + return; 1.293 + } 1.294 + bool subtype = type1.is_assignable_from(_locals[index], verifier(), false, CHECK); 1.295 + if (!subtype) { 1.296 + verifier()->verify_error( 1.297 + ErrorContext::bad_type(_offset, 1.298 + TypeOrigin::local(index, this), TypeOrigin::implicit(type1)), 1.299 + "Bad local variable type"); 1.300 + } else { 1.301 + subtype = type2.is_assignable_from(_locals[index + 1], verifier(), false, CHECK); 1.302 + if (!subtype) { 1.303 + /* Unreachable? All local store routines convert a split long or double 1.304 + * into a TOP during the store. So we should never end up seeing an 1.305 + * orphaned half. */ 1.306 + verifier()->verify_error( 1.307 + ErrorContext::bad_type(_offset, 1.308 + TypeOrigin::local(index + 1, this), TypeOrigin::implicit(type2)), 1.309 + "Bad local variable type"); 1.310 + } 1.311 + } 1.312 +} 1.313 + 1.314 +void StackMapFrame::set_local(int32_t index, VerificationType type, TRAPS) { 1.315 + assert(!type.is_check(), "Must be a real type"); 1.316 + if (index >= _max_locals) { 1.317 + verifier()->verify_error( 1.318 + ErrorContext::bad_local_index(_offset, index), 1.319 + "Local variable table overflow"); 1.320 + return; 1.321 + } 1.322 + // If type at index is double or long, set the next location to be unusable 1.323 + if (_locals[index].is_double() || _locals[index].is_long()) { 1.324 + assert((index + 1) < _locals_size, "Local variable table overflow"); 1.325 + _locals[index + 1] = VerificationType::bogus_type(); 1.326 + } 1.327 + // If type at index is double_2 or long_2, set the previous location to be unusable 1.328 + if (_locals[index].is_double2() || _locals[index].is_long2()) { 1.329 + assert(index >= 1, "Local variable table underflow"); 1.330 + _locals[index - 1] = VerificationType::bogus_type(); 1.331 + } 1.332 + _locals[index] = type; 1.333 + if (index >= _locals_size) { 1.334 +#ifdef ASSERT 1.335 + for (int i=_locals_size; i<index; i++) { 1.336 + assert(_locals[i] == VerificationType::bogus_type(), 1.337 + "holes must be bogus type"); 1.338 + } 1.339 +#endif 1.340 + _locals_size = index + 1; 1.341 + } 1.342 +} 1.343 + 1.344 +void StackMapFrame::set_local_2( 1.345 + int32_t index, VerificationType type1, VerificationType type2, TRAPS) { 1.346 + assert(type1.is_long() || type1.is_double(), "must be long/double"); 1.347 + assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); 1.348 + if (index >= _max_locals - 1) { 1.349 + verifier()->verify_error( 1.350 + ErrorContext::bad_local_index(_offset, index), 1.351 + "Local variable table overflow"); 1.352 + return; 1.353 + } 1.354 + // If type at index+1 is double or long, set the next location to be unusable 1.355 + if (_locals[index+1].is_double() || _locals[index+1].is_long()) { 1.356 + assert((index + 2) < _locals_size, "Local variable table overflow"); 1.357 + _locals[index + 2] = VerificationType::bogus_type(); 1.358 + } 1.359 + // If type at index is double_2 or long_2, set the previous location to be unusable 1.360 + if (_locals[index].is_double2() || _locals[index].is_long2()) { 1.361 + assert(index >= 1, "Local variable table underflow"); 1.362 + _locals[index - 1] = VerificationType::bogus_type(); 1.363 + } 1.364 + _locals[index] = type1; 1.365 + _locals[index+1] = type2; 1.366 + if (index >= _locals_size - 1) { 1.367 +#ifdef ASSERT 1.368 + for (int i=_locals_size; i<index; i++) { 1.369 + assert(_locals[i] == VerificationType::bogus_type(), 1.370 + "holes must be bogus type"); 1.371 + } 1.372 +#endif 1.373 + _locals_size = index + 2; 1.374 + } 1.375 +} 1.376 + 1.377 +TypeOrigin StackMapFrame::stack_top_ctx() { 1.378 + return TypeOrigin::stack(_stack_size, this); 1.379 +} 1.380 + 1.381 +void StackMapFrame::print_on(outputStream* str) const { 1.382 + str->indent().print_cr("bci: @%d", _offset); 1.383 + str->indent().print_cr("flags: {%s }", 1.384 + flag_this_uninit() ? " flagThisUninit" : ""); 1.385 + str->indent().print("locals: {"); 1.386 + for (int32_t i = 0; i < _locals_size; ++i) { 1.387 + str->print(" "); 1.388 + _locals[i].print_on(str); 1.389 + if (i != _locals_size - 1) { 1.390 + str->print(","); 1.391 + } 1.392 + } 1.393 + str->print_cr(" }"); 1.394 + str->indent().print("stack: {"); 1.395 + for (int32_t j = 0; j < _stack_size; ++j) { 1.396 + str->print(" "); 1.397 + _stack[j].print_on(str); 1.398 + if (j != _stack_size - 1) { 1.399 + str->print(","); 1.400 + } 1.401 + } 1.402 + str->print_cr(" }"); 1.403 +}