Patchwork [wwwdocs,Java] Fix up java/papers/compiling.html

login
register
mail settings
Submitter Gerald Pfeifer
Date Nov. 11, 2012, 11:38 p.m.
Message ID <alpine.LNX.2.00.1211111024400.3550@tuna.site>
Download mbox | patch
Permalink /patch/198306/
State New
Headers show

Comments

Gerald Pfeifer - Nov. 11, 2012, 11:38 p.m.
On Sun, 4 Nov 2012, Gerald Pfeifer wrote:
> Looking at that page, I noticed a lot of broken navigation (broken
> images,...).  This removes that navigation and also address the worst
> in terms of broken markup.
> 
> Still bin/preprocess excludes this file from the regular treatment
> that our general web pages get; that'll be next, but it'll require
> a fair number of additional cleanups.

Done thusly, last weekend actually, but only committed/senthere now.

Gerald


2012-11-11  Gerald Pfeifer  <gerald@pfeifer.com>

	* papers/compiling.html: Transform into XHTML 1.0 Transitional.

Patch

Index: papers/compiling.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/java/papers/compiling.html,v
retrieving revision 1.2
diff -u -3 -p -r1.2 compiling.html
--- papers/compiling.html	3 Nov 2012 15:15:21 -0000	1.2
+++ papers/compiling.html	11 Nov 2012 09:23:36 -0000
@@ -1,20 +1,25 @@ 
-<HTML>
-<HEAD>
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html
+          PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
 <title>Cygnus Papers</title>
-<META NAME="robots" CONTENT="index, follow">
-<META NAME="description" CONTENT="Development tools for embedded systems. The leader in Open Sourceware(TM)-based software development tools, mission critical support and custom engineering for the embedded systems market.">
-<META NAME="keywords" CONTENT="y2k, open source, free software, Cygnus, Cygnus Solutions, Cygnus Support, internet,  embedded systems, embedded, embedded compiler, embedded compilers, cross compiler, cross compilers, compiler, compilers,
-GNUPro, GNUPro Toolkit, Source-Navigator, source code browser, Foundry, Cygnus Foundry, GCC, GDB, GNU, native compiler, native compilers, compilation, debugging">
+<meta name="description" content="Development tools for embedded systems. The leader in Open Sourceware(TM)-based software development tools, mission critical support and custom engineering for the embedded systems market." />
+<meta name="keywords" content="y2k, open source, free software, Cygnus, internet,  embedded systems, embedded, embedded compiler, embedded compilers, cross compiler, cross compilers, compiler, compilers,
+source code browser, GCC, GDB, GNU, native compiler, compilation, debugging" />
 </head>
 
-<BODY BGCOLOR="#FFFFFF" text="#000066" link="#ff9900" vlink="#000000">
+<body bgcolor="#FFFFFF" text="#000066" link="#ff9900" vlink="#000000">
 
 <h2><a name="top">Compiling Java for Embedded Systems</a></h2>
 
 <h4>By Per Bothner <a
 href="mailto:bothner@cygnus.com">(bothner@cygnus.com)</a></h4>
 
-<font size=2>
+<p><font size="2">
 While a major factor in Java's success is
 its use of portable bytecodes, we believe it cannot become a
 mainstream programming language without mainstream implementation
@@ -27,9 +32,8 @@  technology. In this paper, we discuss is
 using traditional compiler, linker, and debugging technology;
 particular emphasis is given to using Java in embedded and limited
 memory environments.
-</font>
+</font></p>
 
-<p>
 <ul>
 <li><a href="#sec1">1. Java implementation</a></li>
 <li><a href="#sec2">2. Issues with embedded Java</a>
@@ -42,7 +46,7 @@  memory environments.
 </li>
 <li><a href="#sec3">3. Compiling Java</a>
 	<ul>
-	<li><A HREF="#sec3_1">3.1 Transforming bytecodes</a></li>
+	<li><a href="#sec3_1">3.1 Transforming bytecodes</a></li>
 	<li><a href="#sec3_2">3.2 Class meta-data</a></li>
 	<li><a href="#sec3_3">3.3 Static references</a></li>
 	<li><a href="#sec3_4">3.4 Linking</a></li>
@@ -54,41 +58,41 @@  memory environments.
 	<li><a href="#sec4_2">4.2 Profiling</a></li>
 	</ul>
 </li>
-<li><A HREF="#sec5">5 Status</a>
-<li><a href="#ack">Acknowledgements</a>
-<li><a href="#biblio">Bibliography</a>
+<li><a href="#sec5">5 Status</a></li>
+<li><a href="#ack">Acknowledgements</a></li>
+<li><a href="#biblio">Bibliography</a></li>
 </ul>
 
 <h3><a name="sec1">1 Java implementation</a></h3>
 
-<p>Java (see Bibliography for <A HREF="#JavaSpec">JavaSpec</A>) has
+<p>Java (see Bibliography for <a href="#JavaSpec">JavaSpec</a>) has
 become popular because it is a decent programming language, is
 buzzword-compliant (object-oriented and web-enabled), and because it
 is implemented by compiling to portable bytecodes (see Bibliography
-for <A HREF="#JavaVM">JavaVMSpec</A>). The traditional Java
+for <a href="#JavaVM">JavaVMSpec</a>). The traditional Java
 implementation model is to compile Java source code into
 <code>.class</code> files containing machine-independent byte-code
 instructions. These <code>.class</code> files are downloaded and
 interpreted by a browser or some other Java &quot;Virtual
-Machine&quot; (VM). See <A HREF="java1.gif">Figure 1</A> for a
-model of the traditional Java implementation.</P>
+Machine&quot; (VM). See <a href="java1.gif">Figure 1</a> for a
+model of the traditional Java implementation.</p>
 
-<P align="center">
-<a href="java1.gif"><IMG SRC="java1a.gif" alt="" width="300" height="170"></a></p>
+<p align="center">
+<a href="java1.gif"><img src="java1a.gif" alt="" width="300" height="170" /></a></p>
 
