Index: vm/vmcore/include/stack_trace.h
===================================================================
--- vm/vmcore/include/stack_trace.h (revision 593520)
+++ vm/vmcore/include/stack_trace.h (working copy)
@@ -87,11 +87,10 @@
VMEXPORT unsigned st_get_depth(VM_thread *p_vmthread);
/**
- * Fills the stack trace frame at the given depth for the current thread.
+ * Fills the stack trace frame at the given relative depth for the current thread.
*
- * @param[in] depth - the zero-based depth of the frame or inlined method,
- * information about which will be stored at the given stack trace
- * frame, stf
+ * @param[in] depth - relative depth of a frame or inlined method on the stack,
+ * topmost frame has zero depth.
* @param[out] stf - the pointer to the StackTraceFrame structure that needs
* to be filled with the data on the frame or inlined method
* corresponding to the given depth
@@ -135,7 +134,7 @@
*
* @param[in] method - the handle of the method information to identify the source file
* @param[in] ip - the instruction pointer to identify the JIT and using the JIT line number
- * @param[in] depth - the inlined depth for inlined methods, starting from 0;
+ * @param[in] depth - the inlined depth for inlined methods;
* (-1) for native methods and methods which were not inlined
* @param[out] file - the pointer to the file reference to be filled by this function
* @param[out] line - the pointer to the line number to be filled by this function
Index: vm/vmcore/include/jit_export_rt.h
===================================================================
--- vm/vmcore/include/jit_export_rt.h (revision 593520)
+++ vm/vmcore/include/jit_export_rt.h (working copy)
@@ -192,12 +192,51 @@
GC_Enumeration_Handle enum_handle,
JitFrameContext* context
);
-
+/**
+ * Returns number of methods which were inlined at the specified location (zero if none)
+ * @param jit - a JIT which produced the code
+ * @param prt - corresponding inline info
+ * @param offset - offset in native code relative to code block start
+ */
JITEXPORT uint32
JIT_get_inline_depth(JIT_Handle jit,
InlineInfoPtr ptr,
uint32 offset);
+/**
+* Returns specified inlined method (null if not found).
+* The inlined methods are indexed as [max_depth..1],
+* so the topmost method on the stack has maximum inline depth and
+* enclosing methods have descending indicies.
+* Zero depth would mean nearest non-inlined method and should not be used here.
+* @param jit - a JIT which produced the code
+* @param prt - corresponding inline info
+* @param offset - offset in native code relative to code block start
+* @param inline_depth - index of the inlined method
+*/
+JITEXPORT Method_Handle
+JIT_get_inlined_method(JIT_Handle jit,
+ InlineInfoPtr ptr,
+ uint32 offset,
+ uint32 inline_depth);
+
+/**
+* Returns bytecode offset at specified inlined method for the native code (zero if unknown).
+* The inlined methods are indexed as [max_depth..1],
+* so the topmost method on the stack has maximum inline depth and
+* enclosing methods have descending indicies.
+* Zero depth would mean nearest non-inlined method and should not be used here.
+* @param jit - a JIT which produced the code
+* @param prt - corresponding inline info
+* @param offset - offset in native code relative to code block start
+* @param inline_depth - index of the inlined method
+*/
+JITEXPORT uint16
+JIT_get_inlined_bc(JIT_Handle jit,
+ InlineInfoPtr ptr,
+ uint32 offset,
+ uint32 inline_depth);
+
JITEXPORT Boolean
JIT_can_enumerate(JIT_Handle jit,
Method_Handle method,
Index: vm/vmcore/src/gc/root_set_enum_common.cpp
===================================================================
--- vm/vmcore/src/gc/root_set_enum_common.cpp (revision 593520)
+++ vm/vmcore/src/gc/root_set_enum_common.cpp (working copy)
@@ -319,14 +319,16 @@
JIT *jit = cci->get_jit();
NativeCodePtr ip = si_get_ip(si);
uint32 inlined_depth = si_get_inline_depth(si);
- uint32 offset = (uint32)((POINTER_SIZE_INT)ip - (POINTER_SIZE_INT)cci->get_code_block_addr());
- for (uint32 i = 0; i < inlined_depth; i++) {
- Method* m = jit->get_inlined_method(cci->get_inline_info(), offset, i);
- assert (m);
- cl = m->get_class()->get_class_loader();
- assert (cl);
- // force cl classloader to be enumerated as strong reference
- cl->Mark();
+ if (inlined_depth) {
+ uint32 offset = (uint32)((POINTER_SIZE_INT)ip - (POINTER_SIZE_INT)cci->get_code_block_addr());
+ for (uint32 i = inlined_depth; i > 0; i--) {
+ Method* m = jit->get_inlined_method(cci->get_inline_info(), offset, i);
+ assert (m);
+ cl = m->get_class()->get_class_loader();
+ assert (cl);
+ // force cl classloader to be enumerated as strong reference
+ cl->Mark();
+ }
}
}
TRACE2("enumeration", "enumerated eip=" << (void *) si_get_ip(si)
Index: vm/vmcore/src/jvmti/jvmti_stack.cpp
===================================================================
--- vm/vmcore/src/jvmti/jvmti_stack.cpp (revision 593520)
+++ vm/vmcore/src/jvmti/jvmti_stack.cpp (working copy)
@@ -153,19 +153,21 @@
CodeChunkInfo *cci = si_get_code_chunk_info(si);
JIT *jit = cci->get_jit();
+ uint16 bc;
// inlined method frame
if (0 != inlined_depth) {
uint32 offset = (uint32) ((char*) ip -
(char*) cci->get_code_block_addr());
method = jit->get_inlined_method(
- cci->get_inline_info(), offset, inlined_num - inlined_depth);
+ cci->get_inline_info(), offset, inlined_depth);
+ bc = jit->get_inlined_bc(
+ cci->get_inline_info(), offset, inlined_depth);
+ } else {
+ OpenExeJpdaError UNREF result = jit->get_bc_location_for_native(
+ method, ip, &bc);
+ assert(result == EXE_ERROR_NONE);
}
- uint16 bc;
- OpenExeJpdaError UNREF result = jit->get_bc_location_for_native(
- method, ip, &bc);
- assert(result == EXE_ERROR_NONE);
-
*p_method = (jmethodID) method;
*p_location = (jlocation) bc;
}
Index: vm/vmcore/src/stack/stack_trace.cpp
===================================================================
--- vm/vmcore/src/stack/stack_trace.cpp (revision 593520)
+++ vm/vmcore/src/stack/stack_trace.cpp (working copy)
@@ -19,6 +19,10 @@
* @version $Revision: 1.1.2.1.4.3 $
*/
+#define LOG_DOMAIN "vm.stack"
+#include "cxxlog.h"
+#include "vm_log.h"
+
#include "m2n.h"
#include "stack_iterator.h"
#include "stack_trace.h"
@@ -47,8 +51,6 @@
return;
}
- // inlined method will not have line numbers for now
- // they are marked with zero ip address.
if (ip == NULL) {
return;
}
@@ -65,6 +67,7 @@
POINTER_SIZE_INT eff_ip = (POINTER_SIZE_INT)ip -
(is_ip_past ? callLength : 0);
+ uint32 offset = 0;
if (depth < 0) // Not inlined method
{
if (cci->get_jit()->get_bc_location_for_native(
@@ -77,13 +80,15 @@
if (inl_info)
{
- uint32 offset = (uint32) ((POINTER_SIZE_INT)ip -
+ offset = (uint32) ((POINTER_SIZE_INT)ip -
(POINTER_SIZE_INT)cci->get_code_block_addr());
bcOffset = cci->get_jit()->get_inlined_bc(inl_info, offset, depth);
}
}
*line = method->get_line_number(bcOffset);
+ TRACE("Location of " << method << " at idepth=" << depth << " noff=" << offset
+ << " bc=" << bcOffset << " line=" << *line);
#endif
}
@@ -108,6 +113,7 @@
return interpreter.interpreter_st_get_frame(target_depth, stf);
}
+ TRACE("looking for frame: "<ip = si_get_ip(si);
- if (target_depth < depth + inlined_depth) {
+ if (target_depth != depth + inlined_depth) {
+ assert(inlined_depth);
CodeChunkInfo* cci = si_get_code_chunk_info(si);
// FIXME64: no support for large methods
// with compiled code size greater than 4GB
uint32 offset = (uint32)((POINTER_SIZE_INT)stf->ip - (POINTER_SIZE_INT)cci->get_code_block_addr());
+ stf->depth = inlined_depth - (target_depth - depth);
stf->method = cci->get_jit()->get_inlined_method(
- cci->get_inline_info(), offset, target_depth - depth);
- stf->depth = target_depth - depth;
+ cci->get_inline_info(), offset, stf->depth);
+ TRACE("found inlined frame: "<method << " at depth="<depth << " of "<< inlined_depth);
}
+ else {
+ TRACE("found frame: "<method);
+ }
si_free(si);
return true;
@@ -181,22 +192,28 @@
stf->outdated_this = 0;
} else {
JIT *jit = cci->get_jit();
- uint32 inlined_depth = si_get_inline_depth(si);
- // FIXME64: no support for large methods
- // with compiled code greater than 4GB
- uint32 offset = (uint32)((POINTER_SIZE_INT)ip - (POINTER_SIZE_INT)cci->get_code_block_addr());
-
- for (uint32 i = 0; i < inlined_depth; i++) {
- stf->method = jit->get_inlined_method(cci->get_inline_info(), offset, i);
- stf->ip = ip;
- stf->depth = i;
- stf->outdated_this = get_this(jit, method, si);
- stf++;
- depth++;
+ if (cci->has_inline_info()) {
+ // FIXME64: no support for large methods
+ // with compiled code greater than 4GB
+ uint32 offset = (uint32)((POINTER_SIZE_INT)ip - (POINTER_SIZE_INT)cci->get_code_block_addr());
+ uint32 inlined_depth = jit->get_inline_depth(
+ cci->get_inline_info(), offset);
+ if (inlined_depth) {
+ for (uint32 i = inlined_depth; i > 0; i--) {
+ stf->method = jit->get_inlined_method(cci->get_inline_info(), offset, i);
+ stf->ip = ip;
+ stf->depth = i;
+ TRACE("tracing inlined frame: "<method << " at depth="<depth);
+ stf->outdated_this = get_this(jit, method, si);
+ stf++;
+ depth++;
+ }
+ }
}
stf->outdated_this = get_this(jit, method, si);
}
stf->method = method;
+ TRACE("tracing frame: "<method);
stf->ip = ip;
stf->depth = -1;
stf++;
@@ -282,17 +299,19 @@
if (m) {
fprintf(f, " [%p] %p(%c): ", vm_thread, si_get_ip(si), (si_is_native(si) ? 'n' : 'm'));
CodeChunkInfo* cci = si_get_code_chunk_info(si);
- if ( cci != NULL ) {
- uint32 inlined_depth = si_get_inline_depth(si);
+ if (cci != NULL && cci->has_inline_info()) {
// FIXME64: no support for large methods
// with compiled code size greater than 4GB
uint32 offset = (uint32)((POINTER_SIZE_INT)si_get_ip(si) - (POINTER_SIZE_INT)cci->get_code_block_addr());
-
- for (uint32 i = 0; i < inlined_depth; i++) {
- Method *real_method = cci->get_jit()->get_inlined_method(cci->get_inline_info(), offset, i);
- fprintf(f, "%s.%s%s\n", class_get_name(method_get_class(real_method)),
- method_get_name(real_method), method_get_descriptor(real_method));
- depth++;
+ uint32 inlined_depth = cci->get_jit()->get_inline_depth(
+ cci->get_inline_info(), offset);
+ if (inlined_depth) {
+ for (uint32 i = inlined_depth; i > 0; i--) {
+ Method *real_method = cci->get_jit()->get_inlined_method(cci->get_inline_info(), offset, i);
+ fprintf(f, "%s.%s%s\n", class_get_name(method_get_class(real_method)),
+ method_get_name(real_method), method_get_descriptor(real_method));
+ depth++;
+ }
}
}
fprintf(f, "%s.%s%s\n", class_get_name(method_get_class(m)), method_get_name(m), method_get_descriptor(m));
Index: vm/jitrino/src/codegenerator/ia32/Ia32RuntimeInterface.cpp
===================================================================
--- vm/jitrino/src/codegenerator/ia32/Ia32RuntimeInterface.cpp (revision 593520)
+++ vm/jitrino/src/codegenerator/ia32/Ia32RuntimeInterface.cpp (working copy)
@@ -127,7 +127,9 @@
uint32 RuntimeInterface::getInlineDepth(InlineInfoPtr ptr, uint32 offset) {
const InlineInfoMap::Entry* e = InlineInfoMap::getEntryWithMaxDepth(ptr, offset);
- return e == NULL ? 0 : e->getInlineDepth();
+ // real instructions are recorded at an extra nested level to enclosing method
+ // but we need to count method marker entries only
+ return e == NULL ? 0 : e->getInlineDepth() - 1;
}
Method_Handle RuntimeInterface::getInlinedMethod(InlineInfoPtr ptr, uint32 offset, uint32 inline_depth) {
@@ -136,8 +138,26 @@
}
uint16 RuntimeInterface::getInlinedBc(InlineInfoPtr ptr, uint32 offset, uint32 inline_depth) {
- const InlineInfoMap::Entry* e = InlineInfoMap::getEntry(ptr, offset, inline_depth);
- return e == NULL ? 0 : e->bcOffset;
+ const InlineInfoMap::Entry* e = InlineInfoMap::getEntryWithMaxDepth(ptr, offset);
+ assert(inline_depth);
+
+ // Real instructions are recorded at a nested level to enclosing method
+ // and may happen on topmost entry only;
+ // otherwise we have a chain of inlined methods
+ // and each entry holds bcOffset of a call inst in parent method.
+ // Either way needed bcOffset is recorded at child entry
+ const InlineInfoMap::Entry* childCallee = e;
+ while (e) {
+ uint32 depth = e->getInlineDepth();
+ if (depth == inline_depth)
+ {
+ return childCallee->bcOffset;
+ }
+ childCallee = e;
+ e = e->parentEntry;
+ }
+
+ return 0;
}
Index: vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp
===================================================================
--- vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp (revision 593520)
+++ vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp (working copy)
@@ -341,7 +341,7 @@
for (Inst* inst = (Inst*)node->getFirstInst(); inst!=NULL; inst = inst->getNextInst()) {
if (inst->getKind() == Inst::Kind_MethodEntryPseudoInst) {
if (Log::isEnabled()) {
- IRPrinter::printIndent(Log::out(), parentEntry ? parentEntry->getInlineDepth() + 1 : 0);
+ IRPrinter::printIndent(Log::out(), parentEntry ? parentEntry->getInlineDepth() + 1 : 1);
IRPrinter::printInst(Log::out(), inst);
Log::out()<<" bc offset="<getBCOffset()<getInlineDepth();
+ return (parentEntry == 0) ? 1 : 1 + parentEntry->getInlineDepth();
}
};
Index: vm/jitrino/src/optimizer/CodeGenerator.cpp
===================================================================
--- vm/jitrino/src/optimizer/CodeGenerator.cpp (revision 593520)
+++ vm/jitrino/src/optimizer/CodeGenerator.cpp (working copy)
@@ -146,6 +146,7 @@
header++;
if (nativeOffset == nativeOffs) {
Entry* e = (Entry*)((char*)ptr + entryOffset);
+ assert(e->getInlineDepth() > 1);
return e;
}
}
Index: vm/jitrino/src/optimizer/inliner.cpp
===================================================================
--- vm/jitrino/src/optimizer/inliner.cpp (revision 593520)
+++ vm/jitrino/src/optimizer/inliner.cpp (working copy)
@@ -525,18 +525,16 @@
entry->getFirstInst()->unlink();
entry->prependInst(_instFactory.makeLabel());
- uint16 bcOffset = inlineNode->getCallInst()->getBCOffset();
- assert(bcOffset!=ILLEGAL_BC_MAPPING_VALUE);
+ uint16 callerOffset = inlineNode->getCallInst()->getBCOffset();
+ assert(callerOffset!=ILLEGAL_BC_MAPPING_VALUE);
Inst* entryMarker = obj ? _instFactory.makeMethodMarker(MethodMarkerInst::Entry, &methodDesc, obj)
: _instFactory.makeMethodMarker(MethodMarkerInst::Entry, &methodDesc);
- entryMarker->setBCOffset(bcOffset);
+ entryMarker->setBCOffset(callerOffset);
entry->prependInst(entryMarker);
-
Node* retNode = inlinedFlowGraph.getReturnNode();
if (retNode) {
Inst* exitMarker = obj ? _instFactory.makeMethodMarker(MethodMarkerInst::Exit, &methodDesc, obj)
: _instFactory.makeMethodMarker(MethodMarkerInst::Exit, &methodDesc);
- exitMarker->setBCOffset(entryMarker->getBCOffset());
retNode->appendInst(exitMarker);
}
@@ -544,7 +542,6 @@
if (unwindNode) {
Inst* exitMarker = obj ? _instFactory.makeMethodMarker(MethodMarkerInst::Exit, &methodDesc, obj)
: _instFactory.makeMethodMarker(MethodMarkerInst::Exit, &methodDesc);
- exitMarker->setBCOffset(entryMarker->getBCOffset());
unwindNode->appendInst(exitMarker);
}
}
Index: vm/jitrino/src/vm/JITInterface.cpp
===================================================================
--- vm/jitrino/src/vm/JITInterface.cpp (revision 593520)
+++ vm/jitrino/src/vm/JITInterface.cpp (working copy)
@@ -419,6 +419,10 @@
if (Log::cat_rt()->isEnabled()) {
Log::cat_rt()->out() << "GET_INLINED_METHOD()" << ::std::endl;
}
+ if (0 == inline_depth) {
+ assert(0 && "misused inline_depth, must be [1..max_depth]");
+ return 0;
+ }
return Jitrino::GetInlinedMethod(ptr, offset, inline_depth);
}
@@ -429,6 +433,10 @@
if (Log::cat_rt()->isEnabled()) {
Log::cat_rt()->out() << "GET_INLINED_BC()" << ::std::endl;
}
+ if (0 == inline_depth) {
+ assert(0 && "misused inline_depth, must be [1..max_depth]");
+ return 0;
+ }
return Jitrino::GetInlinedBc(ptr, offset, inline_depth);
}
Index: vm/jitrino/src/main/Jitrino.cpp
===================================================================
--- vm/jitrino/src/main/Jitrino.cpp (revision 593520)
+++ vm/jitrino/src/main/Jitrino.cpp (working copy)
@@ -286,21 +286,13 @@
Method_Handle
Jitrino::GetInlinedMethod(InlineInfoPtr ptr, uint32 offset, uint32 inline_depth)
{
- //+1 here because VM counts inlined methods range like: [0...max_depth)
- //where 0 is the first inlined frame.
- //but Jitrino.OPT algorithm counts methods like [0...max_depth]
- //where 0 is an original method
- return runtimeInterface->getInlinedMethod(ptr, offset, inline_depth+1);
+ return runtimeInterface->getInlinedMethod(ptr, offset, inline_depth);
}
uint16
Jitrino::GetInlinedBc(InlineInfoPtr ptr, uint32 offset, uint32 inline_depth)
{
- //+1 here because VM counts inlined methods range like: [0...max_depth)
- //where 0 is the first inlined frame.
- //but Jitrino.OPT algorithm counts methods like [0...max_depth]
- //where 0 is an original method
- return runtimeInterface->getInlinedBc(ptr, offset, inline_depth + 1);
+ return runtimeInterface->getInlinedBc(ptr, offset, inline_depth);
}
bool