Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/oops/constMethod.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 "interpreter/interpreter.hpp"26#include "memory/gcLocker.hpp"27#include "memory/heapInspection.hpp"28#include "memory/metadataFactory.hpp"29#include "oops/constMethod.hpp"30#include "oops/method.hpp"3132// Static initialization33const u2 ConstMethod::MAX_IDNUM = 0xFFFE;34const u2 ConstMethod::UNSET_IDNUM = 0xFFFF;3536ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,37int byte_code_size,38InlineTableSizes* sizes,39MethodType method_type,40TRAPS) {41int size = ConstMethod::size(byte_code_size, sizes);42return new (loader_data, size, true, MetaspaceObj::ConstMethodType, THREAD) ConstMethod(43byte_code_size, sizes, method_type, size);44}4546ConstMethod::ConstMethod(int byte_code_size,47InlineTableSizes* sizes,48MethodType method_type,49int size) {5051No_Safepoint_Verifier no_safepoint;52init_fingerprint();53set_constants(NULL);54set_stackmap_data(NULL);55set_code_size(byte_code_size);56set_constMethod_size(size);57set_inlined_tables_length(sizes); // sets _flags58set_method_type(method_type);59assert(this->size() == size, "wrong size for object");60set_name_index(0);61set_signature_index(0);62set_constants(NULL);63set_max_stack(0);64set_max_locals(0);65set_method_idnum(0);66set_size_of_parameters(0);67set_result_type(T_VOID);68}6970// Accessor that copies to metadata.71void ConstMethod::copy_stackmap_data(ClassLoaderData* loader_data,72u1* sd, int length, TRAPS) {73_stackmap_data = MetadataFactory::new_array<u1>(loader_data, length, CHECK);74memcpy((void*)_stackmap_data->adr_at(0), (void*)sd, length);75}7677// Deallocate metadata fields associated with ConstMethod*78void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {79if (stackmap_data() != NULL) {80MetadataFactory::free_array<u1>(loader_data, stackmap_data());81}82set_stackmap_data(NULL);8384// deallocate annotation arrays85if (has_method_annotations())86MetadataFactory::free_array<u1>(loader_data, method_annotations());87if (has_parameter_annotations())88MetadataFactory::free_array<u1>(loader_data, parameter_annotations());89if (has_type_annotations())90MetadataFactory::free_array<u1>(loader_data, type_annotations());91if (has_default_annotations())92MetadataFactory::free_array<u1>(loader_data, default_annotations());93}9495// How big must this constMethodObject be?9697int ConstMethod::size(int code_size,98InlineTableSizes* sizes) {99int extra_bytes = code_size;100if (sizes->compressed_linenumber_size() > 0) {101extra_bytes += sizes->compressed_linenumber_size();102}103if (sizes->checked_exceptions_length() > 0) {104extra_bytes += sizeof(u2);105extra_bytes += sizes->checked_exceptions_length() * sizeof(CheckedExceptionElement);106}107if (sizes->localvariable_table_length() > 0) {108extra_bytes += sizeof(u2);109extra_bytes +=110sizes->localvariable_table_length() * sizeof(LocalVariableTableElement);111}112if (sizes->exception_table_length() > 0) {113extra_bytes += sizeof(u2);114extra_bytes += sizes->exception_table_length() * sizeof(ExceptionTableElement);115}116if (sizes->generic_signature_index() != 0) {117extra_bytes += sizeof(u2);118}119if (sizes->method_parameters_length() > 0) {120extra_bytes += sizeof(u2);121extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement);122}123124// Align sizes up to a word.125extra_bytes = align_size_up(extra_bytes, BytesPerWord);126127// One pointer per annotation array128if (sizes->method_annotations_length() > 0) {129extra_bytes += sizeof(AnnotationArray*);130}131if (sizes->parameter_annotations_length() > 0) {132extra_bytes += sizeof(AnnotationArray*);133}134if (sizes->type_annotations_length() > 0) {135extra_bytes += sizeof(AnnotationArray*);136}137if (sizes->default_annotations_length() > 0) {138extra_bytes += sizeof(AnnotationArray*);139}140141int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;142assert(extra_words == extra_bytes/BytesPerWord, "should already be aligned");143return align_object_size(header_size() + extra_words);144}145146Method* ConstMethod::method() const {147return _constants->pool_holder()->method_with_idnum(_method_idnum);148}149150// linenumber table - note that length is unknown until decompression,151// see class CompressedLineNumberReadStream.152153u_char* ConstMethod::compressed_linenumber_table() const {154// Located immediately following the bytecodes.155assert(has_linenumber_table(), "called only if table is present");156return code_end();157}158159// Last short in ConstMethod* before annotations160u2* ConstMethod::last_u2_element() const {161int offset = 0;162if (has_method_annotations()) offset++;163if (has_parameter_annotations()) offset++;164if (has_type_annotations()) offset++;165if (has_default_annotations()) offset++;166return (u2*)((AnnotationArray**)constMethod_end() - offset) - 1;167}168169u2* ConstMethod::generic_signature_index_addr() const {170// Located at the end of the constMethod.171assert(has_generic_signature(), "called only if generic signature exists");172return last_u2_element();173}174175u2* ConstMethod::method_parameters_length_addr() const {176assert(has_method_parameters(), "called only if table is present");177return has_generic_signature() ? (last_u2_element() - 1) :178last_u2_element();179}180181u2* ConstMethod::checked_exceptions_length_addr() const {182// Located immediately before the generic signature index.183assert(has_checked_exceptions(), "called only if table is present");184if(has_method_parameters()) {185// If method parameters present, locate immediately before them.186return (u2*)method_parameters_start() - 1;187} else {188// Else, the exception table is at the end of the constMethod.189return has_generic_signature() ? (last_u2_element() - 1) :190last_u2_element();191}192}193194u2* ConstMethod::exception_table_length_addr() const {195assert(has_exception_handler(), "called only if table is present");196if (has_checked_exceptions()) {197// If checked_exception present, locate immediately before them.198return (u2*) checked_exceptions_start() - 1;199} else {200if(has_method_parameters()) {201// If method parameters present, locate immediately before them.202return (u2*)method_parameters_start() - 1;203} else {204// Else, the exception table is at the end of the constMethod.205return has_generic_signature() ? (last_u2_element() - 1) :206last_u2_element();207}208}209}210211u2* ConstMethod::localvariable_table_length_addr() const {212assert(has_localvariable_table(), "called only if table is present");213if (has_exception_handler()) {214// If exception_table present, locate immediately before them.215return (u2*) exception_table_start() - 1;216} else {217if (has_checked_exceptions()) {218// If checked_exception present, locate immediately before them.219return (u2*) checked_exceptions_start() - 1;220} else {221if(has_method_parameters()) {222// If method parameters present, locate immediately before them.223return (u2*)method_parameters_start() - 1;224} else {225// Else, the exception table is at the end of the constMethod.226return has_generic_signature() ? (last_u2_element() - 1) :227last_u2_element();228}229}230}231}232233// Update the flags to indicate the presence of these optional fields.234void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {235_flags = 0;236if (sizes->compressed_linenumber_size() > 0)237_flags |= _has_linenumber_table;238if (sizes->generic_signature_index() != 0)239_flags |= _has_generic_signature;240if (sizes->method_parameters_length() > 0)241_flags |= _has_method_parameters;242if (sizes->checked_exceptions_length() > 0)243_flags |= _has_checked_exceptions;244if (sizes->exception_table_length() > 0)245_flags |= _has_exception_table;246if (sizes->localvariable_table_length() > 0)247_flags |= _has_localvariable_table;248249// annotations, they are all pointer sized embedded objects so don't have250// a length embedded also.251if (sizes->method_annotations_length() > 0)252_flags |= _has_method_annotations;253if (sizes->parameter_annotations_length() > 0)254_flags |= _has_parameter_annotations;255if (sizes->type_annotations_length() > 0)256_flags |= _has_type_annotations;257if (sizes->default_annotations_length() > 0)258_flags |= _has_default_annotations;259260// This code is extremely brittle and should possibly be revised.261// The *_length_addr functions walk backwards through the262// constMethod data, using each of the length indexes ahead of them,263// as well as the flags variable. Therefore, the indexes must be264// initialized in reverse order, or else they will compute the wrong265// offsets. Moving the initialization of _flags into a separate266// block solves *half* of the problem, but the following part will267// still break if the order is not exactly right.268//269// Also, the servicability agent needs to be informed anytime270// anything is added here. It might be advisable to have some sort271// of indication of this inline.272if (sizes->generic_signature_index() != 0)273*(generic_signature_index_addr()) = sizes->generic_signature_index();274// New data should probably go here.275if (sizes->method_parameters_length() > 0)276*(method_parameters_length_addr()) = sizes->method_parameters_length();277if (sizes->checked_exceptions_length() > 0)278*(checked_exceptions_length_addr()) = sizes->checked_exceptions_length();279if (sizes->exception_table_length() > 0)280*(exception_table_length_addr()) = sizes->exception_table_length();281if (sizes->localvariable_table_length() > 0)282*(localvariable_table_length_addr()) = sizes->localvariable_table_length();283}284285int ConstMethod::method_parameters_length() const {286return has_method_parameters() ? *(method_parameters_length_addr()) : 0;287}288289MethodParametersElement* ConstMethod::method_parameters_start() const {290u2* addr = method_parameters_length_addr();291u2 length = *addr;292assert(length > 0, "should only be called if table is present");293addr -= length * sizeof(MethodParametersElement) / sizeof(u2);294return (MethodParametersElement*) addr;295}296297298int ConstMethod::checked_exceptions_length() const {299return has_checked_exceptions() ? *(checked_exceptions_length_addr()) : 0;300}301302303CheckedExceptionElement* ConstMethod::checked_exceptions_start() const {304u2* addr = checked_exceptions_length_addr();305u2 length = *addr;306assert(length > 0, "should only be called if table is present");307addr -= length * sizeof(CheckedExceptionElement) / sizeof(u2);308return (CheckedExceptionElement*) addr;309}310311312int ConstMethod::localvariable_table_length() const {313return has_localvariable_table() ? *(localvariable_table_length_addr()) : 0;314}315316317LocalVariableTableElement* ConstMethod::localvariable_table_start() const {318u2* addr = localvariable_table_length_addr();319u2 length = *addr;320assert(length > 0, "should only be called if table is present");321addr -= length * sizeof(LocalVariableTableElement) / sizeof(u2);322return (LocalVariableTableElement*) addr;323}324325int ConstMethod::exception_table_length() const {326return has_exception_handler() ? *(exception_table_length_addr()) : 0;327}328329ExceptionTableElement* ConstMethod::exception_table_start() const {330u2* addr = exception_table_length_addr();331u2 length = *addr;332assert(length > 0, "should only be called if table is present");333addr -= length * sizeof(ExceptionTableElement) / sizeof(u2);334return (ExceptionTableElement*)addr;335}336337AnnotationArray** ConstMethod::method_annotations_addr() const {338assert(has_method_annotations(), "should only be called if method annotations are present");339return (AnnotationArray**)constMethod_end() - 1;340}341342AnnotationArray** ConstMethod::parameter_annotations_addr() const {343assert(has_parameter_annotations(), "should only be called if method parameter annotations are present");344int offset = 1;345if (has_method_annotations()) offset++;346return (AnnotationArray**)constMethod_end() - offset;347}348349AnnotationArray** ConstMethod::type_annotations_addr() const {350assert(has_type_annotations(), "should only be called if method type annotations are present");351int offset = 1;352if (has_method_annotations()) offset++;353if (has_parameter_annotations()) offset++;354return (AnnotationArray**)constMethod_end() - offset;355}356357AnnotationArray** ConstMethod::default_annotations_addr() const {358assert(has_default_annotations(), "should only be called if method default annotations are present");359int offset = 1;360if (has_method_annotations()) offset++;361if (has_parameter_annotations()) offset++;362if (has_type_annotations()) offset++;363return (AnnotationArray**)constMethod_end() - offset;364}365366// copy annotations from 'cm' to 'this'367void ConstMethod::copy_annotations_from(ConstMethod* cm) {368if (cm->has_method_annotations()) {369assert(has_method_annotations(), "should be allocated already");370set_method_annotations(cm->method_annotations());371}372if (cm->has_parameter_annotations()) {373assert(has_parameter_annotations(), "should be allocated already");374set_parameter_annotations(cm->parameter_annotations());375}376if (cm->has_type_annotations()) {377assert(has_type_annotations(), "should be allocated already");378set_type_annotations(cm->type_annotations());379}380if (cm->has_default_annotations()) {381assert(has_default_annotations(), "should be allocated already");382set_default_annotations(cm->default_annotations());383}384}385386// Printing387388void ConstMethod::print_on(outputStream* st) const {389ResourceMark rm;390assert(is_constMethod(), "must be constMethod");391st->print_cr("%s", internal_name());392Method* m = method();393st->print(" - method: " INTPTR_FORMAT " ", p2i((address)m));394if (m != NULL) {395m->print_value_on(st);396}397st->cr();398if (has_stackmap_table()) {399st->print(" - stackmap data: ");400stackmap_data()->print_value_on(st);401st->cr();402}403}404405// Short version of printing ConstMethod* - just print the name of the406// method it belongs to.407void ConstMethod::print_value_on(outputStream* st) const {408assert(is_constMethod(), "must be constMethod");409st->print(" const part of method " );410Method* m = method();411if (m != NULL) {412m->print_value_on(st);413} else {414st->print("NULL");415}416}417418#if INCLUDE_SERVICES419// Size Statistics420void ConstMethod::collect_statistics(KlassSizeStats *sz) const {421int n1, n2, n3;422sz->_const_method_bytes += (n1 = sz->count(this));423sz->_bytecode_bytes += (n2 = code_size());424sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data()));425426// Count method annotations427int a1 = 0, a2 = 0, a3 = 0, a4 = 0;428if (has_method_annotations()) {429sz->_methods_annotations_bytes += (a1 = sz->count_array(method_annotations()));430}431if (has_parameter_annotations()) {432sz->_methods_parameter_annotations_bytes += (a2 = sz->count_array(parameter_annotations()));433}434if (has_type_annotations()) {435sz->_methods_type_annotations_bytes += (a3 = sz->count_array(type_annotations()));436}437if (has_default_annotations()) {438sz->_methods_default_annotations_bytes += (a4 = sz->count_array(default_annotations()));439}440441int size_annotations = a1 + a2 + a3 + a4;442443sz->_method_all_bytes += n1 + n3 + size_annotations; // note: n2 is part of n3444sz->_ro_bytes += n1 + n3 + size_annotations;445}446#endif // INCLUDE_SERVICES447448// Verification449450void ConstMethod::verify_on(outputStream* st) {451guarantee(is_constMethod(), "object must be constMethod");452453// Verification can occur during oop construction before the method or454// other fields have been initialized.455guarantee(method() != NULL && method()->is_method(), "should be method");456457address m_end = (address)((intptr_t) this + size());458address compressed_table_start = code_end();459guarantee(compressed_table_start <= m_end, "invalid method layout");460address compressed_table_end = compressed_table_start;461// Verify line number table462if (has_linenumber_table()) {463CompressedLineNumberReadStream stream(compressed_linenumber_table());464while (stream.read_pair()) {465guarantee(stream.bci() >= 0 && stream.bci() <= code_size(), "invalid bci in line number table");466}467compressed_table_end += stream.position();468}469guarantee(compressed_table_end <= m_end, "invalid method layout");470// Verify checked exceptions, exception table and local variable tables471if (has_method_parameters()) {472u2* addr = method_parameters_length_addr();473guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");474}475if (has_checked_exceptions()) {476u2* addr = checked_exceptions_length_addr();477guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");478}479if (has_exception_handler()) {480u2* addr = exception_table_length_addr();481guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");482}483if (has_localvariable_table()) {484u2* addr = localvariable_table_length_addr();485guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");486}487// Check compressed_table_end relative to uncompressed_table_start488u2* uncompressed_table_start;489if (has_localvariable_table()) {490uncompressed_table_start = (u2*) localvariable_table_start();491} else if (has_exception_handler()) {492uncompressed_table_start = (u2*) exception_table_start();493} else if (has_checked_exceptions()) {494uncompressed_table_start = (u2*) checked_exceptions_start();495} else if (has_method_parameters()) {496uncompressed_table_start = (u2*) method_parameters_start();497} else {498uncompressed_table_start = (u2*) m_end;499}500int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end;501int max_gap = align_object_size(1)*BytesPerWord;502guarantee(gap >= 0 && gap < max_gap, "invalid method layout");503}504505506