-<p align="center"><b>Figure 1: Typical Java implementation</b></P>
+<p align="center"><b>Figure 1: Typical Java implementation</b></p>
 
 <p>However, interpreting bytecodes makes Java program many times
 slower than comparable C or C++ programs. One approach to improving
 this situation is &quot;Just-In-Time&quot; (JIT) compilers. These
 dynamically translate bytecodes to machine code just before a method
-is first executed.</P>
+is first executed.</p>
 
-<P>This can provide substantial speed-up, but it is still slower than
+<p>This can provide substantial speed-up, but it is still slower than
 C or C++. There are three main drawbacks with the JIT approach
-compared to conventional compilers: </P>
+compared to conventional compilers:</p>
 
-<UL>
+<ul>
 <li>The compilation is done every time the application is executed,
 which means start-up times are much worse than pre-compiled
 code.</li>
@@ -105,42 +109,42 @@  practice.)</li>
 <li>The JIT compiler must remain in (virtual) memory while the
 application is executing. This memory may be quite costly in an
 embedded application.</li>
-</UL>
+</ul>
 
-<P>While JIT compilers have an important place in a Java system, for
+<p>While JIT compilers have an important place in a Java system, for
 frequently used applications it is better to use a more traditional
 &quot;ahead-of-time&quot; or batch compiler. While many think of Java
 as primarily an internet/web language, others are interested in using
 Java as an alternative to traditional languages such as C++, provided
 performance is acceptable. For embedded applications, it makes much
 more sense to pre-compile the Java program, especially if the program
-is to be in ROM.</P>
+is to be in ROM.</p>
 
-<P>Cygnus is building a Java programming environment that is based on
+<p>Cygnus is building a Java programming environment that is based on
 a conventional compiler, linker, and debugger, using Java-enhanced
 versions of the existing GNU programming tools. These have been ported
 to just about every chip in use (including many chips only used in
 embedded systems), and so we will have a uniquely portable Java
-system. See <A HREF="java2.gif">Figure 2</A> for a model of the
-compilation process.</P>
+system. See <a href="java2.gif">Figure 2</a> for a model of the
+compilation process.</p>
 
-<P align="center">
-<a href="java2.gif"><IMG SRC="java2a.gif" alt=""></a>
+<p align="center">
+<a href="java2.gif"><img src="java2a.gif" alt="" /></a></p>
 
-<P align="center"><b>Figure 2:&nbsp;&nbsp;Compiled Java</b></P>
+<p align="center"><b>Figure 2:&nbsp;Compiled Java</b></p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <h3><a name="sec2">2 Issues with embedded Java</a></h3>
 
-<P>Sun's motto for Java is &quot;Write once, run anywhere&quot;. As
+<p>Sun's motto for Java is &quot;Write once, run anywhere&quot;. As
 part of that, Sun has been pushing Java as also suitable for embedded
 systems, announcing specifications for &quot;Embedded Java&quot; and
 &quot;Personal Java&quot; specifications. The latter (just published
 at the time of writing) is primarily a restricted library that a Java
-application can expect.</P>
+application can expect.</p>
 
-<P>&quot;Embedded systems&quot; covers a large spectrum from 4-bit
+<p>&quot;Embedded systems&quot; covers a large spectrum from 4-bit
 chips with tens of bytes of RAM, to 32- and 64-bit systems with
 megabytes of RAM. I believe it will be very difficult to squeeze a
 reasonably complete implementation of Java into less than one
@@ -150,25 +154,25 @@  general, there is less memory available 
 environment where Java usually runs. Those designers that have been
 leery of C++ because of performance concerns (perceived or real) will
 not embrace Java. On the other hand, those that have been leery of C++
-because of its complexity will find Java easier to master.</P>
+because of its complexity will find Java easier to master.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
 <h4><a name="sec2_1">2.1 Advantages of Java</a></h4>
 </blockquote>
 
-<P>Java has a number of advantages for embedded systems. Using classes
+<p>Java has a number of advantages for embedded systems. Using classes
 to organize the code enforces modularity, and encourages data
 abstraction. Java has many useful and standardized classes (for
 graphics, networking, simple math and containers,
 internationalization, files, and much more). This means a designer can
 count on having these libraries on any (full) implementation of
-Java.</P>
+Java.</p>
 
-<P>Java programs are generally more portable than C or C++ programs: </P>
+<p>Java programs are generally more portable than C or C++ programs: </p>
 
-<UL>
+<ul>
 <li>The size of integer, floats, and character is defined by the
 language.</li>
 
@@ -178,11 +182,11 @@  defined.</li>
 <li>Initial values of fields are defined, and the languages require
 that local variables be set before use in a way that the compiler can
 check.</li>
-</UL>
+</ul>
 
-<P>In fact, the only major non-determinacy in Java is due to
+<p>In fact, the only major non-determinacy in Java is due to
 time-dependencies between interacting threads. Safety-critical
-applications will find the following features very useful: </P>
+applications will find the following features very useful: </p>
 
 <ul>
 <li>More disciplined use of pointers, called &quot;references&quot;
@@ -198,24 +202,24 @@  case from error cases, and to handle the
 manner.</li>
 </ul>
 
-<P>The portability of Java (including a portable binary format) means
+<p>The portability of Java (including a portable binary format) means
 that an application can run on many hardware platforms, with no
