The final step to achieve the JVM port is to support the OP-codes in the IR. In this area, the B module is most useful. The B::JVM::Jasmin module that generates the Jasmin assembler from perl's IR is written as a subclass of B. It descends the syntax tree provided by the IR, in a depth-first fashion. For each node in the OP-tree, the module processes that node using the emitter to generate Jasmin code. The emitted Jasmin code utilizes the various data type classes to perform the task the OP-code would have performed had it been run on the PVM.
|
As an example, Figure 4.3 presents the code from B::JVM::Jasmin that handles the ``gvsv'' SVOP. In this code segment, we see part of the subroutine, B::SVOP::JVMJasmin. The name indicates that it is the code for handling SVOPs for the Jasmin-based JVM port. The B module identifies that a given OP is an SVOP, and calls the routine. As a user of B, B::JVM::Jasmin provides the JVMJasmin portion of the name. This name is given on the command-line via the O module, so the user can indicate that the Jasmin-based JVM back-end is desired.
The first argument when OP-code subroutines, such as B::SVOP::JVMJasmin, are invoked is the object referring to the current OP-code. Usually, the name method is called to find the exact type of the OP-code, and Figure 4.3 reflects this.
However, in Figure 4.3, only the code for handling the ``gvsv'' is shown. The ``gvsv'' OP-code is used when a global scalar variable is mentioned. This OP-code must find the actual data of the variable by searching for it in the name space. To generate the equivalent Jasmin code for this OP-code, the three Java classes, Stash, GV, and Scalar, must be used. These are equivalents to stashes, GVs and SVs on the PVM [1].
If the name of the variable for the given ``gvsv'' SVOP is, for example, $foo, then the code in Figure 4.3 generates Jasmin assembler that looks something like this:
getstatic Stash/DEF_STASH LStash;
ldc "main"
invokevirtual findNamespace(Ljava/lang/String;)LStash;
ldc "foo"
invokevirtual Stash/findGV(Ljava/lang/String;)Linternals/GV;
invokevirtual GV/getScalar()LScalar;
or, as its (easier to read) Java
equivalent4.2:
Stash.DEF_STASH.findNamespace("main").findGV("foo").getScalar();
If you compare this to the process described in [1] of how a stashes work inside perl, it is easy to see that this is equivalent code for a ``gvsv'' OP-code (given that the Stash and GV Java classes do their jobs correctly!).
Copyright © 2000, 2001 Bradley M. Kuhn.
Verbatim copying and distribution of this entire thesis is permitted in any medium, provided this notice is preserved.