Path: blob/master/src/hotspot/share/oops/constMethod.hpp
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#ifndef SHARE_OOPS_CONSTMETHOD_HPP25#define SHARE_OOPS_CONSTMETHOD_HPP2627#include "oops/oop.hpp"28#include "utilities/align.hpp"2930// An ConstMethod represents portions of a Java method which are not written to after31// the classfile is parsed(*see below). This part of the method can be shared across32// processes in a read-only section with Class Data Sharing (CDS). It's important33// that this class doesn't have virtual functions because the vptr cannot be shared34// with CDS.35//36// Note that most applications load thousands of methods, so keeping the size of this37// structure small has a big impact on footprint.3839// The actual bytecodes are inlined after the end of the ConstMethod struct.40//41// The line number table is compressed and inlined following the byte codes. It is42// found as the first byte following the byte codes. Note that accessing the line43// number and local variable tables is not performance critical at all.44//45// The checked exceptions table and the local variable table are inlined after the46// line number table, and indexed from the end of the method. We do not compress the47// checked exceptions table since the average length is less than 2, and it is used48// by reflection so access should be fast. We do not bother to compress the local49// variable table either since it is mostly absent.50//51//52// ConstMethod embedded field layout (after declared fields):53// [EMBEDDED byte codes]54// [EMBEDDED compressed linenumber table]55// (see class CompressedLineNumberReadStream)56// (note that length is unknown until decompressed)57// (access flags bit tells whether table is present)58// (indexed from start of ConstMethod)59// (elements not necessarily sorted!)60// [EMBEDDED localvariable table elements + length (length last)]61// (length is u2, elements are 6-tuples of u2)62// (see class LocalVariableTableElement)63// (access flags bit tells whether table is present)64// (indexed from end of ConstMethod*)65// [EMBEDDED exception table + length (length last)]66// (length is u2, elements are 4-tuples of u2)67// (see class ExceptionTableElement)68// (access flags bit tells whether table is present)69// (indexed from end of ConstMethod*)70// [EMBEDDED checked exceptions elements + length (length last)]71// (length is u2, elements are u2)72// (see class CheckedExceptionElement)73// (access flags bit tells whether table is present)74// (indexed from end of ConstMethod*)75// [EMBEDDED method parameters elements + length (length last)]76// (length is u2, elements are u2, u4 structures)77// (see class MethodParametersElement)78// (access flags bit tells whether table is present)79// (indexed from end of ConstMethod*)80// [EMBEDDED generic signature index (u2)]81// (indexed from end of constMethodOop)82// [EMBEDDED annotations arrays - method, parameter, type, default]83// pointer to Array<u1> if annotation is present84//85// IMPORTANT: If anything gets added here, there need to be changes to86// ensure that ServicabilityAgent doesn't get broken as a result!878889// Utility class describing elements in checked exceptions table inlined in Method*.90class CheckedExceptionElement {91public:92u2 class_cp_index;93};949596// Utility class describing elements in local variable table inlined in Method*.97class LocalVariableTableElement {98public:99u2 start_bci;100u2 length;101u2 name_cp_index;102u2 descriptor_cp_index;103u2 signature_cp_index;104u2 slot;105};106107// Utility class describing elements in exception table108class ExceptionTableElement {109public:110u2 start_pc;111u2 end_pc;112u2 handler_pc;113u2 catch_type_index;114};115116// Utility class describing elements in method parameters117class MethodParametersElement {118public:119u2 name_cp_index;120u2 flags;121};122123// Class to collect the sizes of ConstMethod inline tables124#define INLINE_TABLES_DO(do_element) \125do_element(localvariable_table_length) \126do_element(compressed_linenumber_size) \127do_element(exception_table_length) \128do_element(checked_exceptions_length) \129do_element(method_parameters_length) \130do_element(generic_signature_index) \131do_element(method_annotations_length) \132do_element(parameter_annotations_length) \133do_element(type_annotations_length) \134do_element(default_annotations_length)135136#define INLINE_TABLE_DECLARE(sym) int _##sym;137#define INLINE_TABLE_PARAM(sym) int sym,138#define INLINE_TABLE_INIT(sym) _##sym(sym),139#define INLINE_TABLE_NULL(sym) _##sym(0),140#define INLINE_TABLE_ACCESSOR(sym) int sym() const { return _##sym; }141142class InlineTableSizes : StackObj {143// declarations144INLINE_TABLES_DO(INLINE_TABLE_DECLARE)145int _end;146public:147InlineTableSizes(148INLINE_TABLES_DO(INLINE_TABLE_PARAM)149int end) :150INLINE_TABLES_DO(INLINE_TABLE_INIT)151_end(end) {}152153// Default constructor for no inlined tables154InlineTableSizes() :155INLINE_TABLES_DO(INLINE_TABLE_NULL)156_end(0) {}157158// Accessors159INLINE_TABLES_DO(INLINE_TABLE_ACCESSOR)160};161#undef INLINE_TABLE_ACCESSOR162#undef INLINE_TABLE_NULL163#undef INLINE_TABLE_INIT164#undef INLINE_TABLE_PARAM165#undef INLINE_TABLE_DECLARE166167class ConstMethod : public MetaspaceObj {168friend class VMStructs;169friend class JVMCIVMStructs;170171public:172typedef enum { NORMAL, OVERPASS } MethodType;173174private:175enum {176_has_linenumber_table = 0x0001,177_has_checked_exceptions = 0x0002,178_has_localvariable_table = 0x0004,179_has_exception_table = 0x0008,180_has_generic_signature = 0x0010,181_has_method_parameters = 0x0020,182_is_overpass = 0x0040,183_has_method_annotations = 0x0080,184_has_parameter_annotations = 0x0100,185_has_type_annotations = 0x0200,186_has_default_annotations = 0x0400187};188189// Bit vector of signature190// Callers interpret 0=not initialized yet and191// -1=too many args to fix, must parse the slow way.192// The real initial value is special to account for nonatomicity of 64 bit193// loads and stores. This value may updated and read without a lock by194// multiple threads, so is volatile.195volatile uint64_t _fingerprint;196197// If you add a new field that points to any metaspace object, you198// must add this field to ConstMethod::metaspace_pointers_do().199200ConstantPool* _constants; // Constant pool201202// Raw stackmap data for the method203Array<u1>* _stackmap_data;204205int _constMethod_size;206u2 _flags;207u1 _result_type; // BasicType of result208209// Size of Java bytecodes allocated immediately after Method*.210u2 _code_size;211u2 _name_index; // Method name (index in constant pool)212u2 _signature_index; // Method signature (index in constant pool)213u2 _method_idnum; // unique identification number for the method within the class214// initially corresponds to the index into the methods array.215// but this may change with redefinition216u2 _max_stack; // Maximum number of entries on the expression stack217u2 _max_locals; // Number of local variables used by this method218u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words219u2 _orig_method_idnum; // Original unique identification number for the method220221// Constructor222ConstMethod(int byte_code_size,223InlineTableSizes* sizes,224MethodType is_overpass,225int size);226public:227228static ConstMethod* allocate(ClassLoaderData* loader_data,229int byte_code_size,230InlineTableSizes* sizes,231MethodType mt,232TRAPS);233234// Inlined tables235void set_inlined_tables_length(InlineTableSizes* sizes);236237bool has_generic_signature() const238{ return (_flags & _has_generic_signature) != 0; }239240bool has_linenumber_table() const241{ return (_flags & _has_linenumber_table) != 0; }242243bool has_checked_exceptions() const244{ return (_flags & _has_checked_exceptions) != 0; }245246bool has_localvariable_table() const247{ return (_flags & _has_localvariable_table) != 0; }248249bool has_exception_handler() const250{ return (_flags & _has_exception_table) != 0; }251252bool has_method_parameters() const253{ return (_flags & _has_method_parameters) != 0; }254255MethodType method_type() const {256return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS;257}258259void set_method_type(MethodType mt) {260if (mt == NORMAL) {261_flags &= ~(_is_overpass);262} else {263_flags |= _is_overpass;264}265}266267// constant pool268ConstantPool* constants() const { return _constants; }269void set_constants(ConstantPool* c) { _constants = c; }270271Method* method() const;272273// stackmap table data274Array<u1>* stackmap_data() const { return _stackmap_data; }275void set_stackmap_data(Array<u1>* sd) { _stackmap_data = sd; }276void copy_stackmap_data(ClassLoaderData* loader_data, u1* sd, int length, TRAPS);277bool has_stackmap_table() const { return _stackmap_data != NULL; }278279void init_fingerprint() {280const uint64_t initval = UCONST64(0x8000000000000000);281_fingerprint = initval;282}283284uint64_t fingerprint() const {285// Since reads aren't atomic for 64 bits, if any of the high or low order286// word is the initial value, return 0. See init_fingerprint for initval.287uint high_fp = (uint)(_fingerprint >> 32);288if ((int) _fingerprint == 0 || high_fp == 0x80000000) {289return 0L;290} else {291return _fingerprint;292}293}294295uint64_t set_fingerprint(uint64_t new_fingerprint) {296#ifdef ASSERT297// Assert only valid if complete/valid 64 bit _fingerprint value is read.298uint64_t oldfp = fingerprint();299#endif // ASSERT300_fingerprint = new_fingerprint;301assert(oldfp == 0L || new_fingerprint == oldfp,302"fingerprint cannot change");303assert(((new_fingerprint >> 32) != 0x80000000) && (int)new_fingerprint !=0,304"fingerprint should call init to set initial value");305return new_fingerprint;306}307308// name309int name_index() const { return _name_index; }310void set_name_index(int index) { _name_index = index; }311312// signature313int signature_index() const { return _signature_index; }314void set_signature_index(int index) { _signature_index = index; }315316// generics support317int generic_signature_index() const {318if (has_generic_signature()) {319return *generic_signature_index_addr();320} else {321return 0;322}323}324void set_generic_signature_index(u2 index) {325assert(has_generic_signature(), "");326u2* addr = generic_signature_index_addr();327*addr = index;328}329330// Sizing331static int header_size() {332return align_up((int)sizeof(ConstMethod), wordSize) / wordSize;333}334335// Size needed336static int size(int code_size, InlineTableSizes* sizes);337338int size() const { return _constMethod_size;}339void set_constMethod_size(int size) { _constMethod_size = size; }340341// ConstMethods should be stored in the read-only region of CDS archive.342static bool is_read_only_by_default() { return true; }343344// code size345int code_size() const { return _code_size; }346void set_code_size(int size) {347assert(max_method_code_size < (1 << 16),348"u2 is too small to hold method code size in general");349assert(0 <= size && size <= max_method_code_size, "invalid code size");350_code_size = size;351}352353// linenumber table - note that length is unknown until decompression,354// see class CompressedLineNumberReadStream.355u_char* compressed_linenumber_table() const; // not preserved by gc356u2* generic_signature_index_addr() const;357u2* checked_exceptions_length_addr() const;358u2* localvariable_table_length_addr() const;359u2* exception_table_length_addr() const;360u2* method_parameters_length_addr() const;361362// checked exceptions363int checked_exceptions_length() const;364CheckedExceptionElement* checked_exceptions_start() const;365366// localvariable table367int localvariable_table_length() const;368LocalVariableTableElement* localvariable_table_start() const;369370// exception table371int exception_table_length() const;372ExceptionTableElement* exception_table_start() const;373374// method parameters table375376// This returns -1 if no parameters are present, a non-negative377// value otherwise. Note: sometimes, there are 0-length parameters378// attributes that must be reported up to the reflection API all the379// same.380int method_parameters_length() const;381MethodParametersElement* method_parameters_start() const;382383// method annotations384bool has_method_annotations() const385{ return (_flags & _has_method_annotations) != 0; }386387bool has_parameter_annotations() const388{ return (_flags & _has_parameter_annotations) != 0; }389390bool has_type_annotations() const391{ return (_flags & _has_type_annotations) != 0; }392393bool has_default_annotations() const394{ return (_flags & _has_default_annotations) != 0; }395396397AnnotationArray** method_annotations_addr() const;398AnnotationArray* method_annotations() const {399return has_method_annotations() ? *(method_annotations_addr()) : NULL;400}401void set_method_annotations(AnnotationArray* anno) {402*(method_annotations_addr()) = anno;403}404405AnnotationArray** parameter_annotations_addr() const;406AnnotationArray* parameter_annotations() const {407return has_parameter_annotations() ? *(parameter_annotations_addr()) : NULL;408}409void set_parameter_annotations(AnnotationArray* anno) {410*(parameter_annotations_addr()) = anno;411}412413AnnotationArray** type_annotations_addr() const;414AnnotationArray* type_annotations() const {415return has_type_annotations() ? *(type_annotations_addr()) : NULL;416}417void set_type_annotations(AnnotationArray* anno) {418*(type_annotations_addr()) = anno;419}420421AnnotationArray** default_annotations_addr() const;422AnnotationArray* default_annotations() const {423return has_default_annotations() ? *(default_annotations_addr()) : NULL;424}425void set_default_annotations(AnnotationArray* anno) {426*(default_annotations_addr()) = anno;427}428429int method_annotations_length() const {430return has_method_annotations() ? method_annotations()->length() : 0;431}432int parameter_annotations_length() const {433return has_parameter_annotations() ? parameter_annotations()->length() : 0;434}435int type_annotations_length() const {436return has_type_annotations() ? type_annotations()->length() : 0;437}438int default_annotations_length() const {439return has_default_annotations() ? default_annotations()->length() : 0;440}441442// Copy annotations from other ConstMethod443void copy_annotations_from(ClassLoaderData* loader_data, ConstMethod* cm, TRAPS);444445// byte codes446void set_code(address code) {447if (code_size() > 0) {448memcpy(code_base(), code, code_size());449}450}451address code_base() const { return (address) (this+1); }452address code_end() const { return code_base() + code_size(); }453bool contains(address bcp) const { return code_base() <= bcp454&& bcp < code_end(); }455// Offset to bytecodes456static ByteSize codes_offset()457{ return in_ByteSize(sizeof(ConstMethod)); }458459static ByteSize constants_offset()460{ return byte_offset_of(ConstMethod, _constants); }461462static ByteSize max_stack_offset()463{ return byte_offset_of(ConstMethod, _max_stack); }464static ByteSize size_of_locals_offset()465{ return byte_offset_of(ConstMethod, _max_locals); }466static ByteSize size_of_parameters_offset()467{ return byte_offset_of(ConstMethod, _size_of_parameters); }468469static ByteSize result_type_offset()470{ return byte_offset_of(ConstMethod, _result_type); }471472// Unique id for the method473static const u2 MAX_IDNUM;474static const u2 UNSET_IDNUM;475u2 method_idnum() const { return _method_idnum; }476void set_method_idnum(u2 idnum) { _method_idnum = idnum; }477478u2 orig_method_idnum() const { return _orig_method_idnum; }479void set_orig_method_idnum(u2 idnum) { _orig_method_idnum = idnum; }480481// max stack482int max_stack() const { return _max_stack; }483void set_max_stack(int size) { _max_stack = size; }484485// max locals486int max_locals() const { return _max_locals; }487void set_max_locals(int size) { _max_locals = size; }488489// size of parameters490int size_of_parameters() const { return _size_of_parameters; }491void set_size_of_parameters(int size) { _size_of_parameters = size; }492493// result type (basic type of return value)494BasicType result_type() const { assert(_result_type >= T_BOOLEAN, "Must be set");495return (BasicType)_result_type; }496497void set_result_type(BasicType rt) { assert(rt < 16, "result type too large");498_result_type = (u1)rt; }499// Deallocation for RedefineClasses500void deallocate_contents(ClassLoaderData* loader_data);501bool is_klass() const { return false; }502DEBUG_ONLY(bool on_stack() { return false; })503504void metaspace_pointers_do(MetaspaceClosure* it);505MetaspaceObj::Type type() const { return ConstMethodType; }506private:507// Since the size of the compressed line number table is unknown, the508// offsets of the other variable sized sections are computed backwards509// from the end of the ConstMethod*.510511// First byte after ConstMethod*512address constMethod_end() const513{ return (address)((intptr_t*)this + _constMethod_size); }514515// Last short in ConstMethod*516u2* last_u2_element() const;517518public:519// Printing520void print_on (outputStream* st) const;521void print_value_on(outputStream* st) const;522523const char* internal_name() const { return "{constMethod}"; }524525// Verify526void verify_on(outputStream* st);527};528529#endif // SHARE_OOPS_CONSTMETHOD_HPP530531532