-porting effort (at least that's the theory). </P>
+porting effort (at least that's the theory). </p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
 <h4><a name="sec2_2">2.2 Code compactness</a></h4>
 </blockquote>
 
-<P>It has been argued that even for ROM-based embedded systems (where
+<p>It has been argued that even for ROM-based embedded systems (where
 portability is not an issue), it still makes sense to use a
 bytecode-based implementation of Java, since the bytecodes are
 supposedly more compact than native code. However, it is not at all
 clear if that is really the case. The actual bytecode instructions of
 the Fib class (a program to calculate Fibonacci numbers, which is
-discussed in the section, <A HREF="#sec5">5. Status</A>) only
-take 134 bytes, while the compiled instructions for i86 and Sparc take
+discussed in the section, <a href="#sec5">5. Status</a>) only
+take 134 bytes, while the compiled instructions for i86 and SPARC take
 373 and 484 bytes respectively. (This is if we assume external classes
 are also pre-compiled; otherwise, 417 and 540 bytes are needed,
 respectively.) However, there is quite a bit of symbol table
@@ -226,21 +230,21 @@  information is represented - but it does
 space. (Pre-compiled code also needs space for the reflective data
 structure, about 520 bytes for this example.) Our tentative
 conclusion is that the space advantage of bytecodes is minor at best,
-whereas the speed penalty is major.</P>
+whereas the speed penalty is major.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
 <h4><a name="sec2_3">2.3 Space for standard run-time</a></h4>
 </blockquote>
 
-<P>In addition to the space needed for the user code, there is also a
+<p>In addition to the space needed for the user code, there is also a
 large chunk of fixed code for the run-time environment. This includes
 code for the standard libraries (such as <code>java.lang</code>), code
 for loading new classes, the garbage collector, and an interpreter or
-just-in-time compiler.</P>
+just-in-time compiler.</p>
 
-<P>In a memory-tight environment, it is desirable to be able to leave
+<p>In a memory-tight environment, it is desirable to be able to leave
 out some of this support code. For example, if there is no need for
 loading new classes at run-time, we can leave out the code for reading
 class files, and interpreting (or JIT-compiling) bytecodes. (If you
@@ -248,15 +252,15 @@  have a dynamic loader, you could still d
 compile them off-line.) Similarly, some embedded applications might
 not need support for Java's Abstract Windowing Toolkit, or
 networking, or decryption, while another might need some or all of
-these.</P>
+these.</p>
 
-<P>Depending on a conventional (static) linker to select only the code
+<p>Depending on a conventional (static) linker to select only the code
 that is actually needed does not work, since a Java class can be
 referenced using a run-time String expression passed to the
 <code>Class.forName</code> method. If that feature is not used, then a
-static linker can be used.</P>
+static linker can be used.</p>
 
-<P>The Java run-time needs to have access to the name and type of
+<p>The Java run-time needs to have access to the name and type of
 every field and method of every class that is loaded. This is not
 needed for normal operation (especially not when using precompiled
 methods); however, a program can examine this information using the
@@ -267,9 +271,9 @@  works by looking up fields and methods b
 JNI thus requires extra run-time memory for field and method
 information. Since the JNI is also quite slow, an embedded application
 may prefer to use a lower-level (but less portable) Native
-Interface.</P>
+Interface.</p>
 
-<P>Because applications and resources vary so widely, it is important
+<p>Because applications and resources vary so widely, it is important
 to have a Java VM/run-time than can be easily configured. Some
 applications may need access to dynamically loaded classes, the Java
 Native Interface, reflection, and a large class library. Other
@@ -279,24 +283,24 @@  different algorithms for garbage collect
 implementations. This implies the need for a configuration utility, so
 one can select the features one wants in a VM, much like one might
 need to configure kernel options before building an operating
-system.</P>
+system.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
 <h4><a name="sec2_4">2.4 Garbage collection</a></h4>
 </blockquote>
 
-<P>Programmers used to traditional malloc/free-style heap management
+<p>Programmers used to traditional malloc/free-style heap management
 tend to be skeptical about the efficiency of garbage collection. It is
 true that garbage collection usually takes a significant toll on
 execution time, and can lead to large unpredictable pauses. However,
 it is important to remember that is also an issue for manual heap
 allocations using malloc and free. There are many very poorly written
 <code>malloc/free</code> implementations in common use,
-just as there are inefficient implementations of garbage collection.</P>
+just as there are inefficient implementations of garbage collection.</p>
 
-<P>There are a number of incremental, parallel, or generational
+<p>There are a number of incremental, parallel, or generational
 garbage collection algorithms that provide performance as good or
 better than <code>malloc/free</code>. What is
 difficult, however, is ensuring that pause times are
@@ -306,58 +310,58 @@  triggered. The solution is to make sure 
 garbage collection on each allocation. Unfortunately, the only known
 algorithms that can handle hard-real time either require hardware
 assistance or are very inefficient. However, &quot;soft&quot;
-real-time can be implemented at reasonable cost.</P>
+real-time can be implemented at reasonable cost.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <h3><a name="sec3">3 Compiling Java</a></h3>
 
-<P>The core tool of Cygnus's Java implementation is the
+<p>The core tool of Cygnus's Java implementation is the
 compiler. This is <code>jc1</code>, a new GCC front-end (see
-Bibliography for <A HREF="#GCC">GCC</A>). This has similar structure
+Bibliography for <a href="#GCC">GCC</a>). This has similar structure
 as existing front-ends (such as <code>cc1plus</code>, the C++
 front-end), and shares most of the code with them. The most unusual
 aspect of <code>jc1</code> is that its &quot;parser&quot; reads
-<I>either</I> Java source files or Java bytecode files. (The first
+<em>either</em> Java source files or Java bytecode files. (The first
 release will only directly support bytecodes; parsing Java source will
 be done by invoking Sun's <code>javac</code>. A
 future version will
 provide an integrated Java parser, largely for the sake of compilation
 speed.) In any case, it is important that <code>jc1</code> can read
-bytecodes, for the following reasons: </P>
+bytecodes, for the following reasons:</p>
 
 
-<UL>
+<ul>
 <li>It is the natural way to get declarations of external classes;
 in this respect, a Java bytecode file is like a C++ pre-compiled
 header file.</li>
 
 <li>It is needed so we can support code produced from other tools
 that produce Java bytecodes (such as the Kawa Scheme-to-Java-bytecode
-compiler; see Bibliography for <A HREF="#Kawa">Kawa</A>).</li>
+compiler; see Bibliography for <a href="#Kawa">Kawa</a>).</li>
 
 <li>Some libraries are (unfortunately) distributed as Java
 bytecodes without source.</li>
-</UL>
+</ul>
 
-<P>Much of the work of the compiler is the same whether we are
+<p>Much of the work of the compiler is the same whether we are
 compiling from source code or from byte codes. For example emitting
 code to handle method invocation is the same either way. When we
 compile from source, we need a parser, semantic analysis, and
 error-checking. On the other hand, when parsing from bytecodes, we
 need to extract higher-level information from the lower-level
-bytecodes, which we will discuss in <A HREF="#sec3_1">3.1
-Transforming bytecodes</A>.</P>
+bytecodes, which we will discuss in <a href="#sec3_1">3.1
+Transforming bytecodes</a>.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
-<h4><A NAME="sec3_1">3.1 Transforming bytecodes</A></h4>
+<h4><a name="sec3_1">3.1 Transforming bytecodes</a></h4>
 </blockquote>
 
-<P>This section describes how <code>jc1</code> works.</P>
+<p>This section describes how <code>jc1</code> works.</p>
 
-<P>The executable content of a bytecode file contains a vector of
+<p>The executable content of a bytecode file contains a vector of
 bytecode instructions for each (non-native) method. The bytecodes are
 instructions for an abstract machine with some local variable
 registers and a stack used for expression evaluation. (The first few
@@ -377,9 +381,9 @@  and are enforced by the Java bytecode ve
 analysis in <code>jc1</code>, which lets us know for
 every program
 point, the current stack pointer, and the type of every local variable
-and stack slot.</P>
+and stack slot.</p>
 
-<P>Internally GCC uses two main
+<p>Internally GCC uses two main
 representations: The tree
 representation is at the level of an abstract syntax tree, and is used
 to represent high-level (fully-typed) expressions, declarations, and
@@ -389,9 +393,9 @@  to represent instructions, instruction p
 calculations in general. Constant folding is done using
 <code>trees</code>, but otherwise most optimizations
 are done at the
-<code>rtl</code> level.</P>
+<code>rtl</code> level.</p>
 
-<P>The basic strategy for translating Java stack-oriented bytecodes is
+<p>The basic strategy for translating Java stack-oriented bytecodes is
 that we create a dummy local variable for each Java local variable or
 stack slot. These are mapped to GCC &quot;virtual
 registers,&quot; and standard GCC register
@@ -399,23 +403,24 @@  allocation later
 assigns each virtual register to a hard register or a stack
 location. This makes it easy to map each opcode into
 <code>tree</code>-nodes or <code>rtl</code> to manipulate the virtual
-registers.</P>
+registers.</p>
 
-<P>As an example, consider how to compile <code>iadd</code>, which adds
+<p>As an example, consider how to compile <code>iadd</code>, which adds
 the top two ints on the stack. For illustration, assume the stack
 pointer is 3, and virtual registers 50, 51, and 52 are associated with
 stack slots 0, 1, and 2. The code generated by <code>jc1</code> is the
-following: </P>
+following:</p>
+
 <blockquote>
 <code>        reg51 := vreg51 + vreg52</code>
 </blockquote>
-<P>Note that the stack exists only at compile-time. There is no stack,
-stack pointer, or stack operations in the emitted code.</P>
+<p>Note that the stack exists only at compile-time. There is no stack,
+stack pointer, or stack operations in the emitted code.</p>
 
-<P>This simple model has some problems, compared to conventional
-compilers: </P>
+<p>This simple model has some problems, compared to conventional
+compilers:</p>
 
-<UL>
+<ul>
 <li>We would like to do constant folding, which is done at the
 <code>tree</code> level. However, <code>tree</code> nodes are
 typed.</li>
@@ -423,7 +428,7 @@  typed.</li>
 <li>The simple-minded approach uses lots of virtual registers, and
 the code generated is very bad. Running the optimizer (with the
 <code>-O</code> flag) fixes the generated code, but you still get a lot
-of useless stack slots. It would be nice not to <I>have</I> <I>to</I>
+of useless stack slots. It would be nice not to <em>have</em> <em>to</em>
 run the optimizer, and if you do, not to make unnecessary work for
 it.</li>
 
@@ -432,88 +437,89 @@  distinguishes the various machine &quot;
 and different-sized integers and floats. This causes problems because
 a given Java stack slot may have different types at different points
 in the code.</li>
-</UL>
+</ul>
 
-<P>The last problem we solve by using a separate virtual register for
+<p>The last problem we solve by using a separate virtual register for
 each machine mode. For example, for local variable slot 5 we might use
 <code>vreg40</code> when it contains an integer, and <code>vreg41</code>
 when it points an object reference. This is safe, because the Java
 verifier does not allow storing an integer in an object slot and later
-reusing the same value as an object reference or float.</P>
+reusing the same value as an object reference or float.</p>
 
-<P>The other two problems we solve by modeling the stack as a stack of
+<p>The other two problems we solve by modeling the stack as a stack of
 <code>tree</code> nodes, and not storing the results in their
 &quot;home&quot; virtual registers unless we have to. Thus jc1actually
-does the following for <code>iadd</code>: </P>
+does the following for <code>iadd</code>:</p>
 
-<blockquote><P><code>
-	     tree arg1 = pop_value (int_type_node);<br>
-             tree arg2 = pop_value (int_type_node);<br>
+<blockquote><code>
+	     tree arg1 = pop_value (int_type_node);<br />
+             tree arg2 = pop_value (int_type_node);<br />
              push_value (fold (build (PLUS_EXPR, int_type_node, arg1,
-arg2)));<br></code></P>
+arg2)));<br /></code>
 </blockquote>
