* configure.ac: New switch for disabling -O2 (--disable-optimizations).
[cacao.git] / doc / assertions.tex
1 \documentclass{article}%
2 \usepackage{amsmath}
3 \usepackage{amsfonts}
4 \usepackage{amssymb}
5 \usepackage{graphicx}
6 \usepackage{listings}
7 \lstloadlanguages{Java,C}
8 \lstset{basicstyle=\scriptsize, numbers=left, tabsize=4, frame=none, breaklines=true}
9 %-------------------------------------------
10 \newtheorem{theorem}{Theorem}
11 \newtheorem{acknowledgement}[theorem]{Acknowledgement}
12 \newtheorem{algorithm}[theorem]{Algorithm}
13 \newtheorem{axiom}[theorem]{Axiom}
14 \newtheorem{case}[theorem]{Case}
15 \newtheorem{claim}[theorem]{Claim}
16 \newtheorem{conclusion}[theorem]{Conclusion}
17 \newtheorem{condition}[theorem]{Condition}
18 \newtheorem{conjecture}[theorem]{Conjecture}
19 \newtheorem{corollary}[theorem]{Corollary}
20 \newtheorem{criterion}[theorem]{Criterion}
21 \newtheorem{definition}[theorem]{Definition}
22 \newtheorem{example}[theorem]{Example}
23 \newtheorem{exercise}[theorem]{Exercise}
24 \newtheorem{lemma}[theorem]{Lemma}
25 \newtheorem{notation}[theorem]{Notation}
26 \newtheorem{problem}[theorem]{Problem}
27 \newtheorem{proposition}[theorem]{Proposition}
28 \newtheorem{remark}[theorem]{Remark}
29 \newtheorem{solution}[theorem]{Solution}
30 \newtheorem{summary}[theorem]{Summary}
31 \newenvironment{proof}[1][Proof]{\textbf{#1.} }{\ \rule{0.5em}{0.5em}}
32
33 \begin{document}
34
35 \title{Assertion support \\for the CACAO Virtual Machine}
36 \author{{Gregor Kaufmann}
37 \\0247381 033 534
38 \\gregor@complang.tuwien.ac.at}
39 \date{January 1, 2008}
40 \maketitle
41 \pagebreak
42
43 \tableofcontents
44 \pagebreak
45
46
47 \section{Introduction to assertions in Java}
48 \subsection{General Introduction}
49 The assertion keyword in Java allows to assert the correctness of assumptions made in a program. It was first introdcuded in JDK 1.2 (see JSR41\footnote{http://jcp.org/aboutJava/communityprocess/review/jsr041/publicDraft.html}). An assertion works on an expression, evaluating to a boolean type, that must be true during the execution of a program (or else the execution halts and an exception gets thrown). Short example: a function that calculates from celsius to kelvin. This function might use an assertion to assure that the calculated value is not below 0.
50
51 An assertion statement comes in two forms:
52 \begin{itemize}
53 \item \verb'assert BooleanExpression ;'
54 \item \verb'assert BooleanExpression : ValueExpression ;'
55 \end{itemize}
56 The "BooleanExpression" can be any java expression resulting in a boolean value. If this "BoolenExpression" evalutes to false an (unnamed) AssertionError gets thrown. The second form of the assertion statement is used to generate detailed error messages: the value of "ValueExpression" gets passed to the constructor of the thrown AssertionError exception, building a more detailed error message. An assertion statement is equal to: if (BooleanExpression == false) throw new AssertionError(ValueExpression); (without the possibility to easily turn on/off this code at runtime).
57 Examples:
58 \begin{itemize}
59 \item \verb'assert val < 10;'
60 \item \verb'assert val > 99: val;'
61 \item \verb'assert isValid(val): val;'
62 \item \verb'assert val.isEnabled(): val.getStatus();'
63 \end{itemize}
64
65 \pagebreak
66 \subsection{Interpreter options}
67 Assertions can be turned on or off at runtime (turned off by default). The following options for the interpreter are available (\verb'>'JDK1.2 and \verb'>'CACAO-0.98):
68 \begin{itemize}
69 \item \verb'-ea[:<packagename>...|:<classname>]'
70 \item \verb'-enableassertions[:<packagename>...|:<classname>]'
71 \item \verb'-da[:<packagename>...|:<classname>]'
72 \item \verb'-disableassertions[:<packagename>...|:<classname>]'
73 \item \verb'-esa | -enablesystemassertions'
74 \item \verb'-dsa | -disablesystemassertions}' 
75 \end{itemize}
76 Detailed explanation of the available options:
77 \begin{itemize}
78 \item{\verb'-enableassertions/-ea' -- \tiny{Turns on assertions for all non-system/user classes}}
79 \item{\verb'-disableassertions/-da' -- \tiny{Turns off assertions for all non-system/user classes}}
80 \item{\verb'-enablesystemassertions/-esa' -- \tiny{Turns on assertions for all system/non-user classes}}
81 \item{\verb'-disablesystemassertions/-dsa' -- \tiny{Turns off assertions for all system/non-user classes}}
82 \item{\verb'-enableassertions/-ea:my.package...' -- \tiny{Turns on assertions for all classes in the "my.package" package (and all subpackages)}}
83 \item{\verb'-disableassertions/-da:my.package...' -- \tiny{Turns off assertions for all classes in the "my.package" package (and all subpackages)}}
84 \item{\verb'-enableassertions/-ea:Myclass' -- \tiny{Turns on assertions a class named "Myclass"}}
85 \item{\verb'-disableassertions/-da:Myclass' -- \tiny{Turns off assertions a class named "Myclass"}}
86 \end{itemize}
87 Note 1: Specifing multiple class/package names is possible.
88 \\
89 \\
90 Note 2: The assertion switches -ea/-da/-esa/-dsa are currently not implemented correctly in cacao+classpath (use cacao+openjdk or a patched classpath [see section \ref{see1}]).
91 \pagebreak
92 \subsection{Bytecode of an assertion statement} \label{bytecode}
93 The following example shows how an assertion statement is translated into bytecode.
94 \\
95 \\
96 I've compiled the following class with JDK-6.0 (other compilers produce slightly different bytecode).
97 \begin{lstlisting}[language=Java]
98 public class Test {
99     public static void main(String[] args) {
100         int x = 1;
101         assert x == 2 : x;
102     }
103 }
104 \end{lstlisting}
105 The following bytecode gets produced:
106 \\
107 \begin{lstlisting}[language=Java]
108 static {};
109   Code:
110    0:   ldc\_w   #5; //class Test
111    3:   invokevirtual   #6; //Method java/lang/Class.desiredAssertionStatus:()Z
112    6:   ifne    13
113    9:   iconst\_1
114    10:  goto    14
115    13:  iconst\_0
116    14:  putstatic       #2; //Field \$assertionsDisabled:Z
117    17:  return
118 \end{lstlisting}
119 A static block is used to iniatilizes the boolean variable describing the assertion status of the class "Test".
120 The assertion status, as set by the user/vm for, gets loaded (lines 3,4), and saved into constant\_pool[2] (line 9).
121 \\
122 \begin{lstlisting}[language=Java]
123 public static void main(java.lang.String[]);
124   Code:
125    0:   iconst\_1
126    1:   istore\_1
127    2:   getstatic       #2; //Field \$assertionsDisabled:Z
128    5:   ifne    22
129    8:   iload\_1
130    9:   iconst\_2
131    10:  if\_icmpeq       22
132    13:  new     #3; //class java/lang/AssertionError
133    16:  dup
134    17:  iload\_1
135    18:  invokespecial   #4; //Method java/lang/AssertionError."<init>":(I)V
136    21:  athrow
137    22:  return
138 \end{lstlisting}
139 The assertion status gets loaded from constant\_pool[2] (line 5), if assertions are disabled the function returns immediatly (lines 6,15). Otherwise, the assertion statement gets evaluated and an AssertionError exception gets thrown (lines 6-15).
140
141 \pagebreak
142 \section{Implementation of java assertions in CACAO}
143
144 When I started working on the assertion support for cacao, a basic functionality to toggle assertions on and off was already implemented. It was possible to toggle assertions on and off at a systemwide level, but this only worked when cacao was used together with the GNU classpath classes. Because at least something was already implemented, I decided to start my work on cacao+classpath.
145 \\
146 \\
147 Each class implements a method called desiredAssertionStatus that returns the desired assertion status of a class, see section \ref{bytecode} on how this is used by an assertion statement.
148 \\
149 \\
150 The desiredAssertionStatus method in java.lang.Class of classpath looks like this:
151 \begin{lstlisting}[language=Java,firstnumber=1216]
152   public boolean desiredAssertionStatus()
153   {
154     ClassLoader c = getClassLoader();
155     Object status;
156     if (c == null)
157       return VMClassLoader.defaultAssertionStatus();
158     if (c.classAssertionStatus != null)
159       synchronized (c)
160         {
161           status = c.classAssertionStatus.get(getName());
162           if (status != null)
163             return status.equals(Boolean.TRUE);
164         }
165     else
166       {
167         status = ClassLoader.StaticData.
168                     systemClassAssertionStatus.get(getName());
169         if (status != null)
170           return status.equals(Boolean.TRUE);
171       }
172     if (c.packageAssertionStatus != null)
173       synchronized (c)
174         {
175           String name = getPackagePortion(getName());
176           if ("".equals(name))
177             status = c.packageAssertionStatus.get(null);
178           else
179             do
180               {
181                 status = c.packageAssertionStatus.get(name);
182                 name = getPackagePortion(name);
183               }
184             while (! "".equals(name) && status == null);
185           if (status != null)
186             return status.equals(Boolean.TRUE);
187         }
188     else
189       {
190         String name = getPackagePortion(getName());
191         if ("".equals(name))
192           status = ClassLoader.StaticData.
193                     systemPackageAssertionStatus.get(null);
194         else
195           do
196             {
197               status = ClassLoader.StaticData.
198                         systemPackageAssertionStatus.get(name);
199               name = getPackagePortion(name);
200             }
201           while (! "".equals(name) && status == null);
202         if (status != null)
203           return status.equals(Boolean.TRUE);
204       }
205     return c.defaultAssertionStatus;
206   }
207 \end{lstlisting}
208 The ClassLoader class stores the global assertion status for user classes and the individual status for classes and packages:
209 \begin{itemize}
210 \item{\verb'boolean defaultAssertionStatus'}
211 \item{\verb'Map<String, Boolean> systemPackageAssertionStatus'}
212 \item{\verb'Map<String, Boolean> systemClassAssertionStatus'}
213 \end{itemize}
214
215 \noindent The VMClassLoader class is a special class that needs to implemented by virtual machines that use the classpath classes.
216 The following methods are used by the ClassLoader to initialize the variables above (in the same order):
217 \begin{itemize}
218 \item{\verb'boolean defaultUserAssertionStatus()'}
219 \item{\verb'Map<String, Boolean> packageAssertionStatus()'}
220 \item{\verb'Map<String, Boolean> classAssertionStatus()'}
221 \end{itemize}
222 See: java.lang.Class\footnote{http://cvs.savannah.gnu.org/viewvc/classpath/java/lang/Class.java?revision=1.54\&root=classpath\&view=markup}, java.lang.ClassLoader\footnote{http://cvs.savannah.gnu.org/viewvc/classpath/java/lang/ClassLoader.java?revision=1.62\&root=classpath\&view=markup}, java.lang.VMClassLoader\footnote{http://cvs.savannah.gnu.org/viewvc/classpath/vm/reference/java/lang/VMClassLoader.java?revision=1.16.2.18\&root=classpath\&view=markup}
223 \\
224 \\
225 What had to be done:
226 \begin{itemize}
227 \item{Implement the methods: defaultUserAssertionStatus, packageAssertionStatus, classAssertionStatus}
228 \item{Write a function to parse the commandline options}
229 \end{itemize}
230 See: src/lib/gnu/java/lang/VMClassLoader.java (section \ref{see1}), src/native/vm/gnu/java\_lang\_VMClassLoader.c (section \ref{see2}), src/vm/assertion.c (section \ref{see3}) and src/vm/assertion.c (section \ref{see4})
231 \\\\
232 For cacao+openjdk I could reuse most of the code I wrote for cacao+classpath:
233 \\\\
234 The desiredAssertionStatus method in java.lang.Class of openjdk looks like this:
235 \begin{lstlisting}[language=Java, firstnumber=2849]
236 public boolean desiredAssertionStatus() {
237     ClassLoader loader = getClassLoader();
238     // If the loader is null this is a system class, so ask the VM
239     if (loader == null)
240         return desiredAssertionStatus0(this);
241
242     synchronized(loader) {
243         // If the classloader has been initialized with
244         // the assertion directives, ask it. Otherwise,
245         // ask the VM.
246         return (loader.classAssertionStatus == null ?
247                 desiredAssertionStatus0(this) :
248                 loader.desiredAssertionStatus(getName()));
249     }
250 }
251
252 \end{lstlisting}
253 The native function called by desiredAssertionStatus0 is JVM\_DesiredAssertionStatus, and that's the only function that had to be implemented by me to make assertions work with cacao+openjdk. I've also corrected the implementation of the JVM\_AssertionStatusDirectives function, which is used by java.lang.ClassLoader.
254 \\
255 \\
256 See: src/native/vm/sun/jvm.c (section \ref{see5})
257
258 \pagebreak
259 \section{Patch overview}
260 \subsection{Changed/New files}
261 \begin{itemize}
262 \item{\verb'configure.ac'}
263 \item{\verb'm4/assertion.m4'}
264 \item{\verb'src/lib/gnu/java/lang/VMClassLoader.java'}
265 \item{\verb'src/native/include/Makefile.am'}
266 \item{\verb'src/native/jni.h'}
267 \item{\verb'src/native/vm/gnu/java_lang_VMClassLoader.c'}
268 \item{\verb'src/native/vm/sun/jvm.c'}
269 \item{\verb'src/vm/Makefile.am'}
270 \item{\verb'src/vm/assertion.c'}
271 \item{\verb'src/vm/assertion.h'}
272 \item{\verb'src/vm/vm.c'}
273 \item{\verb'src/vmcore/class.c'}
274 \item{\verb'src/vmcore/class.h'}
275 \item{\verb'src/vmcore/linker.c'}
276 \item{\verb'src/vmcore/loader.c'}
277 \item{\verb'configure.ac'}
278 \end{itemize}
279
280 \subsection{configure.ac}
281 Added configure option "--enable-assertion" (turned on by default).
282 \\
283 Most of the assertion code will be turned off if this switch is disabled.
284 \\\\
285 Actual configure logic is in m4/assertion.m4.
286
287 \subsection{m4/assertion.m4}
288 Added autoconf logic to enable/disable building of assertion support.
289
290 \subsection{src/lib/gnu/java/lang/VMClassLoader.java}
291 \label{see1}
292 Replaced the dummy implementations of:
293 \begin{itemize}
294 \item{\verb'defaultAssertionStatus'}
295 \item{\verb'packageAssertionStatus'}
296 \item{\verb'classAssertionStatus'}
297 \end{itemize}
298
299 Added:
300 \begin{itemize}
301 \item{\verb'defaultUserAssertionStatus'}
302 \end{itemize}
303
304 \noindent This function returns the user assertion status. Due to incorrect handling of user/system assertion status in GNU classpath\footnote{http://www.gnu.org/software/classpath/}, enabling (default) system assertions will also enable assertions in all user classes (a patch\footnote{http://www.mail-archive.com/classpath-patches@gnu.org/msg10400/assertion\_cp.patch} to fix this behaviour was submitted in August 07).
305 \\\\
306 Actual implementations now call into native code to get status.
307
308 \subsection{src/native/include/Makefile.am}
309 Added:
310 \begin{itemize}
311 \item{\verb'java_util_HashMap.h'}
312 \item{\verb'java_util_Map.h'}
313 \end{itemize}
314 \noindent Headers needed to allow construction of Map/HashMap in native code.
315
316 \subsection{src/native/jni.h}
317 Removed:
318 \begin{itemize}
319 \item{\verb'_Jv_JavaVM->Java_java_lang_VMClassLoader_defaultAssertionStatus'}
320 \end{itemize}
321 \noindent This variable was used to hold the system's assertion status and was replaced by assertion\_user\_enabled and assertion\_system\_enabled.
322
323 \subsection{src/native/vm/gnu/java\_lang\_VMClassLoader.c}
324 \label{see2}
325 This file holds native implementations of the VMClassLoader for GNU classpath.
326 \\\\
327 The following functions were added/replaced:
328 \begin{itemize}
329 \item{\verb'Java_java_lang_VMClassLoader_defaultUserAssertionStatus'}
330 \end{itemize}
331 \noindent Native implementation of VMClassLoader.defaultUserAssertionStatus. This function returns the default user assertion status of the system (user\_assertion\_status). Returns false if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
332 \begin{itemize}
333 \item{\verb'Java_java_lang_VMClassLoader_defaultAssertionStatus'}
334 \end{itemize}
335 \noindent Previous implemention was replaced. Native implementation of VMClassLoader.defaultAssertionStatus. This function returns the default assertion status of the system (system\_assertion\_status). Returns false if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
336 \begin{itemize}
337 \item{\verb'Java_java_lang_VMClassLoader_packageAssertionStatus0'}
338 \end{itemize}
339 \noindent Native implementation of VMClassLoader.packageAssertionStatus. Builds and returns a HashMap containing key and value pairs of packagenames and their assertion status (as expected by the ClassLoader). Returns an empty HashMap if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
340 \begin{itemize}
341 \item{\verb'Java_java_lang_VMClassLoader_classAssertionStatus0'}
342 \end{itemize}
343 \noindent Native implementation of VMClassLoader.classAssertionStatus. Builds and returns a HashMap containing key and value pairs of classnames and their assertion status (as expected by the ClassLoader). Returns an empty HashMap if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
344
345 \subsection{src/native/jni.h}
346 Removed:
347 \begin{itemize}
348 \item{\verb'_Jv_JavaVM->Java_java_lang_VMClassLoader_defaultAssertionStatus'}
349 \end{itemize}
350 \noindent This variable was used to hold the system's assertion status and was replaced by assertion\_user\_enabled and assertion\_system\_enabled.
351
352 \subsection{src/native/vm/sun/jvm.c}
353 \label{see5}
354 This file holds various native implementations needed by OpenJDK\footnote{http://openjdk.java.net/}.
355 \\\\
356 The following functions were added/replaced:
357 \begin{itemize}
358 \item{\verb'JVM_DesiredAssertionStatus'}
359 \end{itemize}
360 \noindent Dummy implementation was replaced. Returns the desired assertion status for a given class. Returns false if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
361 \begin{itemize}
362 \item{\verb'JVM_AssertionStatusDirectives'}
363 \end{itemize}
364 \noindent Previous implementation was incomplete. Builds and returns an AssertionStatusDirectives object. This object contains the names of all packages and classes and their assertion status.
365
366 \subsection{src/vm/Makefile.am}
367 Added (optional) building of the assertion module (assertion.c/assertion.h). Will only be built if ENABLE\_ASSERTION is defined (--enable-assertions=yes).
368
369 \subsection{src/vm/assertion.c}
370 \label{see3}
371 This file handles the various assertion commandline options (-ea/-da/-esa/-dsa).
372
373 \subsection{src/vm/assertion.h}
374 \label{see4}
375 Defines the following global variables:
376 \begin{lstlisting}[language=C,firstnumber=46]
377 extern list\_t  *list\_assertion\_names;
378 \end{lstlisting}
379 This variable stores class/package names and their assertion status.
380 \begin{lstlisting}[language=C,firstnumber=47]
381 extern int32\_t  assertion\_class\_count;
382 \end{lstlisting}
383 This variable stores the amount of classnames specified on the commandline.
384 \begin{lstlisting}[language=C,firstnumber=48]
385 extern int32\_t  assertion\_package\_count;
386 \end{lstlisting}
387 This variable stores the amount of packagenames specified on the commandline.
388 \begin{lstlisting}[language=C,firstnumber=49]
389 extern bool     assertion\_user\_enabled;
390 \end{lstlisting}
391 This variable stores the systemwide user default assertion status.
392 \begin{lstlisting}[language=C,firstnumber=50]
393 extern bool     assertion_system_enabled;
394 \end{lstlisting}
395 This variable stores the systemwide default assertion status.
396 \\\\
397 Defines the following functions:
398 \begin{lstlisting}[language=C,firstnumber=54]
399 void assertion\_ea\_da(const char *name, bool enabled);
400 \end{lstlisting}
401 This function is used to initialize the variables described aboved.
402
403 \subsection{src/vm/vm.c}
404 Handling of assertion commandline options was added/changed. Package and classname parsing is handled by src/vm/assertion.c (assertion\_ea\_da function).
405
406 \subsection{src/vmcore/class.c}
407 Added class\_java\_util\_HashMap
408
409 \subsection{src/vmcore/class.h}
410 Added class\_java\_util\_HashMap.
411
412 \subsection{src/vmcore/linker.c}
413 Added linking of class\_java\_util\_HashMap.
414
415 \subsection{src/vmcore/loader.c}
416 Added loading of class\_java\_util\_HashMap.
417
418 \end{document}