5ae5cfec49d3f41492857feb8a3d311e437c6071
[nestedvm.git] / doc / nestedvm.ivme04.tex
1 \documentclass{acmconf}
2 \usepackage{graphicx}
3 \usepackage{multicol}
4 \usepackage{amssymb,amsmath,epsfig,alltt}
5 \sloppy
6 \usepackage{palatino}
7 \usepackage{pdftricks}
8 \begin{psinputs}
9   \usepackage{pstricks}
10   \usepackage{pst-node}
11 \end{psinputs}
12 \usepackage{parskip}
13 \usepackage{tabularx}
14 \usepackage{alltt}
15 \bibliographystyle{alpha}
16
17 \title{\textbf{\textsf{
18 NestedVM: Total Translation of Native Code into Safe Bytecode
19 }}}
20 \date{}
21 \author{\begin{tabular}{@{}c@{}}
22         {\em {Brian Alliet}} \\
23         {Rochester Institute of Technology}\\
24         {\tt brian@ibex.org}
25    \end{tabular}\hskip 1in\begin{tabular}{@{}c@{}}
26         {\em {Adam Megacz}} \\
27         {UC Berkeley Statistical Computing Facility} \\
28         {\tt adam@ibex.org}
29 \end{tabular}}
30 \begin{document}
31
32 \maketitle
33
34 \begin{abstract}
35
36 We present a new approach to utilizing unsafe legacy unsafe code
37 within safe virtual machines by compiling to MIPS machine code as an
38 intermediate language.  This approach carries N key benefits over
39 existing techniques:
40
41 \begin{itemize}
42 \item total coverage of all language features, unlike source translation
43 \item no build process modifications
44 \item no post-translation human intervention
45 \item efficient bytecode
46 \end{itemize}
47
48 We also present NestedVM, a complete system in production use which
49 implements this technique.  We conclude with quantitative performance
50 measurements and suggestions for VM acceleration of the resulting
51 bytecodes.
52
53
54 \end{abstract}
55
56 \section{Introduction}
57
58 The C programming language \cite{KR} has been in use for over 30
59 years.  Consequently, there is a huge library of software written in
60 this language.  Although Java offers substantial benefits \cite{} over
61 C (and C++), its comparatively young age means that it often lacks
62 equivalents of many C/C++ libraries.
63
64 The typical solution to this dilemma is to use JNI \cite{} or CNI
65 \cite{} to invoke C code from within a Java VM.  Unfortunately, there
66 are a number of situations in which this is not an acceptable
67 solution due to security concerns:
68
69 \begin{itemize}
70
71 \item Java Applets are not permitted to invoke {\tt
72       Runtime.loadLibrary()}
73
74 \item Java Servlet containers with a {\tt SecurityManager} will not
75       permit loading new JNI libraries.  This configuration is popular
76       with {\it shared hosting} providers and corporate intranets
77       where a number of different parties contribute individual web
78       applications which are run together in a single container.
79
80 \item Unlike Java Bytecode, JNI code is susceptible to buffer overflow
81       and heap corruption attacks.  This can be a major security
82       vulnerability.
83
84 \end{itemize}
85
86 In addition to security concerns, JNI and CNI carry other
87 disadvantages:
88
89 \begin{itemize}
90
91 \item JNI requires the native library to be compiled ahead of time,
92       separately, for every architecture on which it will be deployed.
93       This is unworkable for situations in which the full set of
94       target architectures is not known at deployment time.
95
96 \item The increasingly popular J2ME \cite{} platform does not support
97       JNI or CNI.
98
99 \item JNI often introduces undesirable added complexity to an
100       application.
101
102 \end{itemize}
103
104 The technique we present here is based on using a typical ANSI C
105 compiler to compile C/C++ code into a MIPS binary, and then using a
106 tool to translate that binary on an instruction-by-instruction basis
107 into Java bytecode.
108
109 The technique presented here is general; we anticipate that it can be
110 applied to other secure virtual machines such as Microsoft's .NET
111 \cite{}, Perl Parrot \cite{}, or Python bytecode \cite{}.
112
113 \section{Approaches to Translation}
114
115 Techniques for translating unsafe code into VM bytecode generally fall
116 into four categories:
117
118 \begin{itemize}
119 \item source-to-source translation
120 \item source-to-binary translation
121 \item binary-to-source translation
122 \item binary-to-binary translation
123 \end{itemize}
124
125 \begin{figure}[h]
126 \begin{pdfpic}
127 \newlength{\MyLength}
128 \settowidth{\MyLength}{machine code}
129 \newcommand{\MyBox}[1]{\makebox[\MyLength]{#1}}
130 \begin{psmatrix}[colsep=3,rowsep=3]
131   [name=s0]\MyBox{unsafe source} & [name=s1]\MyBox{safe source}   \\[0pt]
132   [name=b0]\MyBox{machine code}  & [name=b1]\MyBox{safe bytecode} \\
133   \psset{nodesep=5pt,arrows=->}
134   \ncline{s0}{b0}<{\it gcc}
135   \ncline{s0}{s1}\aput{:U}{\it c2java}
136   \ncline{s0}{b1}\aput{:U}{\it gcc bytecode backend}
137   \ncline{s1}{b1}>{\it javac}
138 \end{psmatrix}
139 \end{pdfpic}
140 \caption{\label{lattice} Conversion Lattice with examples of tools specific to a C/JVM scenario}
141 \end{figure}
142
143 \begin{figure}[h]
144 \begin{pdfpic}
145 \newlength{\MyLength}
146 \settowidth{\MyLength}{machine code}
147 \newcommand{\MyBox}[1]{\makebox[\MyLength]{#1}}
148 \begin{psmatrix}[colsep=3,rowsep=3,nrot=:U]
149   [name=s0]\MyBox{unsafe source} & [name=s1]\MyBox{safe source}   \\[0pt]
150   [name=b0]\MyBox{machine code}  & [name=b1]\MyBox{safe bytecode} \\
151   \psset{nodesep=5pt,arrows=->}
152   \ncline{s0}{b0}<{\it gcc}
153   \ncline{s1}{b1}>{\it javac}
154   \ncline{b0}{s1}\naput{\it NestedVM}
155   \ncline{b0}{s1}\nbput{\it binary-to-source}
156 \end{psmatrix}
157 \end{pdfpic}
158 \caption{\label{lattice2} Conversion Lattice including NestedVM in {\it source-output} mode}
159 \end{figure}
160
161 \begin{figure}[h]
162 \begin{pdfpic}
163 \newlength{\MyLength}
164 \settowidth{\MyLength}{machine code}
165 \newcommand{\MyBox}[1]{\makebox[\MyLength]{#1}}
166 \begin{psmatrix}[colsep=3,rowsep=3,nrot=:U]
167   [name=s0]\MyBox{unsafe source} & [name=s1]\MyBox{safe source}   \\[0pt]
168   [name=b0]\MyBox{machine code}  & [name=b1]\MyBox{safe bytecode} \\
169   \psset{nodesep=5pt,arrows=->}
170   \ncline{s0}{b0}<{\it gcc}
171   \ncline{s1}{b1}>{\it javac}
172   \ncline{b0}{b1}\naput{\it NestedVM}
173   \ncline{b0}{b1}\nbput{\it binary-to-binary}
174 \end{psmatrix}
175 \end{pdfpic}
176 \caption{\label{lattice3} Conversion Lattice including NestedVM in {\it bytecode-output} mode}
177 \end{figure}
178
179 A diagram showing these four translation approaches in the context of
180 running C/C++ code within a Java VM is shown in Figure~\ref{lattice}.
181
182 \subsection{Existing Work}
183 \subsubsection{Source-to-Source Translation}
184
185 \begin{itemize}
186 \item c2java
187 \item commercial products
188 \end{itemize}
189
190 A number of commercial products and research projects attempt to
191 translate C++ code to Java code, preserving the mapping of C++ classes
192 to Java classes.  Unfortunately this is problematic since there is no
193 way to do pointer arithmetic except within arrays, and even in that
194 case, arithmetic cannot be done in terms of fractional objects.
195
196 Mention gcc backend
197
198 Many of these products advise the user to tweak the code which results
199 from the translation.  Unfortunately, hand-modifying machine-generated
200 code is generally a bad idea, since this modification cannot be
201 automated.  This means that every time the origin code changes, the
202 code generator must be re-run, and the hand modifications must be
203 performed yet again.  This is an error-prone process.
204
205 Furthermore, NestedVM does not attempt to read C code directly.  This
206 frees it from the complex task of faithfully implementing the ANSI C
207 standard (or, in the case of non ANSI-C compliant code, some other
208 interface).  This also saves the user the chore of altering their
209 build process to accomodate NestedVM.
210
211 \section{NestedVM}
212
213 NestedVM takes a novel approach; it uses compiled machine code as a
214 starting point for the translation process.  NestedVM has gone through
215 two iterations:
216
217 \begin{itemize}
218 \item binary-to-source compilation  (Figure~\ref{lattice2})
219 \item binary-to-binary compilation  (Figure~\ref{lattice3})
220 \end{itemize}
221
222 \subsection{Translation Process}
223
224 Translating a legacy library for use within a JVM proceeds as follows:
225
226 \begin{enumerate}
227
228 \item Compile the source code to a statically linked binary, targeting
229       the MIPS R2000 ISA.
230
231 \item Invoke {\tt NestedVM} on the statically linked binary.
232       Typically this will involve linking against {\tt libc}, which
233       translates system requests (such as {\tt open()}, {\tt read()},
234       or {\tt write()}) into appropriate invocations of the MIPS
235       {\tt SYSCALL} instruction.
236
237 \item (If using binary-to-source translation) compile the resulting
238       {\tt .java} code using {\tt jikes} or {\tt javac}.
239
240 \item (Optional) compile the resulting bytecode into a {\it safe}
241       native binary using {\tt gcj}.
242
243 \item From java code, invoke the {\tt execute()} on the generated
244       class.  This is equivalent to the {\tt main()} entry point.
245
246 \end{enumerate}
247
248
249 \subsection{Why MIPS?}
250
251 We chose MIPS as a source format for two primary reasons: the
252 availability of tools to translate legacy code into MIPS binaries, and
253 the close similarity between the MIPS ISA and the Java Virtual Machine.
254
255 The MIPS architecture has been around for quite some time, and is well
256 supported by the GNU Compiler Collection, which is capable of
257 compiling C, C++, Java, Fortran, Pascal (with p2c), and Objective C
258 into MIPS binaries.
259
260 The MIPS R2000 ISA bears a striking similarity to the Java Virtual
261 Machine:
262
263 \begin{itemize}
264
265 \item The original MIPS ISA supports only 32-bit aligned memory loads
266       and stores.  This allows NestedVM to represent memory as a Java
267       {\tt int[]} without introducing additional overhead.
268
269 \item Unlike its predecessor, the R2000 supports 32-bit by 32-bit
270       multiply and divide instructions as well as a single and double
271       precision floating point unit.  These capabilities map nicely
272       onto Java's arithmetic instructions.
273
274 \end{itemize}
275
276
277 \subsection{Binary-to-Source Compilation}
278
279 The first incarnation of NestedVM was a binary-to-source compiler.
280 This version reads in a MIPS binary and emits Java source code, which
281 can be compiled with {\tt javac}, {\tt jikes}, or {\tt gcj}.
282
283 This implementation was primarily a first step towards the
284 binary-to-binary compiler.  Conveniently, generating Java source code
285 frees NestedVM from having to perform simple constant propagation
286 optimizations, since most Java compilers already do this.  A recurring
287 example is the treatment of the {\tt r0} register, which is fixed as
288 {\tt 0} in the MIPS ISA.
289
290 Now that the binary-to-binary compiler is available, the
291 binary-to-source compiler is only useful for generating input to {\tt
292 gcj}, as discussed in section FOOBAR.
293
294 Lacking the ability to generate specially optimized bytecode
295 sequences, a straightforward mapping of the general purpose hardware
296 registers to 32 {\tt int} fields was optimal.
297
298 \begin{figure*}[t]
299 \begin{minipage}[c]{7in}%
300 \begin{multicols}{2}
301 {\footnotesize\begin{verbatim}
302 private final static int r0 = 0;
303 private int r1, r2, r3,...,r30;
304 private int r31 = 0xdeadbeef;
305 private int pc = ENTRY_POINT;
306
307 public void run() {
308     for(;;) {
309         switch(pc) {
310             case 0x10000:
311                 r29 = r29 ? 32;
312             case 0x10004:
313                 r1 = r4 + r5;
314             case 0x10008:
315                 if(r1 == r6) {
316                     /* delay slot */
317                     r1 = r1 + 1;
318                     pc = 0x10018:
319                     continue;
320                 }
321             case 0x1000C:
322                 r1 = r1 + 1;
323             case 0x10010:
324                 r31 = 0x10018;
325                 pc = 0x10210;
326                 continue;
327             case 0x10014:
328                 /* nop */
329             case 0x10018:
330                 pc = r31;
331                 continue;
332             ...
333             case 0xdeadbeef:
334                 System.err.println(``Exited.'');
335                 System.exit(1);
336         }
337     }
338 }
339 \end{verbatim}}
340 \vspace{1in}
341 {\footnotesize\begin{verbatim}
342 public void run_0x10000() {
343     for(;;) {
344     switch(pc) {
345         case 0x10000:
346             ...
347         case 0x10004:
348             ...
349         ...
350         case 0x10010:
351             r31 = 0x10018;
352             pc = 0x10210;
353             return;
354         ...
355     }
356     }
357 }
358
359 pubic void run_0x10200() {
360     for(;;) {
361     switch(pc) {
362         case 0x10200:
363             ...
364         case 0x10204:
365             ...
366     }
367     }
368 }
369
370 public void trampoline() {
371     for(;;) {
372     switch(pc&0xfffffe00) {
373             case 0x10000: run_0x10000(); break;
374             case 0x10200: run_0x10200(); break;
375             case 0xdeadbe00:
376                 ...
377         }
378     }
379 }
380 \end{verbatim}}
381 \end{multicols}
382 \end{minipage}
383 \caption{\label{code1} Trampoline transformation necessitated by Java's 64kb method size limit}
384 \end{figure*}
385
386 Unfortunately Java imposes a 64kb limit on the size of the bytecode
387 for a single method.  This presents a problem for NestedVM, and
388 necessitates a {\it trampoline transformation}, as shown in
389 Figure~\ref{code1}.  With this trampoline in place somewhat large
390 binaries can be handled without much difficulty -- fortunately there
391 is no corresponding limit on the size of a classfile as a whole.
392
393 Another interesting problem that was discovered while creating the
394 trampoline method was javac and Jikes? inability to properly optimize
395 switch statements.  The code in Figure~\ref{lookupswitch} is compiled
396 into a comparatively inefficient {\tt LOOKUPSWITCH}, while the code in
397 Figure~\ref{tableswitch} is optimized into a {\tt TABLESWITCH}.
398
399 \begin{figure}
400 {\footnotesize\begin{verbatim}
401 switch(pc&0xffffff00) {
402     case 0x00000100: run_100(); break;
403     case 0x00000200: run_200(); break;
404     case 0x00000300: run_300(); break;
405 }
406 \end{verbatim}}
407 \caption{\label{lookupswitch} Code which {\it is not} optimized into a tableswitch}
408 \end{figure}
409
410 \begin{figure}
411 {\footnotesize\begin{verbatim}
412 Brian, we're missing the code here... can you put it in?
413 \end{verbatim}}
414 \caption{\label{tableswitch} Code which {\it is} optimized into a tableswitch}
415 \end{figure}
416
417 Javac isn?t smart enough to see the patter in the case values and
418 generates very suboptimal bytecode. Manually doing the shifts
419 convinces javac to emit a tableswitch statement, which is
420 significantly faster. This change alone nearly doubled the speed of
421 the compiled binary.
422
423 Finding the optimal method size lead to the next big performance
424 increase.  It was determined with experimentation that the optimal
425 number of MIPS instructions per method is 128 (considering only power
426 of two options). Going above or below that lead to performance
427 decreases. This is most likely due to a combination of two factors.
428
429 \begin{itemize}
430
431 \item The two levels of switch statements jumps have to pass though -
432       The first switch statement jumps go through is the trampoline
433       switch statement. This is implemented as a TABLESWITCH in JVM
434       bytecode so it is very fast. The second level switch statement
435       in the individual run\_ methods is implemented as a
436       LOOKUPSWITCH, which is much slower. Using smaller methods puts
437       more burden on the faster TABLESWITCH and less on the slower
438       LOOKUPSWITCH.
439
440 \item JIT compilers probably favor smaller methods smaller methods are
441       easier to compile and are probably better candidates for JIT
442       compilation than larger methods.
443
444 \end{itemize}
445
446 Put a chart in here
447
448 The next big optimization was eliminating unnecessary case
449 statements. Having case statements before each instruction prevents
450 JIT compilers from being able to optimize across instruction
451 boundaries. In order to eliminate unnecessary case statements every
452 possible address that could be jumped to directly needed to be
453 identified. The sources for possible jump targets come from 3 places.
454
455 \begin{itemize}
456
457 \item The .text segment ? Every instruction in the text segment in
458       scanned for jump targets. Every branch instruction (BEQ, JAL,
459       etc) has its destination added to the list of possible branch
460       targets. In addition, functions that set the link register have
461       theirpc+8 added to the list (the address that would?ve been put
462       to the link register). Finally, combinations of LUI (Load Upper
463       Immediate) of ADDIU (Add Immediate Unsigned) are scanned for
464       possible addresses in the text segment. This combination of
465       instructions is often used to load a 32-bit word into a
466       register.
467
468 \item The .data segment ? When GCC generates switch() statements it
469       often uses a jump table stored in the .data
470       segment. Unfortunately gcc doesn?t identify these jump tables in
471       any way. Therefore, the entire .data segment is conservatively
472       scanned for possible addresses in the .text segment.
473       
474 \item The symbol table ? This is mainly used as a backup. Scanning the
475       .text and .data segments should identify any possible jump
476       targets but adding every function in the symbol table in the ELF
477       binary doesn?t hurt. This will also catch functions that are
478       never called directly from the MIPS binary (for example,
479       functions called with the call() method in the runtime).
480
481 \end{itemize}
482
483 Eliminating unnecessary case statements provided a 10-25\% speed
484 increase.
485
486 Despite all the above optimizations and workaround an impossible to
487 workaround hard classfile limit was eventually hit, the constant
488 pool. The constant pool in classfiles is limited to 65536
489 entries. Every Integer with a magnitude greater than 32767 requires an
490 entry in the constant pool. Every time the compiler emits a
491 jump/branch instruction the PC field is set to the branch target. This
492 means nearly every branch instruction requires an entry in the
493 constant pool. Large binaries hit this limit fairly quickly. One
494 workaround that was employed in the Java source compiler was to
495 express constants as offsets from a few central values. For example:
496 ``pc = N\_0x00010000 + 0x10'' where N\_0x000100000 is a non-final
497 field to prevent javac from inlining it. This was sufficient to get
498 reasonable large binaries to compile. It has a small (approximately
499 5\%) performance impact on the generated code. It also makes the
500 generated classfile somewhat larger.  Fortunately, the classfile
501 compiler eliminates this problem.
502
503
504 \subsection{Binary-to-Binary Translation}
505
506 The next step in the evolution of NestedVM was to compile directly to
507 JVM bytecode eliminating the intermediate javac step. This had several
508 advantages:
509
510 \begin{itemize}
511       
512 \item There are little tricks that can be done in JVM bytecode that
513       can?t be done in Java source code.
514
515 \item Eliminates the time-consuming javac step ? Javac takes a long
516       time to parse and compile the output from the java source
517       compiler.
518
519 \item Allows for MIPS binaries to be compiled and loaded into a
520       running VM using a class loader. This eliminates the need to
521       compile the binaries ahead of time.
522
523 \end{itemize}
524
525 By generating code at the bytecode level there are many areas where
526 the compiler can be smarter than javac. Most of the areas where
527 improvements where made where in the handling of branch instructions
528 and in taking advantage of the JVM stack to eliminate unnecessary
529 LOADs and STOREs to local variables.
530
531 The first obvious optimization that generating bytecode allows for is
532 the use of GOTO. Despite the fact that java doesn?t have a GOTO
533 keyword a GOTO bytecode does exist and is used heavily in the code
534 generates by javac. Unfortunately the java language doesn?t provide
535 any way to take advantage of this. As result of this jumps within a
536 method were implemented by setting the PC field to the new address and
537 making a trip back to the initial switch statement.  In the classfile
538 compiler these jumps are implemented as GOTOs directly to the target
539 instruction. This saves a costly trip back through the LOOKUPSWITCH
540 statement and is a huge win for small loops within a method.
541
542 Somewhat related to using GOTO is the ability to optimize branch
543 statements. In the Java source compiler branch statements are
544 implemented as follows (delay slots are ignored for the purpose of
545 this example):
546
547 {\footnotesize\begin{verbatim}
548 if(condition) { pc = TARGET; continue; }
549 \end{verbatim}}
550
551 This requires a branch in the JVM regardless of whether the MIPS
552 branch is actually taken. If condition is false the JVM has to jump
553 over the code to set the PC and go back to the switch block. If
554 condition is true the JVM as to jump to the switch block. By
555 generating bytecode directly we can make the target of the JVM branch
556 statement the actual bytecode of the final destination. In the case
557 where the branch isn?t taken the JVM doesn?t need to branch at all.
558
559 A side affect of the above two optimizations is a solution to the
560 excess constant pool entries problem. When jumps are implemented as
561 GOTOs and direct branches to the target the PC field doesn?t need to
562 be set. This eliminates many of the constant pool entries the java
563 source compiler requires. The limit is still there however, and given
564 a large enough binary it will still be reached.
565
566 Delay slots are another area where things are done somewhat
567 inefficiently in the Java source compiler. In order to take advantage
568 of instructions already in the pipeline MIPS cpu have a ?delay
569 slot?. That is, an instruction after a branch or jump instruction that
570 is executed regardless of whether the branch is taken. This is done
571 because by the time the branch or jump instruction is finished being
572 processes the next instruction is already ready to be executed and it
573 is wasteful to discard it. (However, newer MIPS CPUs have pipelines
574 that are much larger than early MIPS CPUs so they have to discard many
575 instructions anyway.) As a result of this the instruction in the delay
576 slot is actually executed BEFORE the branch is taken. To make things
577 even more difficult, values from the register file are loaded BEFORE
578 the delay slot is executed.  Here is a small piece of MIPS assembly:
579
580 {\footnotesize\begin{verbatim}
581 ADDIU r2,r0,-1
582 BLTZ r2, target
583 ADDIU r2,r2,10
584 ...
585 :target
586 \end{verbatim}}
587
588 This piece of code is executed as follows
589
590 \begin{enumerate}
591
592 \item r2 is set to ?1
593
594 \item r2 is loaded from the register file by the BLTEZ instruction
595       
596 \item 10 is added to r2 by the ADDIU instruction
597
598 \item The branch is taken because at the time the BLTZ instruction was
599       executed r2 was ?1, but r2 is now 9 (-1 + 10)
600
601 \end{enumerate}
602
603 There is a very element solution to this problem when using JVM
604 bytecode. When a branch instruction is encountered the registers
605 needed for the comparison are pushed onto the stack to prepare for the
606 JVM branch instruction. Then, AFTER the values are on the stack the
607 delay slot is emitted, and then finally the actual JVM branch
608 instruction. Because the values were pushed to the stack before the
609 delay slot was executed any changes the delay slot made to the
610 registers are not visible to the branch bytecode. This allows delay
611 slots to be used with no performance penalty or size penalty.
612
613 One final advantage that generating bytecode directly allows is
614 smaller more compact bytecode. All the optimization above lead to
615 smaller bytecode as a side effect. There are also a few other areas
616 where the generated bytecode can be optimized for size with more
617 knowledge of the program as a whole.
618
619 When encountering the following switch block both javac and Jikes
620 generate redundant bytecode.
621
622 {\footnotesize\begin{verbatim}
623 switch(pc>>>8) {
624     case 0x1: run_1(); break;
625     case 0x2: run_2(); break
626     ...
627     case 0x100: run_100(); break;
628 }
629 \end{verbatim}}
630
631 The first bytecode in each case arm in the switch statement is ALOAD\_0 to
632 prepare for a invoke special call. By simple moving this outside the switch
633 statement each case arm was reduced in size by one instruction. Similar
634 optimizations were also done in other parts of the compiler.
635
636
637 \section{Interfacing with Java Code}
638
639 Java source code can create a copy of the translated binary by
640 instantiating the corresponding class, which extends {\tt Runtime}.
641 Invoking the {\tt main()} method on this class is equivalent to
642 calling the {\tt main()} function within the binary; the {\tt String}
643 arguments to this function are copied into the binary's memory space
644 and made available as {\tt argv**} and {\tt argc}.
645
646 The translated binary communicates with the rest of the VM by
647 executing MIPS {\tt SYSCALL} instructions, which are translated into
648 invocations of the {\tt syscall()} method.  This calls back to the
649 native Java world, which can manipulate the binary's environment by
650 reading and writing to its memory space, checking its exit status,
651 pausing the VM, and restarting the VM.
652
653
654 \subsection{Virtualization}
655
656 The {\tt Runtime} class implements the majority of the standard {\tt
657 libc} syscalls, providing a complete interface to the filesystem,
658 network socket library, time of day, (Brian: what else goes here?).
659
660 \begin{itemize}
661
662 \item ability to provide the same interface to CNI code and
663       NestedVMified code
664       
665 \item security advantages (chroot the {\tt fork()}ed process)
666
667 \end{itemize}
668
669
670 \section{Quantitative Performance}
671
672 \subsection{Charts}
673
674 (Note that none of these libraries have pure-Java equivalents.)
675
676 \begin{itemize}
677 \item libjpeg
678 \item libfreetype
679 \item libmspack
680 \end{itemize}
681
682
683 \subsection{Optimizations}
684
685 Brian, can you write something to go here?  Just mention which
686 optimizations helped and which ones hurt.
687
688 \begin{itemize}
689 \item {\tt trampoline}
690 \item {\tt optimal method size}
691 \item {\tt -msingle-float}
692 \item {\tt -mmemcpy}
693 \item {\tt fastmem}
694 \item {\tt local vars for registers (useless)}
695 \item {\tt -fno-rename-registers}
696 \item {\tt -ffast-math}
697 \item {\tt -fno-trapping-math}
698 \item {\tt -fsingle-precision-constant}
699 \item {\tt -mfused-madd}
700 \item {\tt -freg-struct-return}
701 \item {\tt -freduce-all-givs}
702 \item {\tt -fno-peephole}
703 \item {\tt -fno-peephole2}
704 \item {\tt -fmove-all-movables}
705 \item {\tt -fno-sched-spec-load}
706 \item {\tt -fno-sched-spec}
707 \item {\tt -fno-schedule-insns}
708 \item {\tt -fno-schedule-insns2}
709 \item {\tt -fno-delayed-branch}
710 \item {\tt -fno-function-cse}
711 \item {\tt -ffunction-sections}
712 \item {\tt -fdata-sections}
713 \item {\tt array bounds checking}
714 \item {\tt -falign-functions=n}
715 \item {\tt -falign-labels=n}
716 \item {\tt -falign-loops=n}
717 \item {\tt -falign-jumps=n}
718 \item {\tt -fno-function-cse}
719 \end{itemize}
720
721 \section{Future Directions}
722
723 World domination.
724
725 \section{Conclusion}
726
727 We rock the hizzouse.
728
729 \section{References}
730
731 Yer mom.
732
733 \section{stuff}
734 \begin{onecolumn}
735 {\footnotesize\begin{verbatim}
736
737 libjpeg (render thebride_1280.jpg)
738 Native -  0.235s
739 JavaSource - 1.86s
740 ClassFile - 1.37s
741
742 freetype (rendering characters 32-127 of Comic.TTF at sizes from 8 to
743 48 incrementing by 4)
744 Native - 0.201s
745 JavaSource - 2.02s
746 ClassFile - 1.46s
747
748                                           libjpeg  libmspack libfreetype
749 Interpreted MIPS Binary                   22.2      12.9      21.4
750 Compled MIPS Binary (fastest options)     3.39      2.23      4.31
751 Native -O3                                0.235    0.084     0.201
752
753 Compled - with all case statements        3.50      2.30      4.99
754 Compiled - with pruned case statement     3.39      2.23      4.31
755
756 Compiled - 512 instructions/method        62.7      27.7      56.9
757 Compiled - 256 instructions/method        3.54      2.55      4.43
758 Compiled - 128 instructions/method        3.39      2.23      4.31
759 Compiled - 64 instructions/method         3.56      2.31      4.40
760 Compiled - 32 instruction/method          3.71      2.46      4.64
761
762 Compild MIPS Binary (Server VM)           3.21      2.00      4.54
763 Compiled MIPS Binary (Client VM)          3.39      2.23      4.31
764
765 All times are measured in seconds. These were all run on a dual 1ghz G4
766 running OS X 10.3.1 with Apple's latest VM (JDK 1.4.1_01-27). Each test
767 was run 8 times within a single VM. The highest and lowest times were
768 removed and the remaining 6 were averaged. In each case only the first
769 run differed significantly from the rest.
770
771 The libjpeg test consisted of decoding a 1280x1024 jpeg
772 (thebride_1280.jpg) and writing a tga. The mspack test consisted of
773 extracting all members from arial32.exe, comic32.exe, times32.exe, and
774 verdan32.exe. The freetype test consisted of rendering characters
775 32-127 of Comic.TTF at sizes from 8 to 48 incrementing by 4. (That is
776 about 950 individual glyphs).
777
778 I can provide you with the source for any of these test if you'd like.
779
780 -Brian
781 \end{verbatim}}
782 \end{onecolumn}
783 \end{document}
784