--- a/hotspot/make/Makefile Tue Jan 12 13:54:40 2010 -0800
+++ b/hotspot/make/Makefile Wed Jan 20 11:32:41 2010 -0700
@@ -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)
--- a/hotspot/make/defs.make Tue Jan 12 13:54:40 2010 -0800
+++ b/hotspot/make/defs.make Wed Jan 20 11:32:41 2010 -0700
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/code/jvmticmlr.h Wed Jan 20 11:32:41 2010 -0700
@@ -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
--- a/hotspot/src/share/vm/includeDB_core Tue Jan 12 13:54:40 2010 -0800
+++ b/hotspot/src/share/vm/includeDB_core Wed Jan 20 11:32:41 2010 -0700
@@ -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
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp Tue Jan 12 13:54:40 2010 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp Wed Jan 20 11:32:41 2010 -0700
@@ -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) {