-<P>The build function is the standard GCC function for
+<p>The build function is the standard GCC function for
 creating <code>tree</code>-nodes, while fold is the standard function
 for doing constant folding. The functions <code>pop_value</code> and
 <code>push_value</code> are specific to <code>jc1</code>, and keep track
 of which stack location corresponds to which <code>tree</code> node. No
-code is actually generated yet.</P>
+code is actually generated yet.</p>
 
-<P>This works for straight-line code (i.e. within a basic block). When
+<p>This works for straight-line code (i.e. within a basic block). When
 we come to a branch or a branch target, we have to flush the stack of
 <code>tree</code> nodes, and make sure the value of each stack slot gets
 saved in its &quot;home&quot; virtual register. The stack is usually
 empty at branches and branch targets, so this does not happen very
 often. Otherwise, we only emit actual <code>rtl</code> instructions to
 evaluate the expressions when we get to a side-effecting operation
-(such as a store or a method call).</P>
+(such as a store or a method call).</p>
 
-<P>Since we only allocate a virtual register when we need one, we are
+<p>Since we only allocate a virtual register when we need one, we are
 now using fewer virtual registers, which leads to better code. We also
 get the benefits of GCC constant folding, plus the existing
 machinery for selecting the right instructions for addition and other
-expressions.</P>
+expressions.</p>
 
