Path: blob/master/src/hotspot/share/oops/constMethod.cpp
40951 views
/*1* Copyright (c) 2003, 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 "interpreter/interpreter.hpp"26#include "memory/metadataFactory.hpp"27#include "memory/metaspaceClosure.hpp"28#include "memory/resourceArea.hpp"29#include "oops/constMethod.hpp"30#include "oops/method.hpp"31#include "runtime/safepointVerifiers.hpp"32#include "utilities/align.hpp"3334// Static initialization35const u2 ConstMethod::MAX_IDNUM = 0xFFFE;36const u2 ConstMethod::UNSET_IDNUM = 0xFFFF;3738ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,39int byte_code_size,40InlineTableSizes* sizes,41MethodType method_type,42TRAPS) {43int size = ConstMethod::size(byte_code_size, sizes);44return new (loader_data, size, MetaspaceObj::ConstMethodType, THREAD) ConstMethod(45byte_code_size, sizes, method_type, size);46}4748ConstMethod::ConstMethod(int byte_code_size,49InlineTableSizes* sizes,50MethodType method_type,51int size) {5253NoSafepointVerifier no_safepoint;54init_fingerprint();55set_constants(NULL);56set_stackmap_data(NULL);57set_code_size(byte_code_size);58set_constMethod_size(size);59set_inlined_tables_length(sizes); // sets _flags60set_method_type(method_type);61assert(this->size() == size, "wrong size for object");62set_name_index(0);63set_signature_index(0);64set_constants(NULL);65set_max_stack(0);66set_max_locals(0);67set_method_idnum(0);68set_size_of_parameters(0);69set_result_type((BasicType)0);70}7172// Accessor that copies to metadata.73void ConstMethod::copy_stackmap_data(ClassLoaderData* loader_data,74u1* sd, int length, TRAPS) {75_stackmap_data = MetadataFactory::new_array<u1>(loader_data, length, CHECK);76memcpy((void*)_stackmap_data->adr_at(0), (void*)sd, length);77}7879// Deallocate metadata fields associated with ConstMethod*80void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {81if (stackmap_data() != NULL) {82MetadataFactory::free_array<u1>(loader_data, stackmap_data());83}84set_stackmap_data(NULL);8586// deallocate annotation arrays87if (has_method_annotations())88MetadataFactory::free_array<u1>(loader_data, method_annotations());89if (has_parameter_annotations())90MetadataFactory::free_array<u1>(loader_data, parameter_annotations());91if (has_type_annotations())92MetadataFactory::free_array<u1>(loader_data, type_annotations());93if (has_default_annotations())94MetadataFactory::free_array<u1>(loader_data, default_annotations());95}9697// How big must this constMethodObject be?9899int ConstMethod::size(int code_size,100InlineTableSizes* sizes) {101int extra_bytes = code_size;102if (sizes->compressed_linenumber_size() > 0) {103extra_bytes += sizes->compressed_linenumber_size();104}105if (sizes->checked_exceptions_length() > 0) {106extra_bytes += sizeof(u2);107extra_bytes += sizes->checked_exceptions_length() * sizeof(CheckedExceptionElement);108}109if (sizes->localvariable_table_length() > 0) {110extra_bytes += sizeof(u2);111extra_bytes +=112sizes->localvariable_table_length() * sizeof(LocalVariableTableElement);113}114if (sizes->exception_table_length() > 0) {115extra_bytes += sizeof(u2);116extra_bytes += sizes->exception_table_length() * sizeof(ExceptionTableElement);117}118if (sizes->generic_signature_index() != 0) {119extra_bytes += sizeof(u2);120}121// This has to be a less-than-or-equal check, because we might be122// storing information from a zero-length MethodParameters123// attribute. We have to store these, because in some cases, they124// cause the reflection API to throw a MalformedParametersException.125if (sizes->method_parameters_length() >= 0) {126extra_bytes += sizeof(u2);127extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement);128}129130// Align sizes up to a word.131extra_bytes = align_up(extra_bytes, BytesPerWord);132133// One pointer per annotation array134if (sizes->method_annotations_length() > 0) {135extra_bytes += sizeof(AnnotationArray*);136}137if (sizes->parameter_annotations_length() > 0) {138extra_bytes += sizeof(AnnotationArray*);139}140if (sizes->type_annotations_length() > 0) {141extra_bytes += sizeof(AnnotationArray*);142}143if (sizes->default_annotations_length() > 0) {144extra_bytes += sizeof(AnnotationArray*);145}146147int extra_words = align_up(extra_bytes, BytesPerWord) / BytesPerWord;148assert(extra_words == extra_bytes/BytesPerWord, "should already be aligned");149return align_metadata_size(header_size() + extra_words);150}151152Method* ConstMethod::method() const {153return _constants->pool_holder()->method_with_idnum(_method_idnum);154}155156// linenumber table - note that length is unknown until decompression,157// see class CompressedLineNumberReadStream.158159u_char* ConstMethod::compressed_linenumber_table() const {160// Located immediately following the bytecodes.161assert(has_linenumber_table(), "called only if table is present");162return code_end();163}164165// Last short in ConstMethod* before annotations166u2* ConstMethod::last_u2_element() const {167int offset = 0;168if (has_method_annotations()) offset++;169if (has_parameter_annotations()) offset++;170if (has_type_annotations()) offset++;171if (has_default_annotations()) offset++;172return (u2*)((AnnotationArray**)constMethod_end() - offset) - 1;173}174175u2* ConstMethod::generic_signature_index_addr() const {176// Located at the end of the constMethod.177assert(has_generic_signature(), "called only if generic signature exists");178return last_u2_element();179}180181u2* ConstMethod::method_parameters_length_addr() const {182assert(has_method_parameters(), "called only if table is present");183return has_generic_signature() ? (last_u2_element() - 1) :184last_u2_element();185}186187u2* ConstMethod::checked_exceptions_length_addr() const {188// Located immediately before the generic signature index.189assert(has_checked_exceptions(), "called only if table is present");190if(has_method_parameters()) {191// If method parameters present, locate immediately before them.192return (u2*)method_parameters_start() - 1;193} else {194// Else, the exception table is at the end of the constMethod.195return has_generic_signature() ? (last_u2_element() - 1) :196last_u2_element();197}198}199200u2* ConstMethod::exception_table_length_addr() const {201assert(has_exception_handler(), "called only if table is present");202if (has_checked_exceptions()) {203// If checked_exception present, locate immediately before them.204return (u2*) checked_exceptions_start() - 1;205} else {206if(has_method_parameters()) {207// If method parameters present, locate immediately before them.208return (u2*)method_parameters_start() - 1;209} else {210// Else, the exception table is at the end of the constMethod.211return has_generic_signature() ? (last_u2_element() - 1) :212last_u2_element();213}214}215}216217u2* ConstMethod::localvariable_table_length_addr() const {218assert(has_localvariable_table(), "called only if table is present");219if (has_exception_handler()) {220// If exception_table present, locate immediately before them.221return (u2*) exception_table_start() - 1;222} else {223if (has_checked_exceptions()) {224// If checked_exception present, locate immediately before them.225return (u2*) checked_exceptions_start() - 1;226} else {227if(has_method_parameters()) {228// If method parameters present, locate immediately before them.229return (u2*)method_parameters_start() - 1;230} else {231// Else, the exception table is at the end of the constMethod.232return has_generic_signature() ? (last_u2_element() - 1) :233last_u2_element();234}235}236}237}238239// Update the flags to indicate the presence of these optional fields.240void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {241_flags = 0;242if (sizes->compressed_linenumber_size() > 0)243_flags |= _has_linenumber_table;244if (sizes->generic_signature_index() != 0)245_flags |= _has_generic_signature;246if (sizes->method_parameters_length() >= 0)247_flags |= _has_method_parameters;248if (sizes->checked_exceptions_length() > 0)249_flags |= _has_checked_exceptions;250if (sizes->exception_table_length() > 0)251_flags |= _has_exception_table;252if (sizes->localvariable_table_length() > 0)253_flags |= _has_localvariable_table;254255// annotations, they are all pointer sized embedded objects so don't have256// a length embedded also.257if (sizes->method_annotations_length() > 0)258_flags |= _has_method_annotations;259if (sizes->parameter_annotations_length() > 0)260_flags |= _has_parameter_annotations;261if (sizes->type_annotations_length() > 0)262_flags |= _has_type_annotations;263if (sizes->default_annotations_length() > 0)264_flags |= _has_default_annotations;265266// This code is extremely brittle and should possibly be revised.267// The *_length_addr functions walk backwards through the268// constMethod data, using each of the length indexes ahead of them,269// as well as the flags variable. Therefore, the indexes must be270// initialized in reverse order, or else they will compute the wrong271// offsets. Moving the initialization of _flags into a separate272// block solves *half* of the problem, but the following part will273// still break if the order is not exactly right.274//275// Also, the servicability agent needs to be informed anytime276// anything is added here. It might be advisable to have some sort277// of indication of this inline.278if (sizes->generic_signature_index() != 0)279*(generic_signature_index_addr()) = sizes->generic_signature_index();280// New data should probably go here.281if (sizes->method_parameters_length() >= 0)282*(method_parameters_length_addr()) = sizes->method_parameters_length();283if (sizes->checked_exceptions_length() > 0)284*(checked_exceptions_length_addr()) = sizes->checked_exceptions_length();285if (sizes->exception_table_length() > 0)286*(exception_table_length_addr()) = sizes->exception_table_length();287if (sizes->localvariable_table_length() > 0)288*(localvariable_table_length_addr()) = sizes->localvariable_table_length();289}290291int ConstMethod::method_parameters_length() const {292return has_method_parameters() ? *(method_parameters_length_addr()) : -1;293}294295MethodParametersElement* ConstMethod::method_parameters_start() const {296u2* addr = method_parameters_length_addr();297u2 length = *addr;298addr -= length * sizeof(MethodParametersElement) / sizeof(u2);299return (MethodParametersElement*) addr;300}301302303int ConstMethod::checked_exceptions_length() const {304return has_checked_exceptions() ? *(checked_exceptions_length_addr()) : 0;305}306307308CheckedExceptionElement* ConstMethod::checked_exceptions_start() const {309u2* addr = checked_exceptions_length_addr();310u2 length = *addr;311assert(length > 0, "should only be called if table is present");312addr -= length * sizeof(CheckedExceptionElement) / sizeof(u2);313return (CheckedExceptionElement*) addr;314}315316317int ConstMethod::localvariable_table_length() const {318return has_localvariable_table() ? *(localvariable_table_length_addr()) : 0;319}320321322LocalVariableTableElement* ConstMethod::localvariable_table_start() const {323u2* addr = localvariable_table_length_addr();324u2 length = *addr;325assert(length > 0, "should only be called if table is present");326addr -= length * sizeof(LocalVariableTableElement) / sizeof(u2);327return (LocalVariableTableElement*) addr;328}329330int ConstMethod::exception_table_length() const {331return has_exception_handler() ? *(exception_table_length_addr()) : 0;332}333334ExceptionTableElement* ConstMethod::exception_table_start() const {335u2* addr = exception_table_length_addr();336u2 length = *addr;337assert(length > 0, "should only be called if table is present");338addr -= length * sizeof(ExceptionTableElement) / sizeof(u2);339return (ExceptionTableElement*)addr;340}341342AnnotationArray** ConstMethod::method_annotations_addr() const {343assert(has_method_annotations(), "should only be called if method annotations are present");344return (AnnotationArray**)constMethod_end() - 1;345}346347AnnotationArray** ConstMethod::parameter_annotations_addr() const {348assert(has_parameter_annotations(), "should only be called if method parameter annotations are present");349int offset = 1;350if (has_method_annotations()) offset++;351return (AnnotationArray**)constMethod_end() - offset;352}353354AnnotationArray** ConstMethod::type_annotations_addr() const {355assert(has_type_annotations(), "should only be called if method type annotations are present");356int offset = 1;357if (has_method_annotations()) offset++;358if (has_parameter_annotations()) offset++;359return (AnnotationArray**)constMethod_end() - offset;360}361362AnnotationArray** ConstMethod::default_annotations_addr() const {363assert(has_default_annotations(), "should only be called if method default annotations are present");364int offset = 1;365if (has_method_annotations()) offset++;366if (has_parameter_annotations()) offset++;367if (has_type_annotations()) offset++;368return (AnnotationArray**)constMethod_end() - offset;369}370371Array<u1>* copy_annotations(ClassLoaderData* loader_data, AnnotationArray* from, TRAPS) {372int length = from->length();373Array<u1>* a = MetadataFactory::new_array<u1>(loader_data, length, 0, CHECK_NULL);374memcpy((void*)a->adr_at(0), (void*)from->adr_at(0), length);375return a;376}377378// copy annotations from 'cm' to 'this'379// Must make copy because these are deallocated with their constMethod, if redefined.380void ConstMethod::copy_annotations_from(ClassLoaderData* loader_data, ConstMethod* cm, TRAPS) {381Array<u1>* a;382if (cm->has_method_annotations()) {383assert(has_method_annotations(), "should be allocated already");384a = copy_annotations(loader_data, cm->method_annotations(), CHECK);385set_method_annotations(a);386}387if (cm->has_parameter_annotations()) {388assert(has_parameter_annotations(), "should be allocated already");389a = copy_annotations(loader_data, cm->parameter_annotations(), CHECK);390set_parameter_annotations(a);391}392if (cm->has_type_annotations()) {393assert(has_type_annotations(), "should be allocated already");394a = copy_annotations(loader_data, cm->type_annotations(), CHECK);395set_type_annotations(a);396}397if (cm->has_default_annotations()) {398assert(has_default_annotations(), "should be allocated already");399a = copy_annotations(loader_data, cm->default_annotations(), CHECK);400set_default_annotations(a);401}402}403404void ConstMethod::metaspace_pointers_do(MetaspaceClosure* it) {405log_trace(cds)("Iter(ConstMethod): %p", this);406407if (!method()->method_holder()->is_rewritten()) {408it->push(&_constants, MetaspaceClosure::_writable);409} else {410it->push(&_constants);411}412it->push(&_stackmap_data);413if (has_method_annotations()) {414it->push(method_annotations_addr());415}416if (has_parameter_annotations()) {417it->push(parameter_annotations_addr());418}419if (has_type_annotations()) {420it->push(type_annotations_addr());421}422if (has_default_annotations()) {423it->push(default_annotations_addr());424}425}426427// Printing428429void ConstMethod::print_on(outputStream* st) const {430ResourceMark rm;431st->print_cr("%s", internal_name());432Method* m = method();433st->print(" - method: " INTPTR_FORMAT " ", p2i((address)m));434if (m != NULL) {435m->print_value_on(st);436}437st->cr();438if (has_stackmap_table()) {439st->print(" - stackmap data: ");440stackmap_data()->print_value_on(st);441st->cr();442}443}444445// Short version of printing ConstMethod* - just print the name of the446// method it belongs to.447void ConstMethod::print_value_on(outputStream* st) const {448st->print(" const part of method " );449Method* m = method();450if (m != NULL) {451m->print_value_on(st);452} else {453st->print("NULL");454}455}456457// Verification458459void ConstMethod::verify_on(outputStream* st) {460// Verification can occur during oop construction before the method or461// other fields have been initialized.462guarantee(method() != NULL && method()->is_method(), "should be method");463464address m_end = (address)((intptr_t) this + size());465address compressed_table_start = code_end();466guarantee(compressed_table_start <= m_end, "invalid method layout");467address compressed_table_end = compressed_table_start;468// Verify line number table469if (has_linenumber_table()) {470CompressedLineNumberReadStream stream(compressed_linenumber_table());471while (stream.read_pair()) {472guarantee(stream.bci() >= 0 && stream.bci() <= code_size(), "invalid bci in line number table");473}474compressed_table_end += stream.position();475}476guarantee(compressed_table_end <= m_end, "invalid method layout");477// Verify checked exceptions, exception table and local variable tables478if (has_method_parameters()) {479u2* addr = method_parameters_length_addr();480guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");481}482if (has_checked_exceptions()) {483u2* addr = checked_exceptions_length_addr();484guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");485}486if (has_exception_handler()) {487u2* addr = exception_table_length_addr();488guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");489}490if (has_localvariable_table()) {491u2* addr = localvariable_table_length_addr();492guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");493}494// Check compressed_table_end relative to uncompressed_table_start495u2* uncompressed_table_start;496if (has_localvariable_table()) {497uncompressed_table_start = (u2*) localvariable_table_start();498} else if (has_exception_handler()) {499uncompressed_table_start = (u2*) exception_table_start();500} else if (has_checked_exceptions()) {501uncompressed_table_start = (u2*) checked_exceptions_start();502} else if (has_method_parameters()) {503uncompressed_table_start = (u2*) method_parameters_start();504} else {505uncompressed_table_start = (u2*) m_end;506}507int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end;508int max_gap = align_metadata_size(1)*BytesPerWord;509guarantee(gap >= 0 && gap < max_gap, "invalid method layout");510}511512513