Path: blob/master/src/hotspot/share/code/exceptionHandlerTable.cpp
40930 views
/*1* Copyright (c) 1998, 2021, 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 "code/exceptionHandlerTable.hpp"26#include "code/nmethod.hpp"27#include "memory/allocation.inline.hpp"2829void ExceptionHandlerTable::add_entry(HandlerTableEntry entry) {30_nesting.check();31if (_length >= _size) {32// not enough space => grow the table (amortized growth, double its size)33guarantee(_size > 0, "no space allocated => cannot grow the table since it is part of nmethod");34int new_size = _size * 2;35_table = REALLOC_RESOURCE_ARRAY(HandlerTableEntry, _table, _size, new_size);36_size = new_size;37}38assert(_length < _size, "sanity check");39_table[_length++] = entry;40}414243HandlerTableEntry* ExceptionHandlerTable::subtable_for(int catch_pco) const {44int i = 0;45while (i < _length) {46HandlerTableEntry* t = _table + i;47if (t->pco() == catch_pco) {48// found subtable matching the catch_pco49return t;50} else {51// advance to next subtable52i += t->len() + 1; // +1 for header53}54}55return NULL;56}575859ExceptionHandlerTable::ExceptionHandlerTable(int initial_size) {60guarantee(initial_size > 0, "initial size must be > 0");61_table = NEW_RESOURCE_ARRAY(HandlerTableEntry, initial_size);62_length = 0;63_size = initial_size;64}656667ExceptionHandlerTable::ExceptionHandlerTable(const CompiledMethod* cm) {68_table = (HandlerTableEntry*)cm->handler_table_begin();69_length = cm->handler_table_size() / sizeof(HandlerTableEntry);70_size = 0; // no space allocated by ExeptionHandlerTable!71}727374void ExceptionHandlerTable::add_subtable(75int catch_pco,76GrowableArray<intptr_t>* handler_bcis,77GrowableArray<intptr_t>* scope_depths_from_top_scope,78GrowableArray<intptr_t>* handler_pcos79) {80assert(subtable_for(catch_pco) == NULL, "catch handlers for this catch_pco added twice");81assert(handler_bcis->length() == handler_pcos->length(), "bci & pc table have different length");82assert(scope_depths_from_top_scope == NULL || handler_bcis->length() == scope_depths_from_top_scope->length(), "bci & scope_depths table have different length");83if (handler_bcis->length() > 0) {84// add subtable header85add_entry(HandlerTableEntry(handler_bcis->length(), catch_pco, 0));86// add individual entries87for (int i = 0; i < handler_bcis->length(); i++) {88intptr_t scope_depth = 0;89if (scope_depths_from_top_scope != NULL) {90scope_depth = scope_depths_from_top_scope->at(i);91}92add_entry(HandlerTableEntry(handler_bcis->at(i), handler_pcos->at(i), scope_depth));93assert(entry_for(catch_pco, handler_bcis->at(i), scope_depth)->pco() == handler_pcos->at(i), "entry not added correctly (1)");94assert(entry_for(catch_pco, handler_bcis->at(i), scope_depth)->scope_depth() == scope_depth, "entry not added correctly (2)");95}96}97}9899100void ExceptionHandlerTable::copy_to(CompiledMethod* cm) {101assert(size_in_bytes() == cm->handler_table_size(), "size of space allocated in compiled method incorrect");102copy_bytes_to(cm->handler_table_begin());103}104105void ExceptionHandlerTable::copy_bytes_to(address addr) {106memmove(addr, _table, size_in_bytes());107}108109HandlerTableEntry* ExceptionHandlerTable::entry_for(int catch_pco, int handler_bci, int scope_depth) const {110HandlerTableEntry* t = subtable_for(catch_pco);111if (t != NULL) {112int l = t->len();113while (l-- > 0) {114t++;115if (t->bci() == handler_bci && t->scope_depth() == scope_depth) return t;116}117}118return NULL;119}120121122void ExceptionHandlerTable::print_subtable(HandlerTableEntry* t, address base) const {123int l = t->len();124bool have_base_addr = (base != NULL);125if (have_base_addr) {126tty->print_cr("catch_pco = %d (pc=" INTPTR_FORMAT ", %d entries)", t->pco(), p2i(base + t->pco()), l);127} else {128tty->print_cr("catch_pco = %d (%d entries)", t->pco(), l);129}130while (l-- > 0) {131t++;132if (have_base_addr) {133tty->print_cr(" bci %d at scope depth %d -> pco %d (pc=" INTPTR_FORMAT ")",134t->bci(), t->scope_depth(), t->pco(), p2i(base + t->pco()));135} else {136tty->print_cr(" bci %d at scope depth %d -> pco %d", t->bci(), t->scope_depth(), t->pco());137}138}139}140141142void ExceptionHandlerTable::print(address base) const {143tty->print_cr("ExceptionHandlerTable (size = %d bytes)", size_in_bytes());144int i = 0;145while (i < _length) {146HandlerTableEntry* t = _table + i;147print_subtable(t, base);148// advance to next subtable149i += t->len() + 1; // +1 for header150}151}152153void ExceptionHandlerTable::print_subtable_for(int catch_pco) const {154HandlerTableEntry* subtable = subtable_for(catch_pco);155156if( subtable != NULL ) { print_subtable( subtable ); }157}158159// ----------------------------------------------------------------------------160// Implicit null exception tables. Maps an exception PC offset to a161// continuation PC offset. During construction it's a variable sized162// array with a max size and current length. When stored inside an163// nmethod a zero length table takes no space. This is detected by164// nul_chk_table_size() == 0. Otherwise the table has a length word165// followed by pairs of <excp-offset, const-offset>.166void ImplicitExceptionTable::set_size( uint size ) {167_size = size;168_data = NEW_RESOURCE_ARRAY(implicit_null_entry, (size*2));169_len = 0;170}171172void ImplicitExceptionTable::append( uint exec_off, uint cont_off ) {173assert( (sizeof(implicit_null_entry) >= 4) || (exec_off < 65535), "" );174assert( (sizeof(implicit_null_entry) >= 4) || (cont_off < 65535), "" );175uint l = len();176if (l == _size) {177uint old_size_in_elements = _size*2;178if (_size == 0) _size = 4;179_size *= 2;180uint new_size_in_elements = _size*2;181_data = REALLOC_RESOURCE_ARRAY(uint, _data, old_size_in_elements, new_size_in_elements);182}183*(adr(l) ) = exec_off;184*(adr(l)+1) = cont_off;185_len = l+1;186};187188uint ImplicitExceptionTable::continuation_offset( uint exec_off ) const {189uint l = len();190for( uint i=0; i<l; i++ )191if( *adr(i) == exec_off )192return *(adr(i)+1);193return 0; // Failed to find any execption offset194}195196void ImplicitExceptionTable::print(address base) const {197const uint n = len();198if (n > 0) {199const uint items_per_line = 3;200uint i;201tty->print_cr("ImplicitExceptionTable (size = %d entries, %d bytes):", n, size_in_bytes());202tty->print("{");203for (i = 0; i < n; i++) {204if (i%items_per_line == 0) {205tty->cr();206tty->fill_to(3);207}208tty->print("< " INTPTR_FORMAT ", " INTPTR_FORMAT " > ", p2i(base + *adr(i)), p2i(base + *(adr(i)+1)));209}210tty->bol();211tty->print_cr("}");212} else {213tty->print_cr("ImplicitExceptionTable is empty");214}215}216217ImplicitExceptionTable::ImplicitExceptionTable(const CompiledMethod* nm) {218if (nm->nul_chk_table_size() == 0) {219_len = 0;220_data = NULL;221} else {222// the first word is the length if non-zero, so read it out and223// skip to the next word to get the table.224_data = (implicit_null_entry*)nm->nul_chk_table_begin();225_len = _data[0];226_data++;227}228_size = len();229assert(size_in_bytes() <= nm->nul_chk_table_size(), "size of space allocated in nmethod incorrect");230}231232void ImplicitExceptionTable::copy_to( nmethod* nm ) {233copy_bytes_to(nm->nul_chk_table_begin(), nm->nul_chk_table_size());234}235236void ImplicitExceptionTable::copy_bytes_to(address addr, int size) {237assert(size_in_bytes() <= size, "size of space allocated in nmethod incorrect");238if (len() != 0) {239implicit_null_entry* nmdata = (implicit_null_entry*)addr;240// store the length in the first uint241nmdata[0] = _len;242nmdata++;243// copy the table after the length244memmove( nmdata, _data, 2 * len() * sizeof(implicit_null_entry));245} else {246// zero length table takes zero bytes247assert(size_in_bytes() == 0, "bad size");248assert(size == 0, "bad size");249}250}251252void ImplicitExceptionTable::verify(nmethod *nm) const {253for (uint i = 0; i < len(); i++) {254if ((*adr(i) > (unsigned int)nm->insts_size()) ||255(*(adr(i)+1) > (unsigned int)nm->insts_size()))256fatal("Invalid offset in ImplicitExceptionTable at " PTR_FORMAT, p2i(_data));257}258}259260261