Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/classfile/stackMapFrame.cpp
32285 views
/*1* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/stackMapFrame.hpp"26#include "classfile/verifier.hpp"27#include "memory/resourceArea.hpp"28#include "oops/oop.inline.hpp"29#include "oops/symbol.hpp"30#include "runtime/handles.inline.hpp"31#include "utilities/globalDefinitions.hpp"3233StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* v) :34_offset(0), _locals_size(0), _stack_size(0),35_stack_mark(0), _flags(0), _max_locals(max_locals),36_max_stack(max_stack), _verifier(v) {37Thread* thr = v->thread();38_locals = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_locals);39_stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_stack);40int32_t i;41for(i = 0; i < max_locals; i++) {42_locals[i] = VerificationType::bogus_type();43}44for(i = 0; i < max_stack; i++) {45_stack[i] = VerificationType::bogus_type();46}47}4849StackMapFrame* StackMapFrame::frame_in_exception_handler(u1 flags) {50Thread* thr = _verifier->thread();51VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, 1);52StackMapFrame* frame = new StackMapFrame(_offset, flags, _locals_size, 0, _max_locals, _max_stack, _locals, stack, _verifier);53return frame;54}5556void StackMapFrame::initialize_object(57VerificationType old_object, VerificationType new_object) {58int32_t i;59for (i = 0; i < _max_locals; i++) {60if (_locals[i].equals(old_object)) {61_locals[i] = new_object;62}63}64for (i = 0; i < _stack_size; i++) {65if (_stack[i].equals(old_object)) {66_stack[i] = new_object;67}68}69if (old_object == VerificationType::uninitialized_this_type()) {70// "this" has been initialized - reset flags71_flags = 0;72}73}7475VerificationType StackMapFrame::set_locals_from_arg(76const methodHandle m, VerificationType thisKlass, TRAPS) {77SignatureStream ss(m->signature());78int init_local_num = 0;79if (!m->is_static()) {80init_local_num++;81// add one extra argument for instance method82if (m->name() == vmSymbols::object_initializer_name() &&83thisKlass.name() != vmSymbols::java_lang_Object()) {84_locals[0] = VerificationType::uninitialized_this_type();85_flags |= FLAG_THIS_UNINIT;86} else {87_locals[0] = thisKlass;88}89}9091// local num may be greater than size of parameters because long/double occupies two slots92while(!ss.at_return_type()) {93init_local_num += _verifier->change_sig_to_verificationType(94&ss, &_locals[init_local_num],95CHECK_VERIFY_(verifier(), VerificationType::bogus_type()));96ss.next();97}98_locals_size = init_local_num;99100switch (ss.type()) {101case T_OBJECT:102case T_ARRAY:103{104Symbol* sig = ss.as_symbol(CHECK_(VerificationType::bogus_type()));105// Create another symbol to save as signature stream unreferences106// this symbol.107Symbol* sig_copy =108verifier()->create_temporary_symbol(sig, 0, sig->utf8_length(),109CHECK_(VerificationType::bogus_type()));110assert(sig_copy == sig, "symbols don't match");111return VerificationType::reference_type(sig_copy);112}113case T_INT: return VerificationType::integer_type();114case T_BYTE: return VerificationType::byte_type();115case T_CHAR: return VerificationType::char_type();116case T_SHORT: return VerificationType::short_type();117case T_BOOLEAN: return VerificationType::boolean_type();118case T_FLOAT: return VerificationType::float_type();119case T_DOUBLE: return VerificationType::double_type();120case T_LONG: return VerificationType::long_type();121case T_VOID: return VerificationType::bogus_type();122default:123ShouldNotReachHere();124}125return VerificationType::bogus_type();126}127128void StackMapFrame::copy_locals(const StackMapFrame* src) {129int32_t len = src->locals_size() < _locals_size ?130src->locals_size() : _locals_size;131for (int32_t i = 0; i < len; i++) {132_locals[i] = src->locals()[i];133}134}135136void StackMapFrame::copy_stack(const StackMapFrame* src) {137int32_t len = src->stack_size() < _stack_size ?138src->stack_size() : _stack_size;139for (int32_t i = 0; i < len; i++) {140_stack[i] = src->stack()[i];141}142}143144// Returns the location of the first mismatch, or 'len' if there are no145// mismatches146int StackMapFrame::is_assignable_to(147VerificationType* from, VerificationType* to, int32_t len, TRAPS) const {148int32_t i = 0;149for (i = 0; i < len; i++) {150if (!to[i].is_assignable_from(from[i], verifier(), false, THREAD)) {151break;152}153}154return i;155}156157bool StackMapFrame::is_assignable_to(158const StackMapFrame* target, ErrorContext* ctx, TRAPS) const {159if (_max_locals != target->max_locals()) {160*ctx = ErrorContext::locals_size_mismatch(161_offset, (StackMapFrame*)this, (StackMapFrame*)target);162return false;163}164if (_stack_size != target->stack_size()) {165*ctx = ErrorContext::stack_size_mismatch(166_offset, (StackMapFrame*)this, (StackMapFrame*)target);167return false;168}169// Only need to compare type elements up to target->locals() or target->stack().170// The remaining type elements in this state can be ignored because they are171// assignable to bogus type.172int mismatch_loc;173mismatch_loc = is_assignable_to(174_locals, target->locals(), target->locals_size(), THREAD);175if (mismatch_loc != target->locals_size()) {176*ctx = ErrorContext::bad_type(target->offset(),177TypeOrigin::local(mismatch_loc, (StackMapFrame*)this),178TypeOrigin::sm_local(mismatch_loc, (StackMapFrame*)target));179return false;180}181mismatch_loc = is_assignable_to(_stack, target->stack(), _stack_size, THREAD);182if (mismatch_loc != _stack_size) {183*ctx = ErrorContext::bad_type(target->offset(),184TypeOrigin::stack(mismatch_loc, (StackMapFrame*)this),185TypeOrigin::sm_stack(mismatch_loc, (StackMapFrame*)target));186return false;187}188189if ((_flags | target->flags()) == target->flags()) {190return true;191} else {192*ctx = ErrorContext::bad_flags(target->offset(),193(StackMapFrame*)this, (StackMapFrame*)target);194return false;195}196}197198VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) {199if (_stack_size <= 0) {200verifier()->verify_error(201ErrorContext::stack_underflow(_offset, this),202"Operand stack underflow");203return VerificationType::bogus_type();204}205VerificationType top = _stack[--_stack_size];206bool subtype = type.is_assignable_from(207top, verifier(), false, CHECK_(VerificationType::bogus_type()));208if (!subtype) {209verifier()->verify_error(210ErrorContext::bad_type(_offset, stack_top_ctx(),211TypeOrigin::implicit(type)),212"Bad type on operand stack");213return VerificationType::bogus_type();214}215return top;216}217218VerificationType StackMapFrame::get_local(219int32_t index, VerificationType type, TRAPS) {220if (index >= _max_locals) {221verifier()->verify_error(222ErrorContext::bad_local_index(_offset, index),223"Local variable table overflow");224return VerificationType::bogus_type();225}226bool subtype = type.is_assignable_from(_locals[index],227verifier(), false, CHECK_(VerificationType::bogus_type()));228if (!subtype) {229verifier()->verify_error(230ErrorContext::bad_type(_offset,231TypeOrigin::local(index, this),232TypeOrigin::implicit(type)),233"Bad local variable type");234return VerificationType::bogus_type();235}236if(index >= _locals_size) { _locals_size = index + 1; }237return _locals[index];238}239240void StackMapFrame::get_local_2(241int32_t index, VerificationType type1, VerificationType type2, TRAPS) {242assert(type1.is_long() || type1.is_double(), "must be long/double");243assert(type2.is_long2() || type2.is_double2(), "must be long/double_2");244if (index >= _locals_size - 1) {245verifier()->verify_error(246ErrorContext::bad_local_index(_offset, index),247"get long/double overflows locals");248return;249}250bool subtype = type1.is_assignable_from(_locals[index], verifier(), false, CHECK);251if (!subtype) {252verifier()->verify_error(253ErrorContext::bad_type(_offset,254TypeOrigin::local(index, this), TypeOrigin::implicit(type1)),255"Bad local variable type");256} else {257subtype = type2.is_assignable_from(_locals[index + 1], verifier(), false, CHECK);258if (!subtype) {259/* Unreachable? All local store routines convert a split long or double260* into a TOP during the store. So we should never end up seeing an261* orphaned half. */262verifier()->verify_error(263ErrorContext::bad_type(_offset,264TypeOrigin::local(index + 1, this), TypeOrigin::implicit(type2)),265"Bad local variable type");266}267}268}269270void StackMapFrame::set_local(int32_t index, VerificationType type, TRAPS) {271assert(!type.is_check(), "Must be a real type");272if (index >= _max_locals) {273verifier()->verify_error(274ErrorContext::bad_local_index(_offset, index),275"Local variable table overflow");276return;277}278// If type at index is double or long, set the next location to be unusable279if (_locals[index].is_double() || _locals[index].is_long()) {280assert((index + 1) < _locals_size, "Local variable table overflow");281_locals[index + 1] = VerificationType::bogus_type();282}283// If type at index is double_2 or long_2, set the previous location to be unusable284if (_locals[index].is_double2() || _locals[index].is_long2()) {285assert(index >= 1, "Local variable table underflow");286_locals[index - 1] = VerificationType::bogus_type();287}288_locals[index] = type;289if (index >= _locals_size) {290#ifdef ASSERT291for (int i=_locals_size; i<index; i++) {292assert(_locals[i] == VerificationType::bogus_type(),293"holes must be bogus type");294}295#endif296_locals_size = index + 1;297}298}299300void StackMapFrame::set_local_2(301int32_t index, VerificationType type1, VerificationType type2, TRAPS) {302assert(type1.is_long() || type1.is_double(), "must be long/double");303assert(type2.is_long2() || type2.is_double2(), "must be long/double_2");304if (index >= _max_locals - 1) {305verifier()->verify_error(306ErrorContext::bad_local_index(_offset, index),307"Local variable table overflow");308return;309}310// If type at index+1 is double or long, set the next location to be unusable311if (_locals[index+1].is_double() || _locals[index+1].is_long()) {312assert((index + 2) < _locals_size, "Local variable table overflow");313_locals[index + 2] = VerificationType::bogus_type();314}315// If type at index is double_2 or long_2, set the previous location to be unusable316if (_locals[index].is_double2() || _locals[index].is_long2()) {317assert(index >= 1, "Local variable table underflow");318_locals[index - 1] = VerificationType::bogus_type();319}320_locals[index] = type1;321_locals[index+1] = type2;322if (index >= _locals_size - 1) {323#ifdef ASSERT324for (int i=_locals_size; i<index; i++) {325assert(_locals[i] == VerificationType::bogus_type(),326"holes must be bogus type");327}328#endif329_locals_size = index + 2;330}331}332333TypeOrigin StackMapFrame::stack_top_ctx() {334return TypeOrigin::stack(_stack_size, this);335}336337void StackMapFrame::print_on(outputStream* str) const {338str->indent().print_cr("bci: @%d", _offset);339str->indent().print_cr("flags: {%s }",340flag_this_uninit() ? " flagThisUninit" : "");341str->indent().print("locals: {");342for (int32_t i = 0; i < _locals_size; ++i) {343str->print(" ");344_locals[i].print_on(str);345if (i != _locals_size - 1) {346str->print(",");347}348}349str->print_cr(" }");350str->indent().print("stack: {");351for (int32_t j = 0; j < _stack_size; ++j) {352str->print(" ");353_stack[j].print_on(str);354if (j != _stack_size - 1) {355str->print(",");356}357}358str->print_cr(" }");359}360361362