Return-Path:
- This document gives practical instructions on how to debug
- the DRL virtual machine and its baseline just-in-time
- compiler Jitrino.JET. For a definition of components and
- details on their internal structure, consult the DRL
- Virtual Machine Developer’s Guide supplied with
- the DRLVM image.
-
- The document includes two groups of debugging tips, one for
- VM tips, and the other for JIT compiler tips, as shown
- below.
-
- Debugging the Virtual Machine
-
+
+ This document gives practical instructions on how to debug the DRL virtual machine
+ and its baseline just-in-time compiler Jitrino.JET. For a definition of components
+ and details on their internal structure, consult the
+ DRL Virtual Machine Developer’s Guide supplied with the DRLVM image.
+
+ The document includes two groups of debugging tips, one for VM tips, and the other
+ for JIT compiler tips, as shown below.
+
+ Debugging the Virtual Machine
+
- Debugging the Jitrino.JET Baseline
- Compiler
-
- How to enable tracing in
- Jitrino.JET?
-
- Back to top
-
- This section gives an insight into debugging the DRL virtual
- machine version 1.0 and provides tips on resolving
- non-standard debugging issues.
-
- This section gives instructions on different scenarios of
- debugging the VM source code.
-
- For ordinary tests, start the ij executable with the
- debugger enabled, as follows:
-
- On Windows*
-
- On Linux*
-
- Debugging the DRL Virtual Machine and the
- JIT Compiler
-
-
-
+ Debugging the DRL Virtual Machine and the JIT Compiler
+
+
+
-
-
-
-
-
-
- Debugging the Virtual Machine
-
-
- How to debug the VM?
-
-
- Basic Debugging Steps
-
-
-
- vm\build\vm.sln
.
- ij
executable.
- Select the Debugging tab and specify the
- command and command arguments.
- zlib1.dll
to the
- location of the VM executable.
-
-
LD_LIBRARY_PATH
to point to the
- deploy/jre/bin
directory. Change the working
- directory to the location of the VM executable and run:
-
+
+ How to get more of your debugging? +
+ ++ Debugging the Jitrino.JET Baseline Compiler +
++++ How to enable tracing in Jitrino.JET? +
+ + +
+ Back to top +
++ This section gives an insight into debugging the DRL virtual machine version 1.0 + and provides tips on resolving non-standard debugging issues. +
++ This section gives instructions on different scenarios of debugging the VM source + code. +
++ For ordinary tests, start the ij executable with the debugger enabled, as follows: +
++ On Windows*
+
+ vm\build\vm.sln
. ij
executable. Select the Debugging tab and specify
+ the command and command arguments. zlib1.dll
to the location of the VM executable.
+ + On Linux*
+LD_LIBRARY_PATH
to point to the deploy/jre/bin
+ directory. Change the working directory to the location of the VM executable and
+ run:
+ gdb ij-
+
run <your_params>-
- Back to top -
-- To attach to the running VM process, do the following: -
-- On Windows* -
-- On Linux* -
-- Run: -
-+ + ++ Back to top +
++ Attaching the Debugger to the Live Process +
++ To attach to the running VM process, do the following: +
++ On Windows*
++
+- Start Visual Studio* .
+- Go Debug > Processes.
+- Select the VM process and click Attach.
+
+ If you built the VM in the debug mode, the Microsoft Debug Runtime + window appears. Click the Debug button to go to the crash point. ++ On Linux*
++ Run: +
+gdb –p <PID of ij>-- If the VM crashed during execution, use the core dump to - analyze the crash: -
-++ If the VM crashed during execution, use the core dump to analyze the crash: +
+gdb ij core-- Back to top -
-- How to get more from your - debugging? -
-- This section includes some tips on optimizing the debug - process and getting more debug information. -
-- Configuration of tracing -
-- Consult the Getting Started guide delivered with - DRLVM bundle for information on VM standard and non-standard - configuration options. Tracing-related options might be - useful for debugging purposes. -
-- Native stack examination -
-- The debugger might draw the stack incorrectly when the JIT - or native stubs are involved. To avoid this, set esp as the - memory location and 4-byte integer values as the output - format. As a result, you can examine the stack word by word - and look into the code for each number 0x00… by using - the Disassembly window. -
---- When the VM has crashed -
-- A very specific case on Windows*: the VM - has crashed and you only see the stack frame in the call - stack
-0x00000000
. This means that the - program has jumped or called to a null pointer. -- You might still get the stack trace. For that, do the - following: -
--
-- - Open the Disassembly window. -
-- - Find any ret instruction with no parameters in the - memory space.
-
- Open any source file, open the context menu, and - select Go to - Disassembly to find any -ret
instruction. -- - When found, select the ret instruction and click - Set Next Statement in the context - menu. -
-- - Type
-F11
to go a single instruction.
- You may see several instructions near the current - point of execution. If you see a call instruction, you - have found an appropriate call site and you can see - the call stack in the Call Stack - window. If you have found a wrong call site, repeat - the instruction from step 2. -- Back to top -
-- Java* stack examination -
-- On Windows* -
-- Running the VM in the interpreter mode, you can get Java* methods stack trace almost at any point of - execution. For that, break the execution of the VM and - select the Interpreter frame in the Visual - Studio* Call Stack window. - Then, in the watch window, add the watch -
-stack_dump()
. The stack dump appears in VM - output window. Running the VM in the JIT mode, use the -st_print()
function for the same purpose. -- On Linux* -
-- Use the
-gdb
command print and specify the -stack_dump
orst_print
in the - interpreter or the JIT compiler mode respectively. -- Setting smart breakpoints -
-- On Windows* / IA-32 -
-- Place breakpoints in source code by inserting calls to the - _CrtDbgBreak() function. Placing the call inside a condition - calls the function only for the specified case you need to - debug. Analogously, you can use the Windows* API function DebugBreak() or print INT 3. -
-- Note
-
- This requires recompiling the VM. -- On Linux* -
-- Run the following: -
-++ Back to top +
++ How to get more from your debugging? +
++ This section includes some tips on optimizing the debug process and getting more + debug information. +
++ Configuration of tracing +
++ Consult the Getting Started + guide delivered with DRLVM bundle for information on VM standard and non-standard + configuration options. Tracing-related options might be useful for debugging purposes. +
++ Native stack examination +
++ The debugger might draw the stack incorrectly when the JIT or native stubs are involved. + To avoid this, set esp as the memory location and 4-byte integer values as the output + format. As a result, you can examine the stack word by word and look into the code + for each number 0x00… by using the Disassembly window. +
++ When the VM has crashed +
++ A very specific case on Windows*: the VM has crashed and you only + see the stack frame in the call stack
+0x00000000
. This means that the + program has jumped or called to a null pointer. ++ You might still get the stack trace. For that, do the following: +
++
+- Open the Disassembly window.
+- Find any ret instruction with no parameters in the memory space.
+
+ Open any source file, open the context menu, and select Go to + Disassembly to find anyret
instruction.- When found, select the ret instruction and click Set Next Statement + in the context menu.
+- Type
+F11
to go a single instruction.
+ You may see several instructions near the current point of execution. If you see + a call instruction, you have found an appropriate call site and you can see the + call stack in the Call Stack window. If you have found a wrong + call site, repeat the instruction from step 2.+ Back to top +
++ Java* stack examination +
++ On Windows*
++ Running the VM in the interpreter mode, you can get Java* methods + stack trace almost at any point of execution. For that, break the execution of the + VM and select the Interpreter frame in the Visual Studio* + Call Stack window. Then, in the watch window, add the watch
+stack_dump()
. + The stack dump appears in VM output window. Running the VM in the JIT mode, use + thest_print()
function for the same purpose. ++ On Linux*
++ Use the
+gdb
command print and specify thestack_dump
or +st_print
in the interpreter or the JIT compiler mode respectively. ++ Setting smart breakpoints +
++ On Windows* / IA-32
++ Place breakpoints in source code by inserting calls to the
+_CrtDbgBreak()
+ function. Placing the call inside a condition calls the function only for the specified + case you need to debug. Analogously, you can use the Windows* API + functionDebugBreak()
or printINT 3
. ++ Note
++ This requires recompiling the VM.
++ On Linux*
++ Run the following: +
+__asm {int 3}-- Back to top -
-- Handling Java* threads as native threads -
-- DRL VM has 1:1 mapping between native threads visible in the - debugger and Java* threads.
-
- To work with Java* threads individually, - freeze the threads you do not need with the help of the - debugger, and continue execution of other threads. -- Debugging deadlocks with the CriticalSection synchronization - primitive -
-- The
-CriticalSection
primitive is a common cause - of deadlocks. If the code has stopped at a critical section, - you can try to find the thread that owns this primitive. -- On Windows* -
-- The file WinNT.H located in <PlatformSDK>\Include - contains the definition for the structure - _RTL_CRITICAL_SECTION, which contains the description of the - CriticalSection primitive. You can get the owning thread for - the CriticalSection primitive in a number of ways, as - indicated below. -
---- Lookup in Memory -
-- On Windows* -
-- While debugging the code in Visual Studio, do the - following: -
--
-- - Go Debug > - Windows > Memory - 1. -
-- - In the address line, enter the address of the critical - section. -
-- - Open the context menu and select 4-byte Integers. This - sets the fourth DWORD from the beginning of the - critical section as the owning thread ID in - hexadecimal representation. -
-- Note
-
- Visual Studio* displays thread IDs - in decimal representation. -- In the watch window --- In the watch window of Visual Studio*, - insert the following: -
-++ Back to top +
++ Handling Java* threads as native threads +
++ DRL VM has 1:1 mapping between native threads visible in the debugger and Java* threads.
+
+ To work with Java* threads individually, freeze the threads you + do not need with the help of the debugger, and continue execution of other threads. ++ Debugging deadlocks with the CriticalSection synchronization primitive +
++ The
+CriticalSection
primitive is a common cause of deadlocks. If the + code has stopped at a critical section, you can try to find the thread that owns + this primitive. ++ On Windows*
++ The file
+WinNT.H
located in<PlatformSDK>\Include
+ contains the definition for the structure_RTL_CRITICAL_SECTION
, which + contains the description of the CriticalSection primitive. You can get the owning + thread for the CriticalSection primitive in a number of ways, as indicated below. ++ Lookup in Memory
++ While debugging the code in Visual Studio, do the following: +
++
+- Go Debug > Windows > Memory 1. +
+- In the address line, enter the address of the critical section.
+- Open the context menu and select 4-byte Integers. This sets the fourth DWORD from + the beginning of the critical section as the owning thread ID in hexadecimal representation. +
++ Note
++ Visual Studio* displays thread IDs in decimal representation.
++ In the watch window
++ In the watch window of Visual Studio*, insert the following: +
+* ((int* )<cs-ptr>+3)-- Where
-<cs-ptr>
is the address of your - critical section -- On Linux* -
-- The file
-/usr/include/bits/pthreadtypes.h
- contains the description of thepthread_mutex_t
- type. To get the ID of the thread owning the -CriticalSection
primitive, in gdb execute: -++ Where
+<cs-ptr>
is the address of your critical section ++ On Linux*
++ The file
+/usr/include/bits/pthreadtypes.h
contains the description + of thepthread_mutex_t
type. To get the ID of the thread owning the +CriticalSection
primitive, ingdb
execute: +x/4w <address of your mutex primitive>-- The third word in the output contains the owning thread - descriptor you are looking for. -
-- Getting a class name for an object -
-- You can often need to find out the class name for a Java* object used in VM code. For example, you may - need to get the class name for an object of the type -
-ManagedObject *
(which is a direct pointer to - the heap). For that, insert the following expression into - the watch window in Visual Studio on Windows* or print the command ofgdb
on - Linux* : -((VTable*)(*((int - *)obj)))->clss->name->bytes
-- Variables of the types jobject and -
-Object_Handle
are references to -ManagedObject *
types. These structures contain - a single element, a pointer toManagedObject *
- type object. To use the expression above, de-reference the - variable, for example, substitutingobj
in the - expression above with a cast to(ManagedObject - *)(*(int *)obj)
. -- Back to top -
-- Debugging the Jitrino.JET - Baseline Compiler -
-- To use debugging and tracing in Jitrino.JET, use the debug - build or the release build with the
-JET_PROTO
- macro defined. See the filejdefs.h
for a - definition of the available flags. -- How to enable tracing in - Jitrino.JET? -
-- Currently, Jitrino.JET provides no interface or command line - to control tracing options. To enable tracing, set the -
-compile_flags
variable at the entry point to - the methodCompiler::compile()
. At that point, - the global variableCompiler::g_methodsSeen
- contains the ID of the method being compiled, and the - instance variablem_fname
contains its fully - qualified name with no signature. Obtain these options - through a call to -Compiler::m_infoBlock.get_flags()
. -- How to configure trace - logging? -
-- Tracing flags control compilation results output and trace - run-time execution, as described below. Tracing results are - created in each run in the directory where the -
-ij
executable starts: compilation results are - injet.log
, and run-time output is in -jet.rt.log
. -- Group 1: Compilation Results Tracing -
-- The following flags control tracing compilation of a method: -
-
DBG_TRACE_SUMM
prints a
- short summary about the compiled method: the compilation
- status (success or failure), the name, signature,
- bytecode size, the start and end addresses of the
- generated code, and the compilation ID (the sequential
- number of the method compiled by Jitrino.JET).
- DBG_DUMP_BBS
dumps the
- bytecode and marks up basic blocks boundaries.
- DBG_TRACE_CG
prints
- information about each compiled bytecode instruction: the
- state of the Java* operand stack before
- the instruction, the known state of local variables at
- the given point, and the native code generated for the
- instruction. The order instructions appear in the log
- file is the depth-first order, the same as when
- processing instructions during compilation. See the file
- trace.cpp, function toStr2()
for the legend
- of the operand stack items print-out.
- DBG_TRACE_LAYOUT
prints the
- results of the code layout, mostly, the address ranges
- for the basic blocks.
- DBG_DUMP_CODE
dumps
- generated code for the given method, the method’s
- actual addresses, intermixed with appropriate bytecode
- instructions.
-
- Note
- For DBG_DUMP_CODE
and
- DBG_TRACE_CG
, Jitrino.JET can print
- disassembled code in addition to raw hexadecimal
- dumps. For that, the compiler requires an external
- disassembler. Currently, Jitrino.JET is configured to
- use the external library
- lwdis.dll/liblwdis.so
that must be
- located in the same directory as
- jitrino.dll/libjitrino.so
. The name lwdis
- stands for light weight disassembler. The library must
- export the function disasm()
. Refer to
- the file trace.cpp, the DISFUNC
- definition for details on calling convention and
- signature.
+
+ The third word in the output contains the owning thread descriptor you are looking + for. +
+
+ You can often need to find out the class name for a Java* object
+ used in VM code. For example, you may need to get the class name for an object of
+ the type ManagedObject *
(which is a direct pointer to the heap). For
+ that, insert the following expression into the watch window in Visual Studio on
+ Windows* or print the command of gdb
on Linux*
+ :
+
((VTable*)(*((int*)obj)))->clss->name->bytes+
+ Variables of the types jobject and Object_Handle
are references to
+ ManagedObject *
types. These structures contain a single element, a
+ pointer to ManagedObject *
type object. To use the expression above,
+ de-reference the variable, for example, substituting obj
in the expression
+ above with a cast to (ManagedObject *)(*(int *)obj)
.
+
+ Back to top +
+
+ To use debugging and tracing in Jitrino.JET, use the debug build or the release
+ build with the JET_PROTO
macro defined. See the file jdefs.h
+ for a definition of the available flags.
+
+ Currently, Jitrino.JET provides no interface or command line to control tracing
+ options. To enable tracing, set the compile_flags
variable at the entry
+ point to the method Compiler::compile()
. At that point, the global
+ variable Compiler::g_methodsSeen
contains the ID of the method being
+ compiled, and the instance variable m_fname
contains its fully qualified
+ name with no signature. Obtain these options through a call to Compiler::m_infoBlock.get_flags()
.
+
+ Tracing flags control compilation results output and trace run-time execution, as
+ described below. Tracing results are created in each run in the directory where
+ the ij
executable starts: compilation results are in jet.log
,
+ and run-time output is in jet.rt.log
.
+
+ The following flags control tracing compilation of a method: +
+DBG_TRACE_SUMM
prints a short summary about the compiled
+ method: the compilation status (success or failure), the name, signature, bytecode
+ size, the start and end addresses of the generated code, and the compilation ID
+ (the sequential number of the method compiled by Jitrino.JET). DBG_DUMP_BBS
dumps the bytecode and marks up basic
+ blocks boundaries. DBG_TRACE_CG
prints information about each compiled
+ bytecode instruction: the state of the Java* operand stack before
+ the instruction, the known state of local variables at the given point, and the
+ native code generated for the instruction. The order instructions appear in the
+ log file is the depth-first order, the same as when processing instructions during
+ compilation. See the file trace.cpp, function toStr2()
for the legend
+ of the operand stack items print-out. DBG_TRACE_LAYOUT
prints the results of the code layout,
+ mostly, the address ranges for the basic blocks. DBG_DUMP_CODE
dumps generated code for the given method,
+ the method’s actual addresses, intermixed with appropriate bytecode instructions.
+ + Note
+
+ For DBG_DUMP_CODE
and DBG_TRACE_CG
, Jitrino.JET can print
+ disassembled code in addition to raw hexadecimal dumps. For that, the compiler requires
+ an external disassembler. Currently, Jitrino.JET is configured to use the external
+ library lwdis.dll/liblwdis.so
that must be located in the same directory
+ as jitrino.dll/libjitrino.so
. The name lwdis stands for light weight
+ disassembler. The library must export the function disasm()
. Refer
+ to the file trace.cpp, the DISFUNC
definition for details on calling
+ convention and signature.
DBG_CHECK_STACK
prints
- nothing but instruments code to check stack integrity.
- The methods compiled by Jitrino.JET use EBP-based frames.
- These frames can mask errors, for example, wrong
- convention usage with a VM helper call. Using this option
- performs run-time checks and INT3 raised in case the
- stack integrity broken.
- DBG_BRK
inserts INT3 at the
- method entry point, so it can be stopped in the debugger.
-
-
- Note
- An instance variable of class
- Compiler
, dbg_break_pc
can
- be used to insert INT3
at the specified
- program counter of a method.
+
DBG_CHECK_STACK
prints nothing but instruments code
+ to check stack integrity. The methods compiled by Jitrino.JET use EBP-based frames.
+ These frames can mask errors, for example, wrong convention usage with a VM helper
+ call. Using this option performs run-time checks and INT3 raised in case the stack
+ integrity broken. DBG_BRK
inserts INT3 at the method entry point, so
+ it can be stopped in the debugger.
+ + Note
+
+ An instance variable of class Compiler
, dbg_break_pc
can
+ be used to insert INT3
at the specified program counter of a method.
- Back to top -
-- The following flags trace run-time life of the method: -
-DBG_TRACE_EE
prints
- entering: <method-name>
and exiting:
- <method-name>
at the method entrance
- and exit points.+ Back to top +
++ The following flags trace run-time life of the method: +
+DBG_TRACE_EE
prints entering: <method-name>
+ and exiting: <method-name>
at the method entrance and exit points.DBG_TRACE_BC
traces
- execution of every bytecode instruction by printing a
- string of the following format before executing the
- instruction: <method-name> @
- PC=<pc>
DBG_TRACE_BC
traces execution of every bytecode instruction
+ by printing a string of the following format before executing the instruction:
+ <method-name> @ PC=<pc>
- Notes -
-
- The output string for DBG_TRACE_EE
and
- DBG_TRACE_BC
uses a specific format: before the
- string, an estimated call depth is printed and the string
- gets indentation based on the call depth. After the string,
- the string ID is printed. The estimated call depth may help
- to identify where a method was called from. The string ID
- can be helpful for setting a conditional breakpoint in the
- debugger for a complex scenario. For that, set a condition
- for the static variable cnt in the function
- rt_dbg
, file trace.cpp
.
-
- Turning on the option DBG_TRACE_BC
may slow
- down execution extremely and may result to a gigantic file
- jet.rt.log
.
-
DBG_TRACE_RT
traces
- run-time support calls, for example, getting address of
- ‘this’, support for root set enumeration and
- stack unwinding.+ Notes
+
+ The output string for DBG_TRACE_EE
and DBG_TRACE_BC
uses
+ a specific format: before the string, an estimated call depth is printed and the
+ string gets indentation based on the call depth. After the string, the string ID
+ is printed. The estimated call depth may help to identify where a method was called
+ from. The string ID can be helpful for setting a conditional breakpoint in the debugger
+ for a complex scenario. For that, set a condition for the static variable cnt in
+ the function rt_dbg
, file trace.cpp
.
+ Turning on the option DBG_TRACE_BC
may slow down execution extremely
+ and may result to a gigantic file jet.rt.log
.
+
DBG_TRACE_RT
traces run-time support calls, for example,
+ getting address of ‘this’, support for root set enumeration and stack
+ unwinding.
- Note
- The output goes to jet.log, with the address (both
- native and PC) where the event happens, and some other info.
-
- Back to top -
-- To identify one or more problematic methods with another - stable JIT compiler, use the execution manager. With this - technique, some methods are compiled by the stable JIT, and - the rest goes to the JIT being debugged. With a simple - binary search, you can find the problematic method rather - quickly. -
-
- Note
- Try turning off parallel compilation when using this
- technique (refer to VM’s
- -Xno_parallel_jit
option).
-
- To get details in case of a crash with no adequate - stack trace or IP location available, turn on the option - DBG_TRACE_EE to see, in which method the crash happens. As - the second step, turn on DBG_TRACE_BC for this particular - method to find the exact bytecode instruction. Often, this - cuts the code to analyze down to 5-10 native instructions. -
-- To set a breakpoint and stop execution at a specific - point, use trace.cpp:rt_dbg to break execution at the - specified bytecode instruction or at the entry point of the - specified method. -
-- Back to top -
-
- This is an example of code that turns on various tracing
- scenarios. The code must be placed in the method
- Compiler::compile(
).
-
- #if defined(_DEBUG) || defined(JET_PROTO) -
-- // - Turns on a short summary of all methods -
-- compile_flags |= DBG_TRACE_SUMM; -
-- // A - handy constant -
-- static const unsigned TRACE_CG = DBG_DUMP_BBS | DBG_TRACE_CG | -
-- DBG_TRACE_LAYOUT - | DBG_TRACE_SUMM | -
-- DBG_DUMP_CODE; -
-- // For - methods in the range (1000;15000), print out the complete - code generator dumps -
-- if (g_methodsSeen>1000 && g_methodsSeen<15000) { -
-- compile_flags |= TRACE_CG; -
-- } -
-- // For - methods getSomeValue() and for all methods in class - MyClass, -
-- // - trace enter and exit -
-- if (NULL != strstr(m_fname, "::getSomeValue") || -
-- NULL != strstr(m_fname, "MyClass::") ) { -
-- compile_flags |= DBG_TRACE_EE; -
-- } -
-- // For - the method crashes_some_times() in class MyClass trace - every -
-- // - bytecode execution: the last bytecode in the log is the most - probable -
-- // - cause of the failure -
-- if (!strcmp(m_fname, - "MyClass::crashes_some_times")) { -
-- compile_flags |= DBG_TRACE_EE|DBG_TRACE_BC; -
-- } -
-- // - Break into debugger (INT3) at the entry of the - stop_at_entry() method -
-- if (!strcmp(m_fname, "MyClass::stop_at_entry")) - { -
-- compile_flags |= DBG_BRK; -
-- } -
-- // - Break into debugger (INT3) inside the method -
-- if (!strcmp(m_fname, - "MyClass::stop_somewhere_in_the_middle")) { -
-- dbg_break_pc = 50; -
-- } -
-- // - Trace run-time support calls: unwind, getting the address of - 'this', root -
-- // set - enumeration -
-- if (!strcmp(m_fname, - "MyClass::something_wrong_with_unwind_here")) { -
-- compile_flags |= DBG_TRACE_RT; -
-- } -
-- // - By-pass run-time tracing for java/* classes -
-- if (m_fname == strstr(m_fname, "java/")) { -
-- compile_flags &= ~(DBG_TRACE_EE|DBG_TRACE_BC); -
-- } -
-- #endif -
- -- Back to top -
-- * Other brands and names are the property of - their respective owners. -
- ++ Note
++ The output goes to jet.log, with the address (both native and PC) where the event + happens, and some other info. +
++ Back to top +
++ To identify one or more problematic methods with another stable JIT compiler, use + the execution manager. With this technique, some methods are compiled by the stable + JIT, and the rest goes to the JIT being debugged. With a simple binary search, you + can find the problematic method rather quickly. +
++ Note
+
+ Try turning off parallel compilation when using this technique (refer to VM’s
+ -Xno_parallel_jit
option).
+
+ To get details in case of a crash with no adequate stack trace or IP location
+ available, turn on the option DBG_TRACE_EE
to see, in which method
+ the crash happens. As the second step, turn on DBG_TRACE_BC
for this
+ particular method to find the exact bytecode instruction. Often, this cuts the code
+ to analyze down to 5-10 native instructions.
+
+ To set a breakpoint and stop execution at a specific point, use trace.cpp:rt_dbg
+ to break execution at the specified bytecode instruction or at the entry point of
+ the specified method.
+
+ Back to top +
+
+ This is an example of code that turns on various tracing scenarios. The code must
+ be placed in the method Compiler::compile(
).
+
+ #if + + defined(_DEBUG) || + defined(JET_PROTO) +
++ + // Turns on a short summary of all methods +
++ + compile_flags |= DBG_TRACE_SUMM; +
++ + // A handy constant +
++ + static const unsigned + TRACE_CG = DBG_DUMP_BBS + | DBG_TRACE_CG | +
++ + DBG_TRACE_LAYOUT | DBG_TRACE_SUMM | +
++ + DBG_DUMP_CODE; +
++ + // For methods in the range (1000;15000), print out the complete code generator + dumps +
++ + if (g_methodsSeen>1000 && + g_methodsSeen<15000) { +
++ + compile_flags |= TRACE_CG; +
++ } +
++ + // For methods getSomeValue() and for all methods in class MyClass, +
++ + // trace enter and exit +
++ + if (NULL != + strstr(m_fname, "::getSomeValue") + || +
++ + NULL != strstr(m_fname, + "MyClass::") ) { +
++ + compile_flags |= DBG_TRACE_EE; +
++ } +
++ + // For the method crashes_some_times() in class MyClass trace every +
++ + // bytecode execution: the last bytecode in the log is the most probable +
++ + // cause of the failure +
++ + if (!strcmp(m_fname, + "MyClass::crashes_some_times")) { +
++ + compile_flags |= DBG_TRACE_EE|DBG_TRACE_BC; +
++ } +
++ + // Break into debugger (INT3) at the entry of the stop_at_entry() method +
++ + if (!strcmp(m_fname, + "MyClass::stop_at_entry")) { +
++ + compile_flags |= DBG_BRK; +
++ } +
++ + // Break into debugger (INT3) inside the method +
++ + if (!strcmp(m_fname, + "MyClass::stop_somewhere_in_the_middle")) { +
++ + dbg_break_pc = 50; +
++ } +
++ + // Trace run-time support calls: unwind, getting the address of 'this', root +
++ + // set enumeration +
++ + if (!strcmp(m_fname, + "MyClass::something_wrong_with_unwind_here")) { +
++ + compile_flags |= DBG_TRACE_RT; +
++ } +
++ + // By-pass run-time tracing for java/* classes +
++ + if (m_fname == + strstr(m_fname, "java/")) { +
++ + compile_flags &= ~(DBG_TRACE_EE|DBG_TRACE_BC); +
++ } +
++ #endif +
++ Back to top +
++ * Other brands and names are the property of their respective owners. +
+