measurements obtained with the JIT enabled, whereas
the value denoted by the white bars are obtained with
the JIT disabled.
As a result, we see that the ratio is asymptotic to
1. This means that the cost of the debuggable inter-
preter design pattern compared to the classical visitor
is negligible for deep recursion.
The table below compares the memory consump-
tion of DIDP with VDP. The total number of created
objects is shown for each factorial expression.
Iteration DIDP VDP ratio
fac(100) 102 102 1
fac(200) 202 202 1
fac(400) 402 402 1
fac(900) 902 902 1
fac(10000) 10002 10002 1
fac(70000) 70002 70002 1
During the evaluation of factorial expression, con-
texts are created for each recursion, as well as a mode
and a service. This table shows that the DIDP does
not incur any memory overhead.
The computer used for this experiment is an Intel
Pentium M 1,6GHz, Linux (kernel 2.6.20.1), 512MB
RAM, ST/X 5.2.8.
5 RELATED WORK
Scripting debugging. Marceau et al. (Marceau et al.,
2006) designed a language for a scriptable debug-
ger. The purpose of this debugger is to automatise se-
quences of debugging operations that might be labori-
ous to repeat manually. A classical sequence could be
setting a breakpoint, examining values of some vari-
ables, or resuming execution. Debugging an appli-
cation generally may necessitate repeat this sequence
many times in order to find a single bug. Scripting a
debugger helps in automating such a task.
Similar to the debuggable interpreter pattern, the
scriptable debugger provides primitives to capture
the essential functionality of a debugger: observing
a program’s state, monitoring its control path, and
controlling its execution. This is achieved by explicit
commands embedded in the program. In order to
be debugged, a program must contain explicit trace
points. This is a major difference with the debuggable
interpreter pattern for which program do not need to
be annotated.
Trace library. Hofer et al. (Hofer et al., 2006) pro-
pose a backward-in-time debugger. The Unstuck de-
bugger allows one to navigate the history of the ap-
plication. Their implementation uses a trace library
to collect the events and reconstruct the states. To
generate events (method invocation, variable access
and method return), the methods are instrumented us-
ing ByteSurgeon (Denker et al., 2006), a high-level
library to manipulate method bytecode.
Unstuck assumes that a program is interpreted by
a virtual machine, whereas the debuggable interpreter
design pattern relies on an interpretation driven by a
visitor.
AST instrumentation. The Relational Meta-
Language (RML) (Pop and Fritzson, 2005) is a lan-
guage for writing executable Natural Semantics spec-
ifications. It is used to formally specify program-
ming languages such as Java, Pascal, and MiniML.
The RML debugger is based on an abstract syntax
tree instrumentation that captures and records partic-
ular events. A post-mortem analysis tool is then pro-
vided to walk back and forth in time, display variable
values, and execution points.
The AST is instrumented with debugging anno-
tation related to trace generation. From its design,
the programming environment of RML is limited to
one single debugger per session. On the contrary, our
approach allows several debuggers to coexist.
Grammar weaving. Wu et al. (Wu et al., 2005)
claims that debugging is a concern that crosscuts a do-
main specific language specification. They propose to
use AspectJ
8
to weave the debugging semantics into
the code created by a parser generator.
Their work is restricted to programming lan-
guages that are translated into a general purpose lan-
guage. Our approach is different since it assumes
a program interpretation through a visitor and inter-
preter design pattern.
6 CONCLUSION AND FUTURE
WORK
This paper presents a general approach for imple-
menting and realizing a debugger for a visitor-like in-
terpreter. It extends a visitor with a set of hooks em-
bedded in the visiting methods. The context, primar-
ily used to hold variables bindings, has been extended
with a reference to a parent context, and keeps a refer-
ence to the node currently being interpreted. A debug-
ger service models the different operations available
by means of a set of modes.
To conclude, the Debuggable Interpreter design
pattern offers the benefits of the coexistence of mul-
8
eclipse.org/aspectj/
ICSOFT 2007 - International Conference on Software and Data Technologies
28