📄 compiling.doc.html
字号:
of 2:<p><blockquote><pre><code>int align2grain(int i, int grain) {</code><code> return ((i + grain-1) & ~(grain-1));</code><code>}</code></pre></blockquote><a name="15003"></a>Operands for arithmetic operations are popped from the operand stack, and the results of operations are pushed back onto the operand stack. Results of arithmetic subcomputations can thus be made available as operands of their nesting computation. For instance, the calculation of <code>~(grain</code>-<code>1)</code> is handled by these instructions:<p><blockquote><pre> 5 iload_2 // Push <code>grain</code> 6 iconst_1 // Push <code>int</code> constant <code>1</code> 7 isub // Subtract; push result 8 iconst_m1 // Push <code>int</code> constant -<code>1</code> 9 ixor // Do XOR; push result </pre></blockquote>First <code>grain</code>  -  <code>1</code> is calculated using the contents of local variable 2 and an immediate<code>int</code> value <code>1</code>. These operands are popped from the operand stack and their difference pushed back onto the operand stack. The difference is thus immediatelyavailable for use as one operand of the ixor instruction. (Recall that ~<code>x</code> == -<code>1^x</code>.) Similarly, the result of the ixor instruction becomes an operand for the subsequent iand instruction.<p><a name="9759"></a>The code for the entire method follows:<p><blockquote><pre>Method <code>int</code> <code>align2grain(int,int)</code> 0 iload_1 1 iload_2 2 iadd 3 iconst_1 4 isub 5 iload_2 6 iconst_1 7 isub 8 iconst_m1 9 ixor 10 iand 11 ireturn</pre></blockquote><a name="5841"></a><hr><h2>7.4 Accessing the Runtime Constant Pool</h2>Many numeric constants, as well as objects, fields, and methods, are accessed via the runtime constant pool of the current class. Object access is considered later <a href="Compiling.doc.html#4089">(§7.8)</a>. Data of types <code>int</code>, <code>long</code>, <code>float</code>, and <code>double</code>, as well as references to instances of class <code>String</code>, are managed using the ldc, ldc_w, and ldc2_w instructions.<p><a name="6072"></a>The ldc and ldc_w instructions are used to access values in the runtime constant pool (including instances of class <code>String</code>) of types other than <code>double</code> and <code>long</code>. The ldc_w instruction is used in place of ldc only when there is a large number of runtime constant pool items and a larger index is needed to access an item. The ldc2_w instruction is used to access all values of types <code>double</code> and <code>long</code>; there is no non-wide variant.<p><a name="6073"></a>Integral constants of types <code>byte</code>, <code>char</code>, or <code>short</code>, as well as small <code>int</code> values, may be compiled using the bipush, sipush, or iconst_<i> instructions, as seen earlier <a href="Compiling.doc.html#4182">(§7.2)</a>. Certain small floating-point constants may be compiled using the fconst_<f> and dconst_<d> instructions. <p><a name="10300"></a>In all of these cases, compilation is straightforward. For instance, the constants for<p><blockquote><pre><code>void useManyNumeric() {</code><code> int i = 100;</code><code> int j = 1000000;</code><code> long l1 = 1;</code><code> long l2 = 0xffffffff;</code><code> double d = 2.2;</code><code> ...do some calculations...</code><code>}</code></pre></blockquote>are set up as follows:<p><blockquote><pre>Method <code>void</code> <code>useManyNumeric()</code> 0 bipush 100 // Push a small <code>int</code> with bipush 2 istore_1 3 ldc #1 // Push <code>int</code> constant <code>1000000</code>; a larger <code>int</code> // value uses ldc 5 istore_2 6 lconst_1 // A tiny <code>long</code> value uses short, fast lconst_1 7 lstore_3 8 ldc2_w #6 // Push <code>long</code> <code>0xffffffff</code> (that is, an <code>int</code> -<code>1</code>); any // <code>long</code> constant value can be pushed using ldc2_w 11 lstore 5 13 ldc2_w #8 // Push <code>double</code> constant <code>2.200000</code>; uncommon // <code>double</code> values are also pushed using ldc2_w 16 dstore 7...do those calculations...</pre></blockquote><a name="8478"></a><hr><h2>7.5 More Control Examples</h2>Compilation of <code>for</code> statements was shown in an earlier section <a href="Compiling.doc.html#4182">(§7.2)</a>. Most of the Java programming language's other control constructs (<code>if-then-else</code>, <code>do</code>, <code>while</code>, <code>break</code>, and <code>continue</code>) are also compiled in the obvious ways. The compilation of <code>switch</code> statements is handled in a separate section (<a href="Compiling.doc.html#14942">Section 7.10, "Compiling Switches"</a>), as are the compilation of exceptions (<a href="Compiling.doc.html#9934">Section 7.12, "Throwing and HandlingExceptions"</a>) and the compilation of <code>finally</code> clauses (<a href="Compiling.doc.html#13789">Section 7.13, "Compiling <sub>finally</sub>"</a>).<p><a name="14987"></a>As a further example, a <code>while</code> loop is compiled in an obvious way, although the specific control transfer instructions made available by the Java virtual machine vary by data type. As usual, there is more support for data of type <code>int</code>, for example:<p><blockquote><pre><code>void whileInt() {</code><code> int i = 0;</code><code> while (i < 100) {</code><code> i++;</code><code> }</code><code>}</code></pre></blockquote>is compiled to<p><blockquote><pre>Method <code>void</code> <code>whileInt()</code> 0 iconst_0 1 istore_1 2 goto 8 5 iinc 1 1 8 iload_1 9 bipush 100 11 if_icmplt 5 14 return</pre></blockquote><a name="8508"></a>Note that the test of the <code>while</code> statement (implemented using the if_icmplt instruction) is at the bottom of the Java virtual machine code for the loop. (This was also the case in the <code>spin</code> examples earlier.) The test being at the bottom of the loop forces the use of a goto instruction to get to the test prior to the first iteration of the loop. If that test fails, and the loop body is never entered, this extra instruction is wasted. However, <code>while</code> loops are typically used when their body is expected to be run, often for many iterations. For subsequent iterations, putting the test at the bottom of the loop saves a Java virtual machine instruction each time around the loop: if the test were at the top of the loop, the loop body would need a trailing goto instruction to get back to the top.<p><a name="8700"></a>Control constructs involving other data types are compiled in similar ways, but must use the instructions available for those data types. This leads to somewhat less efficient code because more Java virtual machine instructions are needed, for example:<p><blockquote><pre><code>void whileDouble() {</code><code> double i = 0.0;</code><code> while (i < 100.1) {</code><code> i++;</code><code> }</code><code>}</code></pre></blockquote>is compiled to<p><blockquote><pre>Method <code>void</code> <code>whileDouble()</code> 0 dconst_0 1 dstore_1 2 goto 9 5 dload_1 6 dconst_1 7 dadd 8 dstore_1 9 dload_1 10 ldc2_w #4 // Push <code>double</code> constant <code>100.1</code> 13 dcmpg // To do the compare and branch we have to use... 14 iflt 5 // ...two instructions 17 return</pre></blockquote><a name="8555"></a>Each floating-point type has two comparison instructions: fcmpl and fcmpg for type <code>float</code>, and dcmpl and dcmpg for type <code>double</code>. The variants differ only in their treatment of NaN. NaN is unordered, so all floating-point comparisons fail if either of their operands is NaN. The compiler chooses the variant of the comparison instruction for the appropriate type that produces the same result whether the comparison fails on non-NaN values or encounters a NaN. <p><a name="18373"></a>For instance:<p><blockquote><pre><code>int lessThan100(double d) {</code><code> if (d < 100.0) {</code><code> return 1; </code><code> } else {</code><code> return -1; </code><code> }</code><code>}</code></pre></blockquote>compiles to<p><blockquote><pre>Method <code>int</code> <code>lessThan100(double)</code> 0 dload_1 1 ldc2_w #4 // Push <code>double</code> constant <code>100.0</code> 4 dcmpg // Push 1 if <code>d</code> is NaN or <code>d</code> \> <code>100.0</code>; // push 0 if <code>d</code> == <code>100.0</code> 5 ifge 10 // Branch on 0 or 1 8 iconst_1 9 ireturn 10 iconst_m1 11 ireturn</pre></blockquote>If <code>d</code> is not NaN and is less than <code>100.0</code>, the dcmpg instruction pushes an <code>int</code> -1 onto the operand stack, and the ifge instruction does not branch. Whether <code>d</code> is greater than <code>100.0</code> or is NaN, the dcmpg instruction pushes an <code>int</code> 1 onto the operand stack, and the ifge branches. If <code>d</code> is equal to <code>100.0</code>, the dcmpg instruction pushes an <code>int</code> 0 onto the operand stack, and the ifge branches.<p><a name="10361"></a>The dcmpl instruction achieves the same effect if the comparison is reversed:<p><blockquote><pre><code>int greaterThan100(double d) {</code><code> if (d > 100.0) {</code><code> return 1; </code><code> } else {</code><code> return -1; </code><code> }</code><code>}</code></pre></blockquote>becomes<p><blockquote><pre>Method <code>int</code> <code>greaterThan100(double)</code> 0 dload_1 1 ldc2_w #4 // Push <code>double</code> constant <code>100.0</code> 4 dcmpl // Push -1 if <code>d</code> is Nan or <code>d</code> <<code> 100.0</code>; // push 0 if <code>d</code> == <code>100.0</code> 5 ifle 10 // Branch on 0 or -1 8 iconst_1 9 ireturn 10 iconst_m1 11 ireturn</pre></blockquote>Once again, whether the comparison fails on a non-NaN value or because it is passed a NaN, the dcmpl instruction pushes an <code>int</code> value onto the operand stack that causes the ifle to branch. If both of the dcmp instructions did not exist, one of the example methods would have had to do more work to detect NaN.<p><a name="8556"></a><hr><h2>7.6 Receiving Arguments</h2>If <em>n</em> arguments are passed to an instance method, they are received, by convention, in the local variables numbered 1 through n of the frame created for the new method invocation. The arguments are received in the order they were passed. For example:<p><blockquote><pre><code>int addTwo(int i, int j) {</code><code> return i + j;</code><code>}</code></pre></blockquote>compiles to<p><blockquote><pre>Method <code>int</code> <code>addTwo(int,int)</code> 0 iload_1 // Push value of local variable 1 (<code>i</code>) 1 iload_2 // Push value of local variable 2 (<code>j</code>) 2 iadd // Add; leave <code>int</code> result on operand stack 3 ireturn // Return <code>int</code> result</pre></blockquote><a name="9840"></a>By convention, an instance method is passed a <code>reference</code> to its instance in local variable 0. In the Java programming language the instance is accessible via the <code>this</code> keyword. <p><a name="9846"></a>Class (<code>static</code>) methods do not have an instance, so for them this use of local variable zero is unnecessary. A class method starts using local variables at index zero. If the <code>addTwo</code> method were a class method, its arguments would be passed in a similar way to the first version:<p><blockquote><pre><code>static int addTwoStatic(int i, int j) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -