# HG changeset patch # User ysr # Date 1264577771 28800 # Node ID 291c9b3b64fcdbb6b0b711ac89fd8d8a75422de2 # Parent 34fb2662f6c271233eeec7bc033e7fceb71ba8c8# Parent 2718ec34c69914ad7649938707e73f5aaec18f60 Merge diff -r 34fb2662f6c2 -r 291c9b3b64fc make/Makefile --- a/make/Makefile Tue Jan 26 16:52:29 2010 -0800 +++ b/make/Makefile Tue Jan 26 23:36:11 2010 -0800 @@ -1,5 +1,5 @@ # -# Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2005-2010 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -312,10 +312,13 @@ $(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar $(install-file) -# Include files (jvmti.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h) +# Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h) $(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/% $(install-file) +$(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/code/% + $(install-file) + $(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/prims/% $(install-file) diff -r 34fb2662f6c2 -r 291c9b3b64fc make/defs.make --- a/make/defs.make Tue Jan 26 16:52:29 2010 -0800 +++ b/make/defs.make Tue Jan 26 23:36:11 2010 -0800 @@ -1,5 +1,5 @@ # -# Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2006-2010 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -261,6 +261,7 @@ # Common export list of files EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jvmti.h +EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jvmticmlr.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jni.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h diff -r 34fb2662f6c2 -r 291c9b3b64fc src/share/vm/code/jvmticmlr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/code/jvmticmlr.h Tue Jan 26 23:36:11 2010 -0800 @@ -0,0 +1,115 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This header file defines the data structures sent by the VM + * through the JVMTI CompiledMethodLoad callback function via the + * "void * compile_info" parameter. The memory pointed to by the + * compile_info parameter may not be referenced after returning from + * the CompiledMethodLoad callback. These are VM implementation + * specific data structures that may evolve in future releases. A + * JVMTI agent should interpret a non-NULL compile_info as a pointer + * to a region of memory containing a list of records. In a typical + * usage scenario, a JVMTI agent would cast each record to a + * jvmtiCompiledMethodLoadRecordHeader, a struct that represents + * arbitrary information. This struct contains a kind field to indicate + * the kind of information being passed, and a pointer to the next + * record. If the kind field indicates inlining information, then the + * agent would cast the record to a jvmtiCompiledMethodLoadInlineRecord. + * This record contains an array of PCStackInfo structs, which indicate + * for every pc address what are the methods on the invocation stack. + * The "methods" and "bcis" fields in each PCStackInfo struct specify a + * 1-1 mapping between these inlined methods and their bytecode indices. + * This can be used to derive the proper source lines of the inlined + * methods. + */ + +#ifndef _JVMTI_CMLR_H_ +#define _JVMTI_CMLR_H_ + +enum { + JVMTI_CMLR_MAJOR_VERSION_1 = 0x00000001, + JVMTI_CMLR_MINOR_VERSION_0 = 0x00000000, + + JVMTI_CMLR_MAJOR_VERSION = 0x00000001, + JVMTI_CMLR_MINOR_VERSION = 0x00000000 + + /* + * This comment is for the "JDK import from HotSpot" sanity check: + * version: 1.0.0 + */ +}; + +typedef enum { + JVMTI_CMLR_DUMMY = 1, + JVMTI_CMLR_INLINE_INFO = 2 +} jvmtiCMLRKind; + +/* + * Record that represents arbitrary information passed through JVMTI + * CompiledMethodLoadEvent void pointer. + */ +typedef struct _jvmtiCompiledMethodLoadRecordHeader { + jvmtiCMLRKind kind; /* id for the kind of info passed in the record */ + jint majorinfoversion; /* major and minor info version values. Init'ed */ + jint minorinfoversion; /* to current version value in jvmtiExport.cpp. */ + + struct _jvmtiCompiledMethodLoadRecordHeader* next; +} jvmtiCompiledMethodLoadRecordHeader; + +/* + * Record that gives information about the methods on the compile-time + * stack at a specific pc address of a compiled method. Each element in + * the methods array maps to same element in the bcis array. + */ +typedef struct _PCStackInfo { + void* pc; /* the pc address for this compiled method */ + jint numstackframes; /* number of methods on the stack */ + jmethodID* methods; /* array of numstackframes method ids */ + jint* bcis; /* array of numstackframes bytecode indices */ +} PCStackInfo; + +/* + * Record that contains inlining information for each pc address of + * an nmethod. + */ +typedef struct _jvmtiCompiledMethodLoadInlineRecord { + jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */ + jint numpcs; /* number of pc descriptors in this nmethod */ + PCStackInfo* pcinfo; /* array of numpcs pc descriptors */ +} jvmtiCompiledMethodLoadInlineRecord; + +/* + * Dummy record used to test that we can pass records with different + * information through the void pointer provided that they can be cast + * to a jvmtiCompiledMethodLoadRecordHeader. + */ + +typedef struct _jvmtiCompiledMethodLoadDummyRecord { + jvmtiCompiledMethodLoadRecordHeader header; /* common header for casting */ + char message[50]; +} jvmtiCompiledMethodLoadDummyRecord; + +#endif diff -r 34fb2662f6c2 -r 291c9b3b64fc src/share/vm/includeDB_core --- a/src/share/vm/includeDB_core Tue Jan 26 16:52:29 2010 -0800 +++ b/src/share/vm/includeDB_core Tue Jan 26 23:36:11 2010 -0800 @@ -2530,6 +2530,7 @@ jvmtiExport.hpp handles.hpp jvmtiExport.hpp iterator.hpp jvmtiExport.hpp jvmti.h +jvmtiExport.hpp jvmticmlr.h jvmtiExport.hpp oop.hpp jvmtiExport.hpp oopsHierarchy.hpp diff -r 34fb2662f6c2 -r 291c9b3b64fc src/share/vm/prims/jvmtiExport.cpp --- a/src/share/vm/prims/jvmtiExport.cpp Tue Jan 26 16:52:29 2010 -0800 +++ b/src/share/vm/prims/jvmtiExport.cpp Tue Jan 26 23:36:11 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -686,11 +686,11 @@ jvmtiAddrLocationMap *_map; const void *_compile_info; public: - JvmtiCompiledMethodLoadEventMark(JavaThread *thread, nmethod *nm) + JvmtiCompiledMethodLoadEventMark(JavaThread *thread, nmethod *nm, void* compile_info_ptr = NULL) : JvmtiMethodEventMark(thread,methodHandle(thread, nm->method())) { _code_data = nm->code_begin(); _code_size = nm->code_size(); - _compile_info = NULL; /* no info for our VM. */ + _compile_info = compile_info_ptr; // Set void pointer of compiledMethodLoad Event. Default value is NULL. JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &_map, &_map_length); } ~JvmtiCompiledMethodLoadEventMark() { @@ -1752,6 +1752,46 @@ } } +// Returns a record containing inlining information for the given nmethod +jvmtiCompiledMethodLoadInlineRecord* create_inline_record(nmethod* nm) { + jint numstackframes = 0; + jvmtiCompiledMethodLoadInlineRecord* record = (jvmtiCompiledMethodLoadInlineRecord*)NEW_RESOURCE_OBJ(jvmtiCompiledMethodLoadInlineRecord); + record->header.kind = JVMTI_CMLR_INLINE_INFO; + record->header.next = NULL; + record->header.majorinfoversion = JVMTI_CMLR_MAJOR_VERSION_1; + record->header.minorinfoversion = JVMTI_CMLR_MINOR_VERSION_0; + record->numpcs = 0; + for(PcDesc* p = nm->scopes_pcs_begin(); p < nm->scopes_pcs_end(); p++) { + if(p->scope_decode_offset() == DebugInformationRecorder::serialized_null) continue; + record->numpcs++; + } + record->pcinfo = (PCStackInfo*)(NEW_RESOURCE_ARRAY(PCStackInfo, record->numpcs)); + int scope = 0; + for(PcDesc* p = nm->scopes_pcs_begin(); p < nm->scopes_pcs_end(); p++) { + if(p->scope_decode_offset() == DebugInformationRecorder::serialized_null) continue; + void* pc_address = (void*)p->real_pc(nm); + assert(pc_address != NULL, "pc_address must be non-null"); + record->pcinfo[scope].pc = pc_address; + numstackframes=0; + for(ScopeDesc* sd = nm->scope_desc_at(p->real_pc(nm));sd != NULL;sd = sd->sender()) { + numstackframes++; + } + assert(numstackframes != 0, "numstackframes must be nonzero."); + record->pcinfo[scope].methods = (jmethodID *)NEW_RESOURCE_ARRAY(jmethodID, numstackframes); + record->pcinfo[scope].bcis = (jint *)NEW_RESOURCE_ARRAY(jint, numstackframes); + record->pcinfo[scope].numstackframes = numstackframes; + int stackframe = 0; + for(ScopeDesc* sd = nm->scope_desc_at(p->real_pc(nm));sd != NULL;sd = sd->sender()) { + // sd->method() can be NULL for stubs but not for nmethods. To be completely robust, include an assert that we should never see a null sd->method() + assert(!sd->method().is_null(), "sd->method() cannot be null."); + record->pcinfo[scope].methods[stackframe] = sd->method()->jmethod_id(); + record->pcinfo[scope].bcis[stackframe] = sd->bci(); + stackframe++; + } + scope++; + } + return record; +} void JvmtiExport::post_compiled_method_load(nmethod *nm) { // If there are pending CompiledMethodUnload events then these are @@ -1780,7 +1820,11 @@ (nm->method() == NULL) ? "NULL" : nm->method()->name()->as_C_string())); ResourceMark rm(thread); - JvmtiCompiledMethodLoadEventMark jem(thread, nm); + + // Add inlining information + jvmtiCompiledMethodLoadInlineRecord* inlinerecord = create_inline_record(nm); + // Pass inlining information through the void pointer + JvmtiCompiledMethodLoadEventMark jem(thread, nm, inlinerecord); JvmtiJavaThreadEventTransition jet(thread); jvmtiEventCompiledMethodLoad callback = env->callbacks()->CompiledMethodLoad; if (callback != NULL) {