-<P>The result is that we end up generating code using the same
+<p>The result is that we end up generating code using the same
 mechanisms that the GCC C and C++ front-ends do, and
-therefore we can expect similar code quality.</P>
+therefore we can expect similar code quality.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
 <h4><a name="sec3_2">3.2 Class meta-data</a></h4>
 </blockquote>
 
-<P>Compiling the executable content is only part of the problem. The
+<p>Compiling the executable content is only part of the problem. The
 Java run-time also needs an extensive data structure that describes
 each class with its fields and methods. This is the
 &quot;meta-data&quot; or &quot;reflective&quot; data for the
 class. The compiler has to somehow make it possible for the run-time
 system to correctly initialize the data structures before the compiled
-classes can be used.</P>
+classes can be used.</p>
 
-<P>If we are compiling from bytecodes, the compiler can just pass
+<p>If we are compiling from bytecodes, the compiler can just pass
 through the meta-data as they are encoded in the class file. (If the
 run-time supports dynamically loading new classes, it already knows
-how to read meta-data from a class file.)</P>
+how to read meta-data from a class file.)</p>
 
-<P>It is inconvenient if the meta-data and the compiled code are in
+<p>It is inconvenient if the meta-data and the compiled code are in
 different files. The run-time should be able to create its
 representation of the meta-data without having to go beyond its
 address space. For example reading in the meta-data from an external
 file may cause consistency problems, and it may not even be possible
-for embedded systems.</P>
+for embedded systems.</p>
 
-<P>A possible solution is to emit something like: </P>
+<p>A possible solution is to emit something like:</p>
 <blockquote>
 <code>
-	static const char FooClassData[] = "\xCa\xfe\xba\xbe...";<br>
-        static {<br>
-		LoadClassFromByteArray(FooClassData);<br>
-		Patch up method to point to code;<br>
+	static const char FooClassData[] = "\xCa\xfe\xba\xbe...";<br />
+        static {<br />
+		LoadClassFromByteArray(FooClassData);<br />
+		Patch up method to point to code;<br />
 </code>
 </blockquote>
-<P>The code marked <code>static</code> is compiled into
+
+<p>The code marked <code>static</code> is compiled into
 a dummy function
 that is executed at program startup. This can be handled using
 whatever mechanism is used to execute C++ static initializers. This
@@ -521,9 +527,9 @@  dummy function reads the meta-data in ex
 <code>FooClassData</code>, creates the internal
 representation, and
 enters the class into the class table. It then patches up the method
-descriptors so that they point to the compiled code.</P>
+descriptors so that they point to the compiled code.</p>
 
-<P>This works, but it is rather wasteful in terms of memory and
+<p>This works, but it is rather wasteful in terms of memory and
 startup time. We need space for both the external representation (in
 <code>FooClassData</code>) and the internal representation, and we have
 to spend time creating the latter from the former. It is much better
@@ -532,54 +538,54 @@  representation. If we use initialized st
 compiler statically allocate and initialize the internal data
 structures. This means the actual initialization needed at run is very
 little &ETH; most of it is just entering the meta-data into a global
-symbol table.</P>
+symbol table.</p>
 
-<P>Consider the following example class: </P>
+<p>Consider the following example class:</p>
 <blockquote>
 <code>
-	 public class Foo extends Bar {<br>
-	 &nbsp;&nbsp;&nbsp;&nbsp;public int a;<br>
-	 &nbsp;&nbsp;&nbsp;&nbsp;public int f(int j) { return a+j; }<br>
-	 };<br>
+	 public class Foo extends Bar {<br />
+	 &nbsp;&nbsp;&nbsp;&nbsp;public int a;<br />
+	 &nbsp;&nbsp;&nbsp;&nbsp;public int f(int j) { return a+j; }<br />
+	 };<br />
 </code>
 </blockquote>
 
-<P>That class compiles into something like the following: </P>
+<p>That class compiles into something like the following:</p>
 
 <blockquote>
-<code>int Foo_f (Foo* this, int j)<BR>
-{ return this-&gt;a + j; }<BR>
- <BR>
-struct Method Foo_methods[1] = {{<BR>
-   &nbsp;&nbsp;&nbsp;&nbsp;/* name: */   "f";<BR>
-   &nbsp;&nbsp;&nbsp;&nbsp;/* code: */   (Code) &amp;Foo_f;<BR>
-   &nbsp;&nbsp;&nbsp;&nbsp;/* access: */ PUBLIC,<BR>
-   &nbsp;&nbsp;&nbsp;&nbsp;/* etc */     ... <BR>
-}};<BR>
-<BR>
-struct Class Foo_class = {<BR>
-&nbsp;&nbsp;&nbsp;&nbsp;   /* name: */        "Foo",<BR>
-&nbsp;&nbsp;&nbsp;&nbsp;   /* num_methods: */ 1,<BR>
-&nbsp;&nbsp;&nbsp;&nbsp;   /* methods: */     Foo_methods,<BR>
-&nbsp;&nbsp;&nbsp;&nbsp;   /* super: */       &amp;Bar_class,<BR>
-&nbsp;&nbsp;&nbsp;&nbsp;   /* num_fields: */  1,<BR>
-&nbsp;&nbsp;&nbsp;&nbsp;   /* etc */          ...<BR>
-};<BR>
-<BR>
-static {<BR>
-&nbsp;&nbsp;&nbsp;&nbsp;  RegisterClass (&amp;Foo_class, "Foo");<BR>
+<code>int Foo_f (Foo* this, int j)<br />
+{ return this-&gt;a + j; }<br />
+ <br />
+struct Method Foo_methods[1] = {{<br />
+   &nbsp;&nbsp;&nbsp;&nbsp;/* name: */   "f";<br />
+   &nbsp;&nbsp;&nbsp;&nbsp;/* code: */   (Code) &amp;Foo_f;<br />
+   &nbsp;&nbsp;&nbsp;&nbsp;/* access: */ PUBLIC,<br />
+   &nbsp;&nbsp;&nbsp;&nbsp;/* etc */     ... <br />
+}};<br />
+<br />
+struct Class Foo_class = {<br />
+&nbsp;&nbsp;&nbsp;&nbsp;   /* name: */        "Foo",<br />
+&nbsp;&nbsp;&nbsp;&nbsp;   /* num_methods: */ 1,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;   /* methods: */     Foo_methods,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;   /* super: */       &amp;Bar_class,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;   /* num_fields: */  1,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;   /* etc */          ...<br />
+};<br />
+<br />
+static {<br />
+&nbsp;&nbsp;&nbsp;&nbsp;  RegisterClass (&amp;Foo_class, "Foo");<br />
 }
 </code>
 </blockquote>
-<P>Thus startup is fast, and does not require any dynamic allocation.</P>
+<p>Thus startup is fast, and does not require any dynamic allocation.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
 <h4><a name="sec3_3">3.3 Static references</a></h4>
 </blockquote>
 
-<P>A class may make references to <code>static</code>
+<p>A class may make references to <code>static</code>
 fields and methods of another class. If we can assume that the other
 class will also be <code>jc1</code>-compiled, then
 <code>jc1</code> can emit a direct reference to the
@@ -587,39 +593,39 @@  external <code>static</code> field or me
 a C++ compiler would). That is, a call to a
 <code>static</code> method can be compiled as a direct
 function call. If you want to make a static call from a pre-compiled
-class to a known class that you do <I>not</I> know is pre-compiled,
+class to a known class that you do <em>not</em> know is pre-compiled,
 you can try using extra indirection and a &quot;trampoline&quot; stub
 that jumps to the correct method. (Not that this feature is very
 useful: it makes little sense to pre-compile a class without also
-pre-compiling the other classes that it statically depends on.)</P>
+pre-compiling the other classes that it statically depends on.)</p>
 
-<P>A related problem has to do with string constants. The language
+<p>A related problem has to do with string constants. The language
 specification requires that string literals that are equal will
 compile into the same String object at run-time. This complicates
 separate compilation, and it makes it difficult to statically allocate
 the strings (as in done for C), unless you have a truly unusual
 linker. So, we compile references to string literals as indirect
 references to a pointer that gets initialized at class initialization
-time.</P>
+time.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
 <h4><a name="sec3_4">3.4 Linking</a></h4>
 </blockquote>
 
-<P>The <code>jc1</code> program creates standard
+<p>The <code>jc1</code> program creates standard
 assembler files that are processed by the standard unmodified GNU
 assembler. The resulting object files can be placed in a dynamic or
 static library, or linked (together with the run-time system) into an
 executable, using a standard linker. The only linker extension we
 really need is support for static initializers, but we already have
-that (since GCC supports C++).</P>
+that (since GCC supports C++).</p>
 
-<P>While we do not <I>need</I> any linker modification, there are some
-that may be desirable. Here are some ideas.</P>
+<p>While we do not <em>need</em> any linker modification, there are some
+that may be desirable. Here are some ideas.</p>
 
-<P>Java needs a lot of names at run-time for classes,
+<p>Java needs a lot of names at run-time for classes,
 files, local variables, methods, type signatures, and source
 files. These are represented in the constant pool of
 <code>.class</code> files as
@@ -630,20 +636,20 @@  meta-data. Two different class files may
 same name. It may be desirable to combine them to save space (and to
 speed up equality tests). That requires linker support. The compiler
 could place these names in a special section of the object file, and
-the linker could then combine identical names.</P>
+the linker could then combine identical names.</p>
 
-<P>The run-time maintains a global table of all loaded classes, so it
+<p>The run-time maintains a global table of all loaded classes, so it
 can find a class given its name. When most of the classes are
 statically compiled and allocated, it is reasonable to pre-compute
 (the static part of) the global class table. One idea is that the
 linker could build a perfect hash table of the classes in a library or
-program.</P>
+program.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <h3><a name="sec4">4. Run-time</a></h3>
 
-<P>Running a compiled Java program will need a suitable Java run-time
+<p>Running a compiled Java program will need a suitable Java run-time
 environment. This is in principle no different from C++ (which
 requires an extensive library, as well as support for memory
 allocation, exceptions, and so on). However, Java requires more
@@ -652,9 +658,9 @@  support for threads, garbage collection,
 and all the primitive Java methods. Full Java support also means being
 able to dynamically load new bytecoded classes, though this may not be
 needed in some embedded environments. Basically, the appropriate Java
-run-time environment is a Java Virtual Machine.</P>
+run-time environment is a Java Virtual Machine.</p>
 
-<P>It is possible to have <code>jc1</code> produce code
+<p>It is possible to have <code>jc1</code> produce code
 compatible with the Java Native Interface ABI. Such code could run
 under any Java VM that implements the JNI. However, the JNI has
 relatively high overhead, so if you are not concerned about binary
@@ -664,65 +670,65 @@  portability, use <code>.class</code> fil
 plan to support the portable JNI, we will also support such a
 lower-level ABI. Certainly the standard Java functionality (such as
 that in <code>java.lang</code> will be compiled to the
-lower-level ABI.</P>
+lower-level ABI.</p>
 
-<P>A low-level ABI is inherently dependent on a specific VM. We are
+<p>A low-level ABI is inherently dependent on a specific VM. We are
 using Kaffe, a free Java VM, written by Tim Wilkinson
-(see Bibliography for <A HREF="#Kaffe">Kaffe</A>), with help from
+(see Bibliography for <a href="#Kaffe">Kaffe</a>), with help from
 volunteers around the &quot;Net.&quot; Kaffe uses either a JIT
 compiler on many common platforms, or a conventional bytecode
 interpreter, which is quite portable (except for thread
 support). Using a JIT compiler makes it easy to call between
 pre-compiled and dynamically loaded methods (since both use the same
-calling convention).</P>
+calling convention).</p>
 
-<P>We are making many enhancements to make Kaffe a more suitable
+<p>We are making many enhancements to make Kaffe a more suitable
 target for pre-compiled code. One required change is to add a hook so
 that pre-compiled and pre-allocated classes can be added to the global
 table of loaded classes. This means implementing the
-<code>RegisterClass</code> function.</P>
+<code>RegisterClass</code> function.</p>
 
-<P>Other changes are not strictly needed, but are highly
+<p>Other changes are not strictly needed, but are highly
 desirable. The original Kaffe meta-data had some redundant
 data. Sometimes redundancy can increase run-time efficiency
-(<I>e.g</I>., caching, or a method dispatch table for virtual method
+(<em>e.g.</em>., caching, or a method dispatch table for virtual method
 calls). However, the gain has to be balanced against the extra
 complication and space. Space is especially critical for embedded
 applications, which is an important target for us. Therefore, we have
 put some effort into streamlining the Kaffe data structures, such as
-replacing linked lists by arrays.</P>
+replacing linked lists by arrays.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
 <h4><a name="sec4_1">4.1 Debugging</a></h4>
 </blockquote>
 
-<P>Our debugging strategy for Java is to enhance
+<p>Our debugging strategy for Java is to enhance
 GDB (the GNU debugger) so it can understand
 Java-compiled code. This follows from our philosophy of treating Java
 like other programming languages. This also makes it easier to debug
-multi-language applications (C <I>and</I> Java).</P>
+multi-language applications (C <em>and</em> Java).</p>
 
-<P>Adding support for Java requires adding a Java expression parser,
+<p>Adding support for Java requires adding a Java expression parser,
 and routines to print values and types in Java syntax. It should be
 easy to modify the existing C and C++ language support routines, since
 Java expressions and primitive types are very similar to those of
-C++. </P>
+C++.</p>
 
-<P>Adding support for Java objects is somewhat more work. Getting,
+<p>Adding support for Java objects is somewhat more work. Getting,
 setting, and printing of <code>Object</code> fields is
 basically the same as for C++. Printing an Object reference can be
 done using a format similar to that used by the default
 <code>toString</code> method the class followed by the
 address such as
 <code>java.io.DataInput@cf3408</code>. Sometimes you instead
-want to print the <I>contents</I> of the object, rather than its
+want to print the <i>contents</i> of the object, rather than its
 address (or identity). Strings should, by default, be printed using
 their contents, rather than their address. For other objects,
 GDB can invoke the <code>toString</code> method to get a printable
 representation, and print that. However, there should be different
-options to get different styles of output.</P>
+options to get different styles of output.</p>
 
 <p>GDB can evaluate a general
 user-supplied expression, including a function call. For Java, this
@@ -743,7 +749,7 @@  so it can get the information it needs f
 process. This also makes GDB start-up faster, since it makes it easier
 to only create type information when needed.</p>
 
-<P>Potentially duplicated meta-data includes the source line
+<p>Potentially duplicated meta-data includes the source line
 numbers. This is because a Java program needs to be able to do a stack
 trace, even without an external debugger. Ideally, the stack trace
 should include source line numbers. Therefore, it is best to put the
@@ -751,9 +757,9 @@  line numbers in a special read-only sect
 would be pointed to by the method meta-data, where both GDB and the
 internal Java stack dumper can get at it. (For embedded systems one
 would probably leave out line numbers in the run-time, and only keep
-it in the debug section of the executable file.) </P>
+it in the debug section of the executable file.) </p>
 
-<P>Extracting symbolic information from the process rather than from
+<p>Extracting symbolic information from the process rather than from
 the executable file is also more flexible, since it makes it easier to
 also support new classes that are loaded in at run-time. While the
 first releases will concentrate on debugging pre-compiled Java code,
@@ -762,30 +768,30 @@  the VM. This problem is eased if the VM 
 since in that case the representation of dynamically-(JIT-)compiled
 Java code is the same as pre-compiled code. However, we still need to
 provide hooks so that GDB knows when a new
-class is loaded into the VM.</P>
+class is loaded into the VM.</p>
 
 <p>Long-term, it might be useful to download Java code into
 GDB itself (so we can extend GDB
 using Java), but that requires integrating a
 Java evaluator into GDB.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
 <blockquote>
 <h4><a name="sec4_2">4.2 Profiling</a></h4>
 </blockquote>
 
-<P>One problem with Java is the lack of profiling tools. This makes it
+<p>One problem with Java is the lack of profiling tools. This makes it
 difficult to track down the &quot;hot-spots&quot; in an
 application. Using GCC to compile Java to native code lets us use
 existing profiling tools, such as <code>gprof</code>,
-and the <code>gcov</code> coverage analyzer.</P>
+and the <code>gcov</code> coverage analyzer.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
-<h3><A NAME="sec5">5 Status</a></h3>
+<h3><a name="sec5">5 Status</a></h3>
 
-<P>As of early July 1997, <code>jc1</code> was able to
+<p>As of early July 1997, <code>jc1</code> was able to
 compile a simple test program, which calculates the Fibonacci numbers
 (up to 36), both iteratively and recursively (which is slow!), and
 prints the results. No manual tinkering was needed with the assembly
@@ -794,9 +800,9 @@  code generated, which was assembled and 
 run-time engine. On a SparcStation 5 running Solaris2, it took 16
 seconds to execute. In comparison, the same program dynamically
 compiled by Kaffe's JIT takes 26 seconds, and Sun's JDK 1.1
-takes 88 seconds to run the same program.</P>
+takes 88 seconds to run the same program.</p>
 
-<P>These numbers are encouraging, but they need some context. Start-up
+<p>These numbers are encouraging, but they need some context. Start-up
 times (for class loading and just-in-time compilation) should in all
 cases be fairly minor, since the execution time is dominated by
 recursive calls. In the <code>jc1</code>-compiled case,
@@ -809,61 +815,59 @@  be some slight extra speed up if all the
 simple C-like features that are easy to compile: integer arithmetic,
 simple control structures, and direct recursion. The results cannot be
 directly generalized to larger programs that use object-oriented
-features more heavily.</P>
+features more heavily.</p>
 
-<P>The basic structure of the compiler works, but there is still quite
+<p>The basic structure of the compiler works, but there is still quite
 a bit of work to do. Many of the byte-codes are not supported yet, and
 neither is exception handling. Only some very simple Java-specific
 optimizations are implemented. (Of course,
 <code>jc1</code> benefits from the existing
-language-independent optimizations in GCC.)</P>
+language-independent optimizations in GCC.)</p>
 
-<P>The Kaffe VM works on most Java code. We have enhanced it in
+<p>The Kaffe VM works on most Java code. We have enhanced it in
 various ways, and modified the data structures to be simpler and more
-suitable for being emitted by the compiler.</P>
+suitable for being emitted by the compiler.</p>
 
-<P>The Java support in the GDB debugger is
+<p>The Java support in the GDB debugger is
 partially written, but there is still quite a bit to go before it is
 user-friendly. We have not started work on our own library
-implementation or source-code compiler.</P>
+implementation or source-code compiler.</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
-<P>&nbsp;</P>
 <h3><a name="ack">Acknowledgements</a></h3>
-<P>This paper is partly based on a document
-called &quot;A GCC-based Java Implementation&quot; (<FONT
-FACE="Symbol">&#211;</FONT> 1997, IEEE), which was presented at IEEE Compcon,
-Spring 1997.</P>
+<p>This paper is partly based on a document
+called &quot;A GCC-based Java Implementation&quot; (<font
+face="Symbol">&#211;</font> 1997, IEEE), which was presented at IEEE Compcon,
+Spring 1997.</p>
 
 <h3><a name="biblio">Bibliography</a></h3>
 
-<P><A NAME="GCC"></A>[GCC] <I>Using GNU CC</I><BR>
-Richard Stallman<BR>
-<A HREF="http://www.gnu.org/doc/doc.html">Free Software
-Foundation</A>, 1996.</P>
-
-<P><A NAME="JavaSpec"></A>[JavaSpec] <I>The Java Language
-Specification</I><BR>
-James Gosling, Bill Joy, Guy Steele<BR>
-Addison-Wesley, 1996.</P>
-
-<P><A NAME="JavaVM"></A>[JavaVMSpec] <I>The Java Virtual Machine
-Specification</I><BR>
-Tim Lindholm, Frank Yellin<BR>
-Addison-Wesley, 1996.</P>
-
-<P><A NAME="Kaffe"></A>[Kaffe] <I>Kaffe, a virtual machine to run
-Java code</I><BR>
-Tim Wilkinson<BR>
-<A HREF="http://www.kaffe.org/">http://www.kaffe.org/</A></P>
-
-<P><A NAME="Kawa"></A>[Kawa] <I>Kawa, the Java-based Scheme System</I><BR>
-Per Bothner<BR>
-<A
-HREF="http://www.cygnus.com/~bothner/kawa.html">http://www.cygnus.com/~bothner/kawa.html</A></P>
+<p><a name="GCC"></a>[GCC] <em>Using GNU CC</em><br />
+Richard Stallman<br />
+<a href="http://www.gnu.org/doc/doc.html">Free Software
+Foundation</a>, 1996.</p>
+
+<p><a name="JavaSpec"></a>[JavaSpec] <em>The Java Language
+Specification</em><br />
+James Gosling, Bill Joy, Guy Steele<br />
+Addison-Wesley, 1996.</p>
+
+<p><a name="JavaVM"></a>[JavaVMSpec] <em>The Java Virtual Machine
+Specification</em><br />
+Tim Lindholm, Frank Yellin<br />
+Addison-Wesley, 1996.</p>
+
+<p><a name="Kaffe"></a>[Kaffe] <em>Kaffe, a virtual machine to run
+Java code</em><br />
+Tim Wilkinson<br />
+<a href="http://www.kaffe.org/">http://www.kaffe.org/</a></p>
+
+<p><a name="Kawa"></a>[Kawa] <em>Kawa, the Java-based Scheme System</em><br />
+Per Bothner<br />
+http://www.cygnus.com/~bothner/kawa.html</p>
 
-<P><a href="#top">Top of Page</a><p>
+<p><a href="#top">Top of Page</a></p>
 
-</BODY>
+</body>
 </html>