package org.eclipse.jdt.internal.compiler.codegen; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import java.io.*; | |
import java.util.*; | |
import org.eclipse.jdt.internal.compiler.*; | |
import org.eclipse.jdt.internal.compiler.impl.*; | |
import org.eclipse.jdt.internal.compiler.ast.*; | |
import org.eclipse.jdt.internal.compiler.classfmt.*; | |
import org.eclipse.jdt.internal.compiler.flow.*; | |
import org.eclipse.jdt.internal.compiler.lookup.*; | |
import org.eclipse.jdt.internal.compiler.problem.*; | |
import org.eclipse.jdt.internal.compiler.util.*; | |
public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, BaseTypes, TypeConstants, TypeIds { | |
// It will be responsible for the following items. | |
// -> Tracking Max Stack. | |
public int stackMax; // Use Ints to keep from using extra bc when adding | |
public int stackDepth; // Use Ints to keep from using extra bc when adding | |
public int maxLocals; | |
public static final int max = 100; // Maximum size of the code array | |
public static final int growFactor = 400; | |
public static final int LABELS_INCREMENT = 5; | |
public byte[] bCodeStream; | |
public int pcToSourceMapSize; | |
public int[] pcToSourceMap = new int[24]; | |
public int lastEntryPC; // last entry recorded | |
public int[] lineSeparatorPositions; | |
public int position; // So when first set can be incremented | |
public int classFileOffset; | |
public int startingClassFileOffset; // I need to keep the starting point inside the byte array | |
public ConstantPool constantPool; // The constant pool used to generate bytecodes that need to store information into the constant pool | |
public ClassFile classFile; // The current classfile it is associated to. | |
// local variable attributes output | |
public static final int LOCALS_INCREMENT = 10; | |
public LocalVariableBinding[] locals = new LocalVariableBinding[LOCALS_INCREMENT]; | |
static LocalVariableBinding[] noLocals = new LocalVariableBinding[LOCALS_INCREMENT]; | |
public LocalVariableBinding[] visibleLocals = new LocalVariableBinding[LOCALS_INCREMENT]; | |
static LocalVariableBinding[] noVisibleLocals = new LocalVariableBinding[LOCALS_INCREMENT]; | |
int visibleLocalsCount; | |
public AbstractMethodDeclaration methodDeclaration; | |
public ExceptionLabel[] exceptionHandlers = new ExceptionLabel[LABELS_INCREMENT]; | |
static ExceptionLabel[] noExceptionHandlers = new ExceptionLabel[LABELS_INCREMENT]; | |
public int exceptionHandlersNumber; | |
public static FieldBinding[] ImplicitThis = new FieldBinding[] {}; | |
public boolean generateLineNumberAttributes; | |
public boolean generateLocalVariableTableAttributes; | |
public boolean preserveUnusedLocals; | |
// store all the labels placed at the current position to be able to optimize | |
// a jump to the next bytecode. | |
public Label[] labels = new Label[LABELS_INCREMENT]; | |
static Label[] noLabels = new Label[LABELS_INCREMENT]; | |
public int countLabels; | |
public int allLocalsCounter; | |
public int maxFieldCount; | |
// to handle goto_w | |
public boolean wideMode = false; | |
public static final CompilationResult RESTART_IN_WIDE_MODE = new CompilationResult((char[])null, 0, 0); | |
public CodeStream(ClassFile classFile) { | |
generateLineNumberAttributes = (classFile.produceDebugAttributes & CompilerOptions.Lines) != 0; | |
generateLocalVariableTableAttributes = (classFile.produceDebugAttributes & CompilerOptions.Vars) != 0; | |
if (generateLineNumberAttributes) { | |
lineSeparatorPositions = classFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions; | |
} | |
} | |
final public void aaload() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aaload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_aaload); | |
} | |
} | |
final public void aastore() { | |
countLabels = 0; | |
stackDepth -= 3; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aastore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_aastore); | |
} | |
} | |
final public void aconst_null() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aconst_null; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_aconst_null); | |
} | |
} | |
public final void addDefinitelyAssignedVariables(Scope scope, int initStateIndex) { | |
// Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect | |
if (!generateLocalVariableTableAttributes) | |
return; | |
/* if (initStateIndex == lastInitStateIndexWhenAddingInits) | |
return; | |
lastInitStateIndexWhenAddingInits = initStateIndex; | |
if (lastInitStateIndexWhenRemovingInits != initStateIndex){ | |
lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index | |
// remove(1)-add(1)-remove(1) -> ignore second remove | |
// remove(1)-add(2)-remove(1) -> perform second remove | |
} | |
*/ for (int i = 0; i < visibleLocalsCount; i++) { | |
LocalVariableBinding localBinding = visibleLocals[i]; | |
if (localBinding != null) { | |
// Check if the local is definitely assigned | |
if ((initStateIndex != -1) && isDefinitelyAssigned(scope, initStateIndex, localBinding)) { | |
if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) { | |
/* There are two cases: | |
* 1) there is no initialization interval opened ==> add an opened interval | |
* 2) there is already some initialization intervals but the last one is closed ==> add an opened interval | |
* An opened interval means that the value at localBinding.initializationPCs[localBinding.initializationCount - 1][1] | |
* is equals to -1. | |
* initializationPCs is a collection of pairs of int: | |
* first value is the startPC and second value is the endPC. -1 one for the last value means that the interval | |
* is not closed yet. | |
*/ | |
localBinding.recordInitializationStartPC(position); | |
} | |
} | |
} | |
} | |
} | |
public void addLabel(Label aLabel) { | |
if (countLabels == labels.length) | |
System.arraycopy(labels, 0, (labels = new Label[countLabels + LABELS_INCREMENT]), 0, countLabels); | |
labels[countLabels++] = aLabel; | |
} | |
public void addVisibleLocalVariable(LocalVariableBinding localBinding) { | |
if (!generateLocalVariableTableAttributes) | |
return; | |
if (visibleLocalsCount >= visibleLocals.length) { | |
System.arraycopy(visibleLocals, 0, (visibleLocals = new LocalVariableBinding[visibleLocalsCount * 2]), 0, visibleLocalsCount); | |
} | |
visibleLocals[visibleLocalsCount++] = localBinding; | |
} | |
final public void aload(int iArg) { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_aload); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
// Don't need to use the wide bytecode | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_aload); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) (iArg); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void aload_0() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_aload_0); | |
} | |
} | |
final public void aload_1() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_aload_1); | |
} | |
} | |
final public void aload_2() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_aload_2); | |
} | |
} | |
final public void aload_3() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_aload_3); | |
} | |
} | |
public final void anewarray(TypeBinding typeBinding) { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_anewarray; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_anewarray); | |
} | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
} | |
public void anewarrayJavaLangClass() { | |
// anewarray: java.lang.Class | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_anewarray; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_anewarray); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangClass()); | |
} | |
public void anewarrayJavaLangObject() { | |
// anewarray: java.lang.Object | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_anewarray; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_anewarray); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangObject()); | |
} | |
final public void areturn() { | |
countLabels = 0; | |
stackDepth--; | |
// the stackDepth should be equal to 0 | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_areturn; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_areturn); | |
} | |
} | |
public void arrayAt(int typeBindingID) { | |
switch (typeBindingID) { | |
case T_int : | |
this.iaload(); | |
break; | |
case T_byte : | |
case T_boolean : | |
this.baload(); | |
break; | |
case T_short : | |
this.saload(); | |
break; | |
case T_char : | |
this.caload(); | |
break; | |
case T_long : | |
this.laload(); | |
break; | |
case T_float : | |
this.faload(); | |
break; | |
case T_double : | |
this.daload(); | |
break; | |
default : | |
this.aaload(); | |
} | |
} | |
public void arrayAtPut(int elementTypeID, boolean valueRequired) { | |
switch (elementTypeID) { | |
case T_int : | |
if (valueRequired) | |
dup_x2(); | |
iastore(); | |
break; | |
case T_byte : | |
case T_boolean : | |
if (valueRequired) | |
dup_x2(); | |
bastore(); | |
break; | |
case T_short : | |
if (valueRequired) | |
dup_x2(); | |
sastore(); | |
break; | |
case T_char : | |
if (valueRequired) | |
dup_x2(); | |
castore(); | |
break; | |
case T_long : | |
if (valueRequired) | |
dup2_x2(); | |
lastore(); | |
break; | |
case T_float : | |
if (valueRequired) | |
dup_x2(); | |
fastore(); | |
break; | |
case T_double : | |
if (valueRequired) | |
dup2_x2(); | |
dastore(); | |
break; | |
default : | |
if (valueRequired) | |
dup_x2(); | |
aastore(); | |
} | |
} | |
final public void arraylength() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_arraylength; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_arraylength); | |
} | |
} | |
final public void astore(int iArg) { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_astore); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_astore); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void astore_0() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_astore_0); | |
} | |
} | |
final public void astore_1() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_astore_1); | |
} | |
} | |
final public void astore_2() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_astore_2); | |
} | |
} | |
final public void astore_3() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_astore_3); | |
} | |
} | |
final public void athrow() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_athrow; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_athrow); | |
} | |
} | |
final public void baload() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_baload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_baload); | |
} | |
} | |
final public void bastore() { | |
countLabels = 0; | |
stackDepth -= 3; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_bastore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_bastore); | |
} | |
} | |
final public void bipush(byte b) { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_bipush; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_bipush); | |
} | |
writeSignedByte(b); | |
} | |
final public void caload() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_caload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_caload); | |
} | |
} | |
final public void castore() { | |
countLabels = 0; | |
stackDepth -= 3; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_castore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_castore); | |
} | |
} | |
public final void checkcast(TypeBinding typeBinding) { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_checkcast; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_checkcast); | |
} | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
} | |
public final void checkcastJavaLangError() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_checkcast; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_checkcast); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangError()); | |
} | |
final public void d2f() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_d2f; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_d2f); | |
} | |
} | |
final public void d2i() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_d2i; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_d2i); | |
} | |
} | |
final public void d2l() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_d2l; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_d2l); | |
} | |
} | |
final public void dadd() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dadd; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dadd); | |
} | |
} | |
final public void daload() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_daload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_daload); | |
} | |
} | |
final public void dastore() { | |
countLabels = 0; | |
stackDepth -= 4; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dastore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dastore); | |
} | |
} | |
final public void dcmpg() { | |
countLabels = 0; | |
stackDepth -= 3; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dcmpg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dcmpg); | |
} | |
} | |
final public void dcmpl() { | |
countLabels = 0; | |
stackDepth -= 3; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dcmpl; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dcmpl); | |
} | |
} | |
final public void dconst_0() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dconst_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dconst_0); | |
} | |
} | |
final public void dconst_1() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dconst_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dconst_1); | |
} | |
} | |
final public void ddiv() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ddiv; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ddiv); | |
} | |
} | |
public void decrStackSize(int offset) { | |
stackDepth -= offset; | |
} | |
final public void dload(int iArg) { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals < iArg + 2) { | |
maxLocals = iArg + 2; // + 2 because it is a double | |
} | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dload); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
// Don't need to use the wide bytecode | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dload); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void dload_0() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals < 2) { | |
maxLocals = 2; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dload_0); | |
} | |
} | |
final public void dload_1() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals < 3) { | |
maxLocals = 3; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dload_1); | |
} | |
} | |
final public void dload_2() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals < 4) { | |
maxLocals = 4; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dload_2); | |
} | |
} | |
final public void dload_3() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals < 5) { | |
maxLocals = 5; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dload_3); | |
} | |
} | |
final public void dmul() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dmul; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dmul); | |
} | |
} | |
final public void dneg() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dneg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dneg); | |
} | |
} | |
final public void drem() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_drem; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_drem); | |
} | |
} | |
final public void dreturn() { | |
countLabels = 0; | |
stackDepth -= 2; | |
// the stackDepth should be equal to 0 | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dreturn; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dreturn); | |
} | |
} | |
final public void dstore(int iArg) { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals <= iArg + 1) { | |
maxLocals = iArg + 2; | |
} | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dstore); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dstore); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void dstore_0() { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 2) { | |
maxLocals = 2; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dstore_0); | |
} | |
} | |
final public void dstore_1() { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 3) { | |
maxLocals = 3; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dstore_1); | |
} | |
} | |
final public void dstore_2() { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 4) { | |
maxLocals = 4; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dstore_2); | |
} | |
} | |
final public void dstore_3() { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 5) { | |
maxLocals = 5; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dstore_3); | |
} | |
} | |
final public void dsub() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dsub; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dsub); | |
} | |
} | |
final public void dup() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dup); | |
} | |
} | |
final public void dup_x1() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup_x1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dup_x1); | |
} | |
} | |
final public void dup_x2() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup_x2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dup_x2); | |
} | |
} | |
final public void dup2() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dup2); | |
} | |
} | |
final public void dup2_x1() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup2_x1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dup2_x1); | |
} | |
} | |
final public void dup2_x2() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup2_x2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_dup2_x2); | |
} | |
} | |
public void exitUserScope(BlockScope blockScope) { | |
// mark all the scope's locals as loosing their definite assignment | |
if (!generateLocalVariableTableAttributes) | |
return; | |
for (int i = 0; i < visibleLocalsCount; i++) { | |
LocalVariableBinding visibleLocal = visibleLocals[i]; | |
if ((visibleLocal != null) && (visibleLocal.declaringScope == blockScope)) { | |
// there maybe some some preserved locals never initialized | |
if (visibleLocal.initializationCount > 0){ | |
visibleLocals[i].recordInitializationEndPC(position); | |
} | |
visibleLocals[i] = null; // this variable is no longer visible afterwards | |
} | |
} | |
} | |
final public void f2d() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_f2d; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_f2d); | |
} | |
} | |
final public void f2i() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_f2i; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_f2i); | |
} | |
} | |
final public void f2l() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_f2l; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_f2l); | |
} | |
} | |
final public void fadd() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fadd; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fadd); | |
} | |
} | |
final public void faload() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_faload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_faload); | |
} | |
} | |
final public void fastore() { | |
countLabels = 0; | |
stackDepth -= 3; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fastore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fastore); | |
} | |
} | |
final public void fcmpg() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fcmpg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fcmpg); | |
} | |
} | |
final public void fcmpl() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fcmpl; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fcmpl); | |
} | |
} | |
final public void fconst_0() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fconst_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fconst_0); | |
} | |
} | |
final public void fconst_1() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fconst_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fconst_1); | |
} | |
} | |
final public void fconst_2() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fconst_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fconst_2); | |
} | |
} | |
final public void fdiv() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fdiv; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fdiv); | |
} | |
} | |
final public void fload(int iArg) { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fload); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fload); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void fload_0() { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fload_0); | |
} | |
} | |
final public void fload_1() { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fload_1); | |
} | |
} | |
final public void fload_2() { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fload_2); | |
} | |
} | |
final public void fload_3() { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fload_3); | |
} | |
} | |
final public void fmul() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fmul; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fmul); | |
} | |
} | |
final public void fneg() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fneg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fneg); | |
} | |
} | |
final public void frem() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_frem; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_frem); | |
} | |
} | |
final public void freturn() { | |
countLabels = 0; | |
stackDepth--; | |
// the stackDepth should be equal to 0 | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_freturn; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_freturn); | |
} | |
} | |
final public void fstore(int iArg) { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fstore); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fstore); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void fstore_0() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fstore_0); | |
} | |
} | |
final public void fstore_1() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fstore_1); | |
} | |
} | |
final public void fstore_2() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fstore_2); | |
} | |
} | |
final public void fstore_3() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fstore_3); | |
} | |
} | |
final public void fsub() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fsub; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_fsub); | |
} | |
} | |
/** | |
* Macro for building a class descriptor object | |
*/ | |
public void generateClassLiteralAccessForType(TypeBinding accessedType, FieldBinding syntheticFieldBinding) { | |
Label endLabel; | |
ExceptionLabel anyExceptionHandler; | |
int saveStackSize; | |
if (accessedType.isBaseType() && accessedType != NullBinding) { | |
this.getTYPE(accessedType.id); | |
return; | |
} | |
endLabel = new Label(this); | |
if (syntheticFieldBinding != null) { // non interface case | |
this.getstatic(syntheticFieldBinding); | |
this.dup(); | |
this.ifnonnull(endLabel); | |
this.pop(); | |
} | |
/* Macro for building a class descriptor object... using or not a field cache to store it into... | |
this sequence is responsible for building the actual class descriptor. | |
If the fieldCache is set, then it is supposed to be the body of a synthetic access method | |
factoring the actual descriptor creation out of the invocation site (saving space). | |
If the fieldCache is nil, then we are dumping the bytecode on the invocation site, since | |
we have no way to get a hand on the field cache to do better. */ | |
// Wrap the code in an exception handler to convert a ClassNotFoundException into a NoClassDefError | |
anyExceptionHandler = new ExceptionLabel(this, TypeBinding.NullBinding /* represents ClassNotFoundException*/); | |
this.ldc(accessedType == TypeBinding.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$ | |
this.invokeClassForName(); | |
/* We need to protect the runtime code from binary inconsistencies | |
in case the accessedType is missing, the ClassNotFoundException has to be converted | |
into a NoClassDefError(old ex message), we thus need to build an exception handler for this one. */ | |
anyExceptionHandler.placeEnd(); | |
if (syntheticFieldBinding != null) { // non interface case | |
this.dup(); | |
this.putstatic(syntheticFieldBinding); | |
} | |
this.goto_(endLabel); | |
// Generate the body of the exception handler | |
saveStackSize = stackDepth; | |
stackDepth = 1; | |
/* ClassNotFoundException on stack -- the class literal could be doing more things | |
on the stack, which means that the stack may not be empty at this point in the | |
above code gen. So we save its state and restart it from 1. */ | |
anyExceptionHandler.place(); | |
// Transform the current exception, and repush and throw a | |
// NoClassDefFoundError(ClassNotFound.getMessage()) | |
this.newNoClassDefFoundError(); | |
this.dup_x1(); | |
this.swap(); | |
// Retrieve the message from the old exception | |
this.invokeThrowableGetMessage(); | |
// Send the constructor taking a message string as an argument | |
this.invokeNoClassDefFoundErrorStringConstructor(); | |
this.athrow(); | |
endLabel.place(); | |
stackDepth = saveStackSize; | |
} | |
/** | |
* This method returns the exception handler to be able to generate the exception handler | |
* attribute. | |
*/ | |
final public int[] generateCodeAttributeForProblemMethod(String errorName, String problemMessage) { | |
/** | |
* Equivalent code: | |
* try { | |
* throw ((Error) (Class.forName(errorName).getConstructor(new Class[] {Class.forName("java.lang.String")})).newInstance(new Object[] {problemMessage})); | |
* } catch (Exception e) { | |
* throw (NullPointerException) null; | |
* } | |
*/ | |
int endPC, handlerPC; | |
ldc(errorName); | |
invokeClassForName(); | |
iconst_1(); | |
anewarrayJavaLangClass(); | |
dup(); | |
iconst_0(); | |
ldc("java.lang.String"); //$NON-NLS-1$ | |
invokeClassForName(); | |
aastore(); | |
invokeConstructorGetConstructor(); | |
iconst_1(); | |
anewarrayJavaLangObject(); | |
dup(); | |
iconst_0(); | |
ldc(problemMessage); | |
aastore(); | |
invokeObjectNewInstance(); | |
checkcastJavaLangError(); | |
athrow(); | |
endPC = handlerPC = position; | |
pop(); | |
aconst_null(); | |
athrow(); | |
return_(); | |
return new int[] {0, endPC, handlerPC}; | |
} | |
public void generateConstant(Constant constant, int implicitConversionCode) { | |
int targetTypeID = implicitConversionCode >> 4; | |
switch (targetTypeID) { | |
case T_boolean : | |
generateInlinedValue(constant.booleanValue()); | |
break; | |
case T_char : | |
generateInlinedValue(constant.charValue()); | |
break; | |
case T_byte : | |
generateInlinedValue(constant.byteValue()); | |
break; | |
case T_short : | |
generateInlinedValue(constant.shortValue()); | |
break; | |
case T_int : | |
generateInlinedValue(constant.intValue()); | |
break; | |
case T_long : | |
generateInlinedValue(constant.longValue()); | |
break; | |
case T_float : | |
generateInlinedValue(constant.floatValue()); | |
break; | |
case T_double : | |
generateInlinedValue(constant.doubleValue()); | |
break; | |
case T_String : | |
this.ldc(constant.stringValue()); | |
break; | |
default : //reference object (constant can be from T_null or T_String) | |
if (constant.typeID() == T_String) | |
ldc(constant.stringValue()); | |
else | |
aconst_null(); | |
} | |
} | |
/** | |
* @param implicitConversionCode int | |
*/ | |
public void generateImplicitConversion(int implicitConversionCode) { | |
switch (implicitConversionCode) { | |
case Float2Char : | |
this.f2i(); | |
this.i2c(); | |
break; | |
case Double2Char : | |
this.d2i(); | |
this.i2c(); | |
break; | |
case Int2Char : | |
case Short2Char : | |
case Byte2Char : | |
this.i2c(); | |
break; | |
case Long2Char : | |
this.l2i(); | |
this.i2c(); | |
break; | |
case Char2Float : | |
case Short2Float : | |
case Int2Float : | |
case Byte2Float : | |
this.i2f(); | |
break; | |
case Double2Float : | |
this.d2f(); | |
break; | |
case Long2Float : | |
this.l2f(); | |
break; | |
case Float2Byte : | |
this.f2i(); | |
this.i2b(); | |
break; | |
case Double2Byte : | |
this.d2i(); | |
this.i2b(); | |
break; | |
case Int2Byte : | |
case Short2Byte : | |
case Char2Byte : | |
this.i2b(); | |
break; | |
case Long2Byte : | |
this.l2i(); | |
this.i2b(); | |
break; | |
case Byte2Double : | |
case Char2Double : | |
case Short2Double : | |
case Int2Double : | |
this.i2d(); | |
break; | |
case Float2Double : | |
this.f2d(); | |
break; | |
case Long2Double : | |
this.l2d(); | |
break; | |
case Byte2Short : | |
case Char2Short : | |
case Int2Short : | |
this.i2s(); | |
break; | |
case Double2Short : | |
this.d2i(); | |
this.i2s(); | |
break; | |
case Long2Short : | |
this.l2i(); | |
this.i2s(); | |
break; | |
case Float2Short : | |
this.f2i(); | |
this.i2s(); | |
break; | |
case Double2Int : | |
this.d2i(); | |
break; | |
case Float2Int : | |
this.f2i(); | |
break; | |
case Long2Int : | |
this.l2i(); | |
break; | |
case Int2Long : | |
case Char2Long : | |
case Byte2Long : | |
case Short2Long : | |
this.i2l(); | |
break; | |
case Double2Long : | |
this.d2l(); | |
break; | |
case Float2Long : | |
this.f2l(); | |
} | |
} | |
public void generateInlinedValue(byte inlinedValue) { | |
switch (inlinedValue) { | |
case -1 : | |
this.iconst_m1(); | |
break; | |
case 0 : | |
this.iconst_0(); | |
break; | |
case 1 : | |
this.iconst_1(); | |
break; | |
case 2 : | |
this.iconst_2(); | |
break; | |
case 3 : | |
this.iconst_3(); | |
break; | |
case 4 : | |
this.iconst_4(); | |
break; | |
case 5 : | |
this.iconst_5(); | |
break; | |
default : | |
if ((-128 <= inlinedValue) && (inlinedValue <= 127)) { | |
this.bipush((byte) inlinedValue); | |
return; | |
} | |
} | |
} | |
public void generateInlinedValue(char inlinedValue) { | |
switch (inlinedValue) { | |
case 0 : | |
this.iconst_0(); | |
break; | |
case 1 : | |
this.iconst_1(); | |
break; | |
case 2 : | |
this.iconst_2(); | |
break; | |
case 3 : | |
this.iconst_3(); | |
break; | |
case 4 : | |
this.iconst_4(); | |
break; | |
case 5 : | |
this.iconst_5(); | |
break; | |
default : | |
if ((6 <= inlinedValue) && (inlinedValue <= 127)) { | |
this.bipush((byte) inlinedValue); | |
return; | |
} | |
if ((128 <= inlinedValue) && (inlinedValue <= 32767)) { | |
this.sipush(inlinedValue); | |
return; | |
} | |
this.ldc(inlinedValue); | |
} | |
} | |
public void generateInlinedValue(double inlinedValue) { | |
if (inlinedValue == 0.0) { | |
if (Double.doubleToLongBits(inlinedValue) != 0L) | |
this.ldc2_w(inlinedValue); | |
else | |
this.dconst_0(); | |
return; | |
} | |
if (inlinedValue == 1.0) { | |
this.dconst_1(); | |
return; | |
} | |
this.ldc2_w(inlinedValue); | |
} | |
public void generateInlinedValue(float inlinedValue) { | |
if (inlinedValue == 0.0f) { | |
if (Float.floatToIntBits(inlinedValue) != 0) | |
this.ldc(inlinedValue); | |
else | |
this.fconst_0(); | |
return; | |
} | |
if (inlinedValue == 1.0f) { | |
this.fconst_1(); | |
return; | |
} | |
if (inlinedValue == 2.0f) { | |
this.fconst_2(); | |
return; | |
} | |
this.ldc(inlinedValue); | |
} | |
public void generateInlinedValue(int inlinedValue) { | |
switch (inlinedValue) { | |
case -1 : | |
this.iconst_m1(); | |
break; | |
case 0 : | |
this.iconst_0(); | |
break; | |
case 1 : | |
this.iconst_1(); | |
break; | |
case 2 : | |
this.iconst_2(); | |
break; | |
case 3 : | |
this.iconst_3(); | |
break; | |
case 4 : | |
this.iconst_4(); | |
break; | |
case 5 : | |
this.iconst_5(); | |
break; | |
default : | |
if ((-128 <= inlinedValue) && (inlinedValue <= 127)) { | |
this.bipush((byte) inlinedValue); | |
return; | |
} | |
if ((-32768 <= inlinedValue) && (inlinedValue <= 32767)) { | |
this.sipush(inlinedValue); | |
return; | |
} | |
this.ldc(inlinedValue); | |
} | |
} | |
public void generateInlinedValue(long inlinedValue) { | |
if (inlinedValue == 0) { | |
this.lconst_0(); | |
return; | |
} | |
if (inlinedValue == 1) { | |
this.lconst_1(); | |
return; | |
} | |
this.ldc2_w(inlinedValue); | |
} | |
public void generateInlinedValue(short inlinedValue) { | |
switch (inlinedValue) { | |
case -1 : | |
this.iconst_m1(); | |
break; | |
case 0 : | |
this.iconst_0(); | |
break; | |
case 1 : | |
this.iconst_1(); | |
break; | |
case 2 : | |
this.iconst_2(); | |
break; | |
case 3 : | |
this.iconst_3(); | |
break; | |
case 4 : | |
this.iconst_4(); | |
break; | |
case 5 : | |
this.iconst_5(); | |
break; | |
default : | |
if ((-128 <= inlinedValue) && (inlinedValue <= 127)) { | |
this.bipush((byte) inlinedValue); | |
return; | |
} | |
this.sipush(inlinedValue); | |
} | |
} | |
public void generateInlinedValue(boolean inlinedValue) { | |
if (inlinedValue) | |
this.iconst_1(); | |
else | |
this.iconst_0(); | |
} | |
public void generateOuterAccess(Object[] mappingSequence, AstNode invocationSite, Scope scope) { | |
if (mappingSequence == null) | |
return; | |
if (mappingSequence == BlockScope.EmulationPathToImplicitThis) { | |
if (scope.methodScope().isConstructorCall){ | |
scope.problemReporter().errorThisSuperInStatic(invocationSite); | |
} | |
this.aload_0(); | |
return; | |
} | |
if (mappingSequence[0] instanceof FieldBinding) { | |
FieldBinding fieldBinding = (FieldBinding) mappingSequence[0]; | |
if (scope.methodScope().isConstructorCall){ | |
scope.problemReporter().errorThisSuperInStatic(invocationSite); | |
} | |
this.aload_0(); | |
this.getfield(fieldBinding); | |
} else { | |
load((LocalVariableBinding) mappingSequence[0]); | |
} | |
for (int i = 1, length = mappingSequence.length; i < length; i++) { | |
if (mappingSequence[i] instanceof FieldBinding) { | |
FieldBinding fieldBinding = (FieldBinding) mappingSequence[i]; | |
this.getfield(fieldBinding); | |
} else { | |
this.invokestatic((MethodBinding) mappingSequence[i]); | |
} | |
} | |
} | |
/** | |
* The equivalent code performs a string conversion: | |
* | |
* @param oper1 org.eclipse.jdt.internal.compiler.lookup.BlockScope | |
* @param oper1 org.eclipse.jdt.internal.compiler.ast.Expression | |
* @param oper2 org.eclipse.jdt.internal.compiler.ast.Expression | |
*/ | |
public void generateStringAppend(BlockScope blockScope, Expression oper1, Expression oper2) { | |
int pc; | |
if (oper1 == null) { | |
/* Operand is already on the stack, and maybe nil: | |
note type1 is always to java.lang.String here.*/ | |
this.newStringBuffer(); | |
this.dup_x1(); | |
this.swap(); | |
// If argument is reference type, need to transform it | |
// into a string (handles null case) | |
this.invokeStringValueOf(T_Object); | |
this.invokeStringBufferStringConstructor(); | |
} else { | |
pc = position; | |
oper1.generateOptimizedStringBufferCreation(blockScope, this, oper1.implicitConversion & 0xF); | |
this.recordPositionsFrom(pc, oper1.sourceStart); | |
} | |
pc = position; | |
oper2.generateOptimizedStringBuffer(blockScope, this, oper2.implicitConversion & 0xF); | |
this.recordPositionsFrom(pc, oper2.sourceStart); | |
this.invokeStringBufferToString(); | |
} | |
/** | |
* Code responsible to generate the suitable code to supply values for the synthetic arguments of | |
* a constructor invocation of a nested type. | |
*/ | |
public void generateSyntheticArgumentValues(BlockScope currentScope, ReferenceBinding targetType, Expression enclosingInstance, AstNode invocationSite) { | |
// perform some emulation work in case there is some and we are inside a local type only | |
ReferenceBinding[] syntheticArgumentTypes; | |
// generate the enclosing instance first | |
if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes()) != null) { | |
ReferenceBinding targetEnclosingType = targetType.isAnonymousType() ? | |
targetType.superclass().enclosingType() // supplying enclosing instance for the anonymous type's superclass | |
: targetType.enclosingType(); | |
for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) { | |
ReferenceBinding syntheticArgType = syntheticArgumentTypes[i]; | |
if (enclosingInstance != null && i == 0) { | |
if (syntheticArgType != targetEnclosingType) { | |
currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, targetType); | |
} | |
//if (currentScope.environment().options.complianceLevel >= CompilerOptions.JDK1_4){ | |
enclosingInstance.generateCode(currentScope, this, true); | |
if (syntheticArgType == targetEnclosingType){ | |
this.dup(); | |
} | |
this.invokeObjectGetClass(); // causes null check for all explicit enclosing instances | |
this.pop(); | |
//} else { | |
// enclosingInstance.generateCode(currentScope, this, syntheticArgType == targetEnclosingType); | |
//} | |
} else { | |
Object[] emulationPath = currentScope.getCompatibleEmulationPath(syntheticArgType); | |
if (emulationPath == null) { | |
currentScope.problemReporter().missingEnclosingInstanceSpecification(syntheticArgType, invocationSite); | |
} else { | |
this.generateOuterAccess(emulationPath, invocationSite, currentScope); | |
} | |
} | |
} | |
} else { // we may still have an enclosing instance to consider | |
if (enclosingInstance != null) { | |
currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, targetType); | |
//if (currentScope.environment().options.complianceLevel >= CompilerOptions.JDK1_4){ | |
enclosingInstance.generateCode(currentScope, this, true); | |
this.invokeObjectGetClass(); // causes null check for all explicit enclosing instances | |
this.pop(); | |
//} else { | |
// enclosingInstance.generateCode(currentScope, this, false); // do not want the value | |
//} | |
} | |
} | |
// generate the synthetic outer arguments then | |
SyntheticArgumentBinding syntheticArguments[]; | |
if ((syntheticArguments = targetType.syntheticOuterLocalVariables()) != null) { | |
for (int i = 0, max = syntheticArguments.length; i < max; i++) { | |
VariableBinding[] emulationPath = currentScope.getEmulationPath(syntheticArguments[i].actualOuterLocalVariable); | |
if (emulationPath == null) { | |
// could not emulate a path to a given outer local variable (internal error) | |
currentScope.problemReporter().needImplementation(); | |
} else { | |
this.generateOuterAccess(emulationPath, invocationSite, currentScope); | |
} | |
} | |
} | |
} | |
/** | |
* @param parameters org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] | |
* @param constructorBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding | |
*/ | |
public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBinding accessBinding) { | |
initializeMaxLocals(accessBinding); | |
MethodBinding constructorBinding = accessBinding.targetMethod; | |
TypeBinding[] parameters = constructorBinding.parameters; | |
int length = parameters.length; | |
int resolvedPosition = 1; | |
this.aload_0(); | |
if (constructorBinding.declaringClass.isNestedType()) { | |
NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass; | |
SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticEnclosingInstances(); | |
for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) { | |
TypeBinding type; | |
load((type = syntheticArguments[i].type), resolvedPosition); | |
if ((type == DoubleBinding) || (type == LongBinding)) | |
resolvedPosition += 2; | |
else | |
resolvedPosition++; | |
} | |
syntheticArguments = nestedType.syntheticOuterLocalVariables(); | |
for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) { | |
TypeBinding type; | |
load((type = syntheticArguments[i].type), resolvedPosition); | |
if ((type == DoubleBinding) || (type == LongBinding)) | |
resolvedPosition += 2; | |
else | |
resolvedPosition++; | |
} | |
} | |
for (int i = 0; i < length; i++) { | |
load(parameters[i], resolvedPosition); | |
if ((parameters[i] == DoubleBinding) || (parameters[i] == LongBinding)) | |
resolvedPosition += 2; | |
else | |
resolvedPosition++; | |
} | |
this.invokespecial(constructorBinding); | |
this.return_(); | |
} | |
public void generateSyntheticBodyForFieldReadAccess(SyntheticAccessMethodBinding accessBinding) { | |
initializeMaxLocals(accessBinding); | |
FieldBinding fieldBinding = accessBinding.targetReadField; | |
TypeBinding type; | |
if (fieldBinding.isStatic()) | |
this.getstatic(fieldBinding); | |
else { | |
this.aload_0(); | |
this.getfield(fieldBinding); | |
} | |
if ((type = fieldBinding.type).isBaseType()) { | |
if (type == IntBinding) | |
this.ireturn(); | |
else | |
if (type == FloatBinding) | |
this.freturn(); | |
else | |
if (type == LongBinding) | |
this.lreturn(); | |
else | |
if (type == DoubleBinding) | |
this.dreturn(); | |
else | |
this.ireturn(); | |
} else | |
this.areturn(); | |
} | |
public void generateSyntheticBodyForFieldWriteAccess(SyntheticAccessMethodBinding accessBinding) { | |
initializeMaxLocals(accessBinding); | |
FieldBinding fieldBinding = accessBinding.targetWriteField; | |
if (fieldBinding.isStatic()) { | |
load(fieldBinding.type, 0); | |
this.putstatic(fieldBinding); | |
} else { | |
this.aload_0(); | |
load(fieldBinding.type, 1); | |
this.putfield(fieldBinding); | |
} | |
this.return_(); | |
} | |
public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding accessBinding) { | |
initializeMaxLocals(accessBinding); | |
MethodBinding methodBinding = accessBinding.targetMethod; | |
TypeBinding[] parameters = methodBinding.parameters; | |
int length = parameters.length; | |
int resolvedPosition; | |
if (methodBinding.isStatic()) | |
resolvedPosition = 0; | |
else { | |
this.aload_0(); | |
resolvedPosition = 1; | |
} | |
for (int i = 0; i < length; i++) { | |
load(parameters[i], resolvedPosition); | |
if ((parameters[i] == DoubleBinding) || (parameters[i] == LongBinding)) | |
resolvedPosition += 2; | |
else | |
resolvedPosition++; | |
} | |
TypeBinding type; | |
if (methodBinding.isStatic()) | |
this.invokestatic(methodBinding); | |
else { | |
if (methodBinding.isConstructor() | |
|| methodBinding.isPrivate() | |
// qualified super "X.super.foo()" targets methods from superclass | |
|| (methodBinding.declaringClass != methodDeclaration.binding.declaringClass)){ | |
this.invokespecial(methodBinding); | |
} else { | |
if (methodBinding.declaringClass.isInterface()){ | |
this.invokeinterface(methodBinding); | |
} else { | |
this.invokevirtual(methodBinding); | |
} | |
} | |
} | |
if ((type = methodBinding.returnType).isBaseType()) | |
if (type == VoidBinding) | |
this.return_(); | |
else | |
if (type == IntBinding) | |
this.ireturn(); | |
else | |
if (type == FloatBinding) | |
this.freturn(); | |
else | |
if (type == LongBinding) | |
this.lreturn(); | |
else | |
if (type == DoubleBinding) | |
this.dreturn(); | |
else | |
this.ireturn(); | |
else | |
this.areturn(); | |
} | |
final public byte[] getContents() { | |
byte[] contents; | |
System.arraycopy(bCodeStream, 0, contents = new byte[position], 0, position); | |
return contents; | |
} | |
final public void getfield(FieldBinding fieldBinding) { | |
countLabels = 0; | |
if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) { | |
if (++stackDepth > stackMax) | |
stackMax = stackDepth; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_getfield; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_getfield); | |
} | |
writeUnsignedShort(constantPool.literalIndex(fieldBinding)); | |
} | |
final public void getstatic(FieldBinding fieldBinding) { | |
countLabels = 0; | |
if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) | |
stackDepth += 2; | |
else | |
stackDepth += 1; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_getstatic; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_getstatic); | |
} | |
writeUnsignedShort(constantPool.literalIndex(fieldBinding)); | |
} | |
public void getSystemOut() { | |
countLabels = 0; | |
if (++stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_getstatic; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_getstatic); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangSystemOut()); | |
} | |
public void getTYPE(int baseTypeID) { | |
countLabels = 0; | |
if (++stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_getstatic; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_getstatic); | |
} | |
switch (baseTypeID) { | |
// getstatic: java.lang.Byte.TYPE | |
case T_byte : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangByteTYPE()); | |
break; | |
// getstatic: java.lang.Short.TYPE | |
case T_short : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangShortTYPE()); | |
break; | |
// getstatic: java.lang.Character.TYPE | |
case T_char : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangCharacterTYPE()); | |
break; | |
// getstatic: java.lang.Integer.TYPE | |
case T_int : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangIntegerTYPE()); | |
break; | |
// getstatic: java.lang.Long.TYPE | |
case T_long : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangLongTYPE()); | |
break; | |
// getstatic: java.lang.Float.TYPE | |
case T_float : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangFloatTYPE()); | |
break; | |
// getstatic: java.lang.Double.TYPE | |
case T_double : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangDoubleTYPE()); | |
break; | |
// getstatic: java.lang.Boolean.TYPE | |
case T_boolean : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangBooleanTYPE()); | |
break; | |
// getstatic: java.lang.Void.TYPE | |
case T_void : | |
writeUnsignedShort(constantPool.literalIndexForJavaLangVoidTYPE()); | |
break; | |
} | |
} | |
/** | |
* We didn't call it goto, because there is a conflit with the goto keyword | |
*/ | |
final public void goto_(Label lbl) { | |
if (this.wideMode) { | |
this.goto_w(lbl); | |
return; | |
} | |
try { | |
lbl.inlineForwardReferencesFromLabelsTargeting(position); | |
/* | |
Possible optimization for code such as: | |
public Object foo() { | |
boolean b = true; | |
if (b) { | |
if (b) | |
return null; | |
} else { | |
if (b) { | |
return null; | |
} | |
} | |
return null; | |
} | |
The goto around the else block for the first if will | |
be unreachable, because the thenClause of the second if | |
returns. | |
See inlineForwardReferencesFromLabelsTargeting defined | |
on the Label class for the remaining part of this | |
optimization. | |
if (!lbl.isBranchTarget(position)) { | |
switch(bCodeStream[classFileOffset-1]) { | |
case OPC_return : | |
case OPC_areturn: | |
return; | |
} | |
}*/ | |
position++; | |
bCodeStream[classFileOffset++] = OPC_goto; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_goto); | |
} | |
lbl.branch(); | |
} | |
/** | |
* We didn't call it goto, because there is a conflit with the goto keyword | |
*/ | |
final public void internal_goto_(Label lbl) { | |
try { | |
lbl.inlineForwardReferencesFromLabelsTargeting(position); | |
/* | |
Possible optimization for code such as: | |
public Object foo() { | |
boolean b = true; | |
if (b) { | |
if (b) | |
return null; | |
} else { | |
if (b) { | |
return null; | |
} | |
} | |
return null; | |
} | |
The goto around the else block for the first if will | |
be unreachable, because the thenClause of the second if | |
returns. | |
See inlineForwardReferencesFromLabelsTargeting defined | |
on the Label class for the remaining part of this | |
optimization. | |
if (!lbl.isBranchTarget(position)) { | |
switch(bCodeStream[classFileOffset-1]) { | |
case OPC_return : | |
case OPC_areturn: | |
return; | |
} | |
}*/ | |
position++; | |
bCodeStream[classFileOffset++] = OPC_goto; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_goto); | |
} | |
lbl.branch(); | |
} | |
final public void goto_w(Label lbl) { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_goto_w; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_goto_w); | |
} | |
lbl.branchWide(); | |
} | |
final public void i2b() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2b; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_i2b); | |
} | |
} | |
final public void i2c() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2c; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_i2c); | |
} | |
} | |
final public void i2d() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2d; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_i2d); | |
} | |
} | |
final public void i2f() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2f; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_i2f); | |
} | |
} | |
final public void i2l() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2l; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_i2l); | |
} | |
} | |
final public void i2s() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2s; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_i2s); | |
} | |
} | |
final public void iadd() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iadd; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iadd); | |
} | |
} | |
final public void iaload() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iaload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iaload); | |
} | |
} | |
final public void iand() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iand; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iand); | |
} | |
} | |
final public void iastore() { | |
countLabels = 0; | |
stackDepth -= 3; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iastore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iastore); | |
} | |
} | |
final public void iconst_0() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iconst_0); | |
} | |
} | |
final public void iconst_1() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iconst_1); | |
} | |
} | |
final public void iconst_2() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iconst_2); | |
} | |
} | |
final public void iconst_3() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iconst_3); | |
} | |
} | |
final public void iconst_4() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_4; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iconst_4); | |
} | |
} | |
final public void iconst_5() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_5; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iconst_5); | |
} | |
} | |
final public void iconst_m1() { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_m1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iconst_m1); | |
} | |
} | |
final public void idiv() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_idiv; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_idiv); | |
} | |
} | |
final public void if_acmpeq(Label lbl) { | |
countLabels = 0; | |
stackDepth-=2; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_if_acmpeq, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_acmpeq; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_if_acmpeq); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void if_acmpne(Label lbl) { | |
countLabels = 0; | |
stackDepth-=2; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_if_acmpne, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_acmpne; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_if_acmpne); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void if_icmpeq(Label lbl) { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_if_icmpeq, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmpeq; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_if_icmpeq); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void if_icmpge(Label lbl) { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_if_icmpge, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmpge; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_if_icmpge); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void if_icmpgt(Label lbl) { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_if_icmpgt, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmpgt; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_if_icmpgt); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void if_icmple(Label lbl) { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_if_icmple, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmple; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_if_icmple); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void if_icmplt(Label lbl) { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_if_icmplt, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmplt; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_if_icmplt); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void if_icmpne(Label lbl) { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_if_icmpne, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmpne; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_if_icmpne); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void ifeq(Label lbl) { | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_ifeq, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifeq; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ifeq); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void ifge(Label lbl) { | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_ifge, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifge; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ifge); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void ifgt(Label lbl) { | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_ifgt, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifgt; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ifgt); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void ifle(Label lbl) { | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_ifle, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifle; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ifle); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void iflt(Label lbl) { | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_iflt, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iflt; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iflt); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void ifne(Label lbl) { | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_ifne, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifne; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ifne); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void ifnonnull(Label lbl) { | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_ifnonnull, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifnonnull; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ifnonnull); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void ifnull(Label lbl) { | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideConditionalBranch(OPC_ifnull, lbl); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifnull; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ifnull); | |
} | |
lbl.branch(); | |
} | |
} | |
final public void iinc(int index, int value) { | |
countLabels = 0; | |
if ((index > 255) || (value < -128 || value > 127)) { // have to widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iinc; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iinc); | |
} | |
writeUnsignedShort(index); | |
writeSignedShort(value); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iinc; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iinc); | |
} | |
writeUnsignedByte(index); | |
writeSignedByte(value); | |
} | |
} | |
final public void iload(int iArg) { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iload); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iload); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void iload_0() { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 0) { | |
maxLocals = 1; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iload_0); | |
} | |
} | |
final public void iload_1() { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iload_1); | |
} | |
} | |
final public void iload_2() { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iload_2); | |
} | |
} | |
final public void iload_3() { | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iload_3); | |
} | |
} | |
final public void imul() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_imul; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_imul); | |
} | |
} | |
public void incrementTemp(LocalVariableBinding localBinding, int value) { | |
if (value == (short) value) { | |
this.iinc(localBinding.resolvedPosition, value); | |
return; | |
} | |
load(localBinding); | |
this.ldc(value); | |
this.iadd(); | |
store(localBinding, false); | |
} | |
public void incrStackSize(int offset) { | |
if ((stackDepth += offset) > stackMax) | |
stackMax = stackDepth; | |
} | |
public int indexOfSameLineEntrySincePC(int pc, int line) { | |
for (int index = pc, max = pcToSourceMapSize; index < max; index+=2) { | |
if (pcToSourceMap[index+1] == line) | |
return index; | |
} | |
return -1; | |
} | |
final public void ineg() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ineg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ineg); | |
} | |
} | |
public void init(ClassFile classFile) { | |
this.classFile = classFile; | |
this.constantPool = classFile.constantPool; | |
this.bCodeStream = classFile.contents; | |
this.classFileOffset = classFile.contentsOffset; | |
this.startingClassFileOffset = this.classFileOffset; | |
pcToSourceMapSize = 0; | |
lastEntryPC = 0; | |
int length = visibleLocals.length; | |
if (noVisibleLocals.length < length) { | |
noVisibleLocals = new LocalVariableBinding[length]; | |
} | |
System.arraycopy(noVisibleLocals, 0, visibleLocals, 0, length); | |
visibleLocalsCount = 0; | |
length = locals.length; | |
if (noLocals.length < length) { | |
noLocals = new LocalVariableBinding[length]; | |
} | |
System.arraycopy(noLocals, 0, locals, 0, length); | |
allLocalsCounter = 0; | |
length = exceptionHandlers.length; | |
if (noExceptionHandlers.length < length) { | |
noExceptionHandlers = new ExceptionLabel[length]; | |
} | |
System.arraycopy(noExceptionHandlers, 0, exceptionHandlers, 0, length); | |
exceptionHandlersNumber = 0; | |
length = labels.length; | |
if (noLabels.length < length) { | |
noLabels = new Label[length]; | |
} | |
System.arraycopy(noLabels, 0, labels, 0, length); | |
countLabels = 0; | |
stackMax = 0; | |
stackDepth = 0; | |
maxLocals = 0; | |
position = 0; | |
} | |
/** | |
* @param methodDeclaration org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration | |
* @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile | |
*/ | |
public void initializeMaxLocals(MethodBinding methodBinding) { | |
maxLocals = (methodBinding == null || methodBinding.isStatic()) ? 0 : 1; | |
// take into account the synthetic parameters | |
if (methodBinding != null) { | |
if (methodBinding.isConstructor() && methodBinding.declaringClass.isNestedType()) { | |
ReferenceBinding enclosingInstanceTypes[]; | |
if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) { | |
for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) { | |
maxLocals++; // an enclosingInstanceType can only be a reference binding. It cannot be | |
// LongBinding or DoubleBinding | |
} | |
} | |
SyntheticArgumentBinding syntheticArguments[]; | |
if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) { | |
for (int i = 0, max = syntheticArguments.length; i < max; i++) { | |
TypeBinding argType; | |
if (((argType = syntheticArguments[i].type) == LongBinding) || (argType == DoubleBinding)) { | |
maxLocals += 2; | |
} else { | |
maxLocals++; | |
} | |
} | |
} | |
} | |
TypeBinding[] arguments; | |
if ((arguments = methodBinding.parameters) != null) { | |
for (int i = 0, max = arguments.length; i < max; i++) { | |
TypeBinding argType; | |
if (((argType = arguments[i]) == LongBinding) || (argType == DoubleBinding)) { | |
maxLocals += 2; | |
} else { | |
maxLocals++; | |
} | |
} | |
} | |
} | |
} | |
/** | |
* This methods searches for an existing entry inside the pcToSourceMap table with a pc equals to @pc. | |
* If there is an existing entry it returns -1 (no insertion required). | |
* Otherwise it returns the index where the entry for the pc has to be inserted. | |
* This is based on the fact that the pcToSourceMap table is sorted according to the pc. | |
* | |
* @param int pc | |
* @return int | |
*/ | |
public static int insertionIndex(int[] pcToSourceMap, int length, int pc) { | |
int g = 0; | |
int d = length - 2; | |
int m = 0; | |
while (g <= d) { | |
m = (g + d) / 2; | |
// we search only on even indexes | |
if ((m % 2) != 0) | |
m--; | |
int currentPC = pcToSourceMap[m]; | |
if (pc < currentPC) { | |
d = m - 2; | |
} else | |
if (pc > currentPC) { | |
g = m + 2; | |
} else { | |
return -1; | |
} | |
} | |
if (pc < pcToSourceMap[m]) | |
return m; | |
return m + 2; | |
} | |
/** | |
* We didn't call it instanceof because there is a conflit with the | |
* instanceof keyword | |
*/ | |
final public void instance_of(TypeBinding typeBinding) { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_instanceof; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_instanceof); | |
} | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
} | |
public void invokeClassForName() { | |
// invokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokestatic; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokestatic); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangClassForName()); | |
} | |
public void invokeJavaLangClassDesiredAssertionStatus() { | |
// invokevirtual: java.lang.Class.desiredAssertionStatus()Z; | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangClassDesiredAssertionStatus()); | |
} | |
public void invokeConstructorGetConstructor() { | |
// invokevirtual: java.lang.Class.getConstructor(java.lang.Class[])Ljava.lang.reflect.Constructor; | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangClassGetConstructor()); | |
} | |
final public void invokeinterface(MethodBinding methodBinding) { | |
// initialized to 1 to take into account this immediately | |
countLabels = 0; | |
int argCount = 1; | |
int id; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokeinterface; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokeinterface); | |
} | |
writeUnsignedShort(constantPool.literalIndex(methodBinding)); | |
for (int i = methodBinding.parameters.length - 1; i >= 0; i--) | |
if (((id = methodBinding.parameters[i].id) == T_double) || (id == T_long)) | |
argCount += 2; | |
else | |
argCount += 1; | |
writeUnsignedByte(argCount); | |
// Generate a 0 into the byte array. Like the array is already fill with 0, we just need to increment | |
// the number of bytes. | |
position++; | |
classFileOffset++; | |
if (((id = methodBinding.returnType.id) == T_double) || (id == T_long)) | |
stackDepth += (2 - argCount); | |
else | |
if (id == T_void) | |
stackDepth -= argCount; | |
else | |
stackDepth += (1 - argCount); | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
} | |
public void invokeJavaLangErrorConstructor() { | |
// invokespecial: java.lang.Error<init>(Ljava.lang.String;)V | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokespecial); | |
} | |
stackDepth -= 2; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangErrorConstructor()); | |
} | |
public void invokeNoClassDefFoundErrorStringConstructor() { | |
// invokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokespecial); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundErrorStringConstructor()); | |
stackDepth -= 2; | |
} | |
public void invokeObjectNewInstance() { | |
// invokevirtual: java.lang.reflect.Constructor.newInstance(java.lang.Object[])Ljava.lang.Object; | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangReflectConstructorNewInstance()); | |
} | |
public void invokeObjectGetClass() { | |
// invokevirtual: java.lang.Object.getClass()Ljava.lang.Class; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangObjectGetClass()); | |
} | |
final public void invokespecial(MethodBinding methodBinding) { | |
// initialized to 1 to take into account this immediately | |
countLabels = 0; | |
int argCount = 1; | |
int id; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokespecial); | |
} | |
writeUnsignedShort(constantPool.literalIndex(methodBinding)); | |
if (methodBinding.isConstructor() && methodBinding.declaringClass.isNestedType()) { | |
// enclosing instances | |
TypeBinding[] syntheticArgumentTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes(); | |
if (syntheticArgumentTypes != null) { | |
for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) { | |
if (((id = syntheticArgumentTypes[i].id) == T_double) || (id == T_long)) { | |
argCount += 2; | |
} else { | |
argCount++; | |
} | |
} | |
} | |
// outer local variables | |
SyntheticArgumentBinding[] syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables(); | |
if (syntheticArguments != null) { | |
for (int i = 0, max = syntheticArguments.length; i < max; i++) { | |
if (((id = syntheticArguments[i].type.id) == T_double) || (id == T_long)) { | |
argCount += 2; | |
} else { | |
argCount++; | |
} | |
} | |
} | |
} | |
for (int i = methodBinding.parameters.length - 1; i >= 0; i--) | |
if (((id = methodBinding.parameters[i].id) == T_double) || (id == T_long)) | |
argCount += 2; | |
else | |
argCount++; | |
if (((id = methodBinding.returnType.id) == T_double) || (id == T_long)) | |
stackDepth += (2 - argCount); | |
else | |
if (id == T_void) | |
stackDepth -= argCount; | |
else | |
stackDepth += (1 - argCount); | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
} | |
final public void invokestatic(MethodBinding methodBinding) { | |
// initialized to 0 to take into account that there is no this for | |
// a static method | |
countLabels = 0; | |
int argCount = 0; | |
int id; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokestatic; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokestatic); | |
} | |
writeUnsignedShort(constantPool.literalIndex(methodBinding)); | |
for (int i = methodBinding.parameters.length - 1; i >= 0; i--) | |
if (((id = methodBinding.parameters[i].id) == T_double) || (id == T_long)) | |
argCount += 2; | |
else | |
argCount += 1; | |
if (((id = methodBinding.returnType.id) == T_double) || (id == T_long)) | |
stackDepth += (2 - argCount); | |
else | |
if (id == T_void) | |
stackDepth -= argCount; | |
else | |
stackDepth += (1 - argCount); | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
} | |
/** | |
* The equivalent code performs a string conversion of the TOS | |
* @param typeID <CODE>int</CODE> | |
*/ | |
public void invokeStringBufferAppendForType(int typeID) { | |
countLabels = 0; | |
int usedTypeID; | |
if (typeID == T_null) | |
usedTypeID = T_String; | |
else | |
usedTypeID = typeID; | |
// invokevirtual | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferAppend(typeID)); | |
if ((usedTypeID == T_long) || (usedTypeID == T_double)) | |
stackDepth -= 2; | |
else | |
stackDepth--; | |
} | |
public void invokeJavaLangAssertionErrorConstructor(int typeBindingID) { | |
// invokespecial: java.lang.AssertionError.<init>(typeBindingID)V | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokespecial); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorConstructor(typeBindingID)); | |
stackDepth -= 2; | |
} | |
public void invokeJavaLangAssertionErrorDefaultConstructor() { | |
// invokespecial: java.lang.AssertionError.<init>()V | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokespecial); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorDefaultConstructor()); | |
stackDepth --; | |
} | |
public void invokeStringBufferDefaultConstructor() { | |
// invokespecial: java.lang.StringBuffer.<init>()V | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokespecial); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferDefaultConstructor()); | |
stackDepth--; | |
} | |
public void invokeStringBufferStringConstructor() { | |
// invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokespecial); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferConstructor()); | |
stackDepth -= 2; | |
} | |
public void invokeStringBufferToString() { | |
// invokevirtual: StringBuffer.toString()Ljava.lang.String; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferToString()); | |
} | |
public void invokeStringIntern() { | |
// invokevirtual: java.lang.String.intern() | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringIntern()); | |
} | |
public void invokeStringValueOf(int typeID) { | |
// invokestatic: java.lang.String.valueOf(argumentType) | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokestatic; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokestatic); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringValueOf(typeID)); | |
} | |
public void invokeSystemExit() { | |
// invokestatic: java.lang.System.exit(I) | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokestatic; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokestatic); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangSystemExitInt()); | |
stackDepth--; // int argument | |
} | |
public void invokeThrowableGetMessage() { | |
// invokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String; | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangThrowableGetMessage()); | |
} | |
final public void invokevirtual(MethodBinding methodBinding) { | |
// initialized to 1 to take into account this immediately | |
countLabels = 0; | |
int argCount = 1; | |
int id; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_invokevirtual); | |
} | |
writeUnsignedShort(constantPool.literalIndex(methodBinding)); | |
for (int i = methodBinding.parameters.length - 1; i >= 0; i--) | |
if (((id = methodBinding.parameters[i].id) == T_double) || (id == T_long)) | |
argCount += 2; | |
else | |
argCount++; | |
if (((id = methodBinding.returnType.id) == T_double) || (id == T_long)) | |
stackDepth += (2 - argCount); | |
else | |
if (id == T_void) | |
stackDepth -= argCount; | |
else | |
stackDepth += (1 - argCount); | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
} | |
final public void ior() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ior; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ior); | |
} | |
} | |
final public void irem() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_irem; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_irem); | |
} | |
} | |
final public void ireturn() { | |
countLabels = 0; | |
stackDepth--; | |
// the stackDepth should be equal to 0 | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ireturn; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ireturn); | |
} | |
} | |
public boolean isDefinitelyAssigned(Scope scope, int initStateIndex, LocalVariableBinding local) { | |
// Dependant of UnconditionalFlowInfo.isDefinitelyAssigned(..) | |
if (initStateIndex == -1) | |
return false; | |
if (local.isArgument) { | |
return true; | |
} | |
int position = local.id + maxFieldCount; | |
MethodScope methodScope = scope.methodScope(); | |
// id is zero-based | |
if (position < UnconditionalFlowInfo.BitCacheSize) { | |
return (methodScope.definiteInits[initStateIndex] & (1L << position)) != 0; // use bits | |
} | |
// use extra vector | |
long[] extraInits = methodScope.extraDefiniteInits[initStateIndex]; | |
if (extraInits == null) | |
return false; // if vector not yet allocated, then not initialized | |
int vectorIndex; | |
if ((vectorIndex = (position / UnconditionalFlowInfo.BitCacheSize) - 1) >= extraInits.length) | |
return false; // if not enough room in vector, then not initialized | |
return ((extraInits[vectorIndex]) & (1L << (position % UnconditionalFlowInfo.BitCacheSize))) != 0; | |
} | |
final public void ishl() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ishl; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ishl); | |
} | |
} | |
final public void ishr() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ishr; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ishr); | |
} | |
} | |
final public void istore(int iArg) { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_istore); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_istore); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void istore_0() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_istore_0); | |
} | |
} | |
final public void istore_1() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_istore_1); | |
} | |
} | |
final public void istore_2() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_istore_2); | |
} | |
} | |
final public void istore_3() { | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_istore_3); | |
} | |
} | |
final public void isub() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_isub; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_isub); | |
} | |
} | |
final public void iushr() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iushr; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_iushr); | |
} | |
} | |
final public void ixor() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ixor; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ixor); | |
} | |
} | |
final public void jsr(Label lbl) { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_jsr; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_jsr); | |
} | |
lbl.branch(); | |
} | |
final public void jsr_w(Label lbl) { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_jsr_w; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_jsr_w); | |
} | |
lbl.branchWide(); | |
} | |
final public void l2d() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_l2d; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_l2d); | |
} | |
} | |
final public void l2f() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_l2f; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_l2f); | |
} | |
} | |
final public void l2i() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_l2i; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_l2i); | |
} | |
} | |
final public void ladd() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ladd; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ladd); | |
} | |
} | |
final public void laload() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_laload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_laload); | |
} | |
} | |
final public void land() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_land; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_land); | |
} | |
} | |
final public void lastore() { | |
countLabels = 0; | |
stackDepth -= 4; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lastore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lastore); | |
} | |
} | |
final public void lcmp() { | |
countLabels = 0; | |
stackDepth -= 3; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lcmp; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lcmp); | |
} | |
} | |
final public void lconst_0() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lconst_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lconst_0); | |
} | |
} | |
final public void lconst_1() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lconst_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lconst_1); | |
} | |
} | |
final public void ldc(float constant) { | |
countLabels = 0; | |
int index = constantPool.literalIndex(constant); | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (index > 255) { | |
// Generate a ldc_w | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc_w); | |
} | |
writeUnsignedShort(index); | |
} else { | |
// Generate a ldc | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc); | |
} | |
writeUnsignedByte(index); | |
} | |
} | |
final public void ldc(int constant) { | |
countLabels = 0; | |
int index = constantPool.literalIndex(constant); | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (index > 255) { | |
// Generate a ldc_w | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc_w); | |
} | |
writeUnsignedShort(index); | |
} else { | |
// Generate a ldc | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc); | |
} | |
writeUnsignedByte(index); | |
} | |
} | |
final public void ldc(String constant) { | |
countLabels = 0; | |
int currentConstantPoolIndex = constantPool.currentIndex; | |
int currentConstantPoolOffset = constantPool.currentOffset; | |
int currentCodeStreamPosition = position; | |
int index = constantPool.literalIndexForLdc(constant.toCharArray()); | |
if (index > 0) { | |
// the string already exists inside the constant pool | |
// we reuse the same index | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (index > 255) { | |
// Generate a ldc_w | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc_w); | |
} | |
writeUnsignedShort(index); | |
} else { | |
// Generate a ldc | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc); | |
} | |
writeUnsignedByte(index); | |
} | |
} else { | |
// the string is too big to be utf8-encoded in one pass. | |
// we have to split it into different pieces. | |
// first we clean all side-effects due to the code above | |
// this case is very rare, so we can afford to lose time to handle it | |
char[] constantChars = constant.toCharArray(); | |
position = currentCodeStreamPosition; | |
constantPool.currentIndex = currentConstantPoolIndex; | |
constantPool.currentOffset = currentConstantPoolOffset; | |
constantPool.stringCache.remove(constantChars); | |
constantPool.UTF8Cache.remove(constantChars); | |
int i = 0; | |
int length = 0; | |
int constantLength = constant.length(); | |
byte[] utf8encoding = new byte[Math.min(constantLength + 100, 65535)]; | |
int utf8encodingLength = 0; | |
while ((length < 65532) && (i < constantLength)) { | |
char current = constantChars[i]; | |
// we resize the byte array immediately if necessary | |
if (length + 3 > (utf8encodingLength = utf8encoding.length)) { | |
System.arraycopy(utf8encoding, 0, (utf8encoding = new byte[Math.min(utf8encodingLength + 100, 65535)]), 0, length); | |
} | |
if ((current >= 0x0001) && (current <= 0x007F)) { | |
// we only need one byte: ASCII table | |
utf8encoding[length++] = (byte) current; | |
} else { | |
if (current > 0x07FF) { | |
// we need 3 bytes | |
utf8encoding[length++] = (byte) (0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000 | |
utf8encoding[length++] = (byte) (0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000 | |
utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 | |
} else { | |
// we can be 0 or between 0x0080 and 0x07FF | |
// In that case we only need 2 bytes | |
utf8encoding[length++] = (byte) (0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000 | |
utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 | |
} | |
} | |
i++; | |
} | |
// check if all the string is encoded (PR 1PR2DWJ) | |
// the string is too big to be encoded in one pass | |
newStringBuffer(); | |
dup(); | |
// write the first part | |
char[] subChars = new char[i]; | |
System.arraycopy(constantChars, 0, subChars, 0, i); | |
System.arraycopy(utf8encoding, 0, (utf8encoding = new byte[length]), 0, length); | |
index = constantPool.literalIndex(subChars, utf8encoding); | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (index > 255) { | |
// Generate a ldc_w | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc_w); | |
} | |
writeUnsignedShort(index); | |
} else { | |
// Generate a ldc | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc); | |
} | |
writeUnsignedByte(index); | |
} | |
// write the remaining part | |
invokeStringBufferStringConstructor(); | |
while (i < constantLength) { | |
length = 0; | |
utf8encoding = new byte[Math.min(constantLength - i + 100, 65535)]; | |
int startIndex = i; | |
while ((length < 65532) && (i < constantLength)) { | |
char current = constantChars[i]; | |
// we resize the byte array immediately if necessary | |
if (constantLength + 2 > (utf8encodingLength = utf8encoding.length)) { | |
System.arraycopy(utf8encoding, 0, (utf8encoding = new byte[Math.min(utf8encodingLength + 100, 65535)]), 0, length); | |
} | |
if ((current >= 0x0001) && (current <= 0x007F)) { | |
// we only need one byte: ASCII table | |
utf8encoding[length++] = (byte) current; | |
} else { | |
if (current > 0x07FF) { | |
// we need 3 bytes | |
utf8encoding[length++] = (byte) (0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000 | |
utf8encoding[length++] = (byte) (0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000 | |
utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 | |
} else { | |
// we can be 0 or between 0x0080 and 0x07FF | |
// In that case we only need 2 bytes | |
utf8encoding[length++] = (byte) (0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000 | |
utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000 | |
} | |
} | |
i++; | |
} | |
// the next part is done | |
subChars = new char[i - startIndex]; | |
System.arraycopy(constantChars, startIndex, subChars, 0, i - startIndex); | |
System.arraycopy(utf8encoding, 0, (utf8encoding = new byte[length]), 0, length); | |
index = constantPool.literalIndex(subChars, utf8encoding); | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (index > 255) { | |
// Generate a ldc_w | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc_w); | |
} | |
writeUnsignedShort(index); | |
} else { | |
// Generate a ldc | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc); | |
} | |
writeUnsignedByte(index); | |
} | |
// now on the stack it should be a StringBuffer and a string. | |
invokeStringBufferAppendForType(T_String); | |
} | |
invokeStringBufferToString(); | |
invokeStringIntern(); | |
} | |
} | |
final public void ldc2_w(double constant) { | |
countLabels = 0; | |
int index = constantPool.literalIndex(constant); | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
// Generate a ldc2_w | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc2_w; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc2_w); | |
} | |
writeUnsignedShort(index); | |
} | |
final public void ldc2_w(long constant) { | |
countLabels = 0; | |
int index = constantPool.literalIndex(constant); | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
// Generate a ldc2_w | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc2_w; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldc2_w); | |
} | |
writeUnsignedShort(index); | |
} | |
final public void ldiv() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldiv; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ldiv); | |
} | |
} | |
final public void lload(int iArg) { | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals <= iArg + 1) { | |
maxLocals = iArg + 2; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lload); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lload); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void lload_0() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals < 2) { | |
maxLocals = 2; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lload_0); | |
} | |
} | |
final public void lload_1() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals < 3) { | |
maxLocals = 3; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lload_1); | |
} | |
} | |
final public void lload_2() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals < 4) { | |
maxLocals = 4; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lload_2); | |
} | |
} | |
final public void lload_3() { | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals < 5) { | |
maxLocals = 5; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lload_3); | |
} | |
} | |
final public void lmul() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lmul; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lmul); | |
} | |
} | |
final public void lneg() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lneg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lneg); | |
} | |
} | |
public final void load(LocalVariableBinding localBinding) { | |
countLabels = 0; | |
TypeBinding typeBinding = localBinding.type; | |
int resolvedPosition = localBinding.resolvedPosition; | |
// Using dedicated int bytecode | |
if (typeBinding == IntBinding) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.iload_0(); | |
break; | |
case 1 : | |
this.iload_1(); | |
break; | |
case 2 : | |
this.iload_2(); | |
break; | |
case 3 : | |
this.iload_3(); | |
break; | |
default : | |
this.iload(resolvedPosition); | |
} | |
return; | |
} | |
// Using dedicated float bytecode | |
if (typeBinding == FloatBinding) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.fload_0(); | |
break; | |
case 1 : | |
this.fload_1(); | |
break; | |
case 2 : | |
this.fload_2(); | |
break; | |
case 3 : | |
this.fload_3(); | |
break; | |
default : | |
this.fload(resolvedPosition); | |
} | |
return; | |
} | |
// Using dedicated long bytecode | |
if (typeBinding == LongBinding) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.lload_0(); | |
break; | |
case 1 : | |
this.lload_1(); | |
break; | |
case 2 : | |
this.lload_2(); | |
break; | |
case 3 : | |
this.lload_3(); | |
break; | |
default : | |
this.lload(resolvedPosition); | |
} | |
return; | |
} | |
// Using dedicated double bytecode | |
if (typeBinding == DoubleBinding) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.dload_0(); | |
break; | |
case 1 : | |
this.dload_1(); | |
break; | |
case 2 : | |
this.dload_2(); | |
break; | |
case 3 : | |
this.dload_3(); | |
break; | |
default : | |
this.dload(resolvedPosition); | |
} | |
return; | |
} | |
// boolean, byte, char and short are handled as int | |
if ((typeBinding == ByteBinding) || (typeBinding == CharBinding) || (typeBinding == BooleanBinding) || (typeBinding == ShortBinding)) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.iload_0(); | |
break; | |
case 1 : | |
this.iload_1(); | |
break; | |
case 2 : | |
this.iload_2(); | |
break; | |
case 3 : | |
this.iload_3(); | |
break; | |
default : | |
this.iload(resolvedPosition); | |
} | |
return; | |
} | |
// Reference object | |
switch (resolvedPosition) { | |
case 0 : | |
this.aload_0(); | |
break; | |
case 1 : | |
this.aload_1(); | |
break; | |
case 2 : | |
this.aload_2(); | |
break; | |
case 3 : | |
this.aload_3(); | |
break; | |
default : | |
this.aload(resolvedPosition); | |
} | |
} | |
public final void load(TypeBinding typeBinding, int resolvedPosition) { | |
countLabels = 0; | |
// Using dedicated int bytecode | |
if (typeBinding == IntBinding) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.iload_0(); | |
break; | |
case 1 : | |
this.iload_1(); | |
break; | |
case 2 : | |
this.iload_2(); | |
break; | |
case 3 : | |
this.iload_3(); | |
break; | |
default : | |
this.iload(resolvedPosition); | |
} | |
return; | |
} | |
// Using dedicated float bytecode | |
if (typeBinding == FloatBinding) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.fload_0(); | |
break; | |
case 1 : | |
this.fload_1(); | |
break; | |
case 2 : | |
this.fload_2(); | |
break; | |
case 3 : | |
this.fload_3(); | |
break; | |
default : | |
this.fload(resolvedPosition); | |
} | |
return; | |
} | |
// Using dedicated long bytecode | |
if (typeBinding == LongBinding) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.lload_0(); | |
break; | |
case 1 : | |
this.lload_1(); | |
break; | |
case 2 : | |
this.lload_2(); | |
break; | |
case 3 : | |
this.lload_3(); | |
break; | |
default : | |
this.lload(resolvedPosition); | |
} | |
return; | |
} | |
// Using dedicated double bytecode | |
if (typeBinding == DoubleBinding) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.dload_0(); | |
break; | |
case 1 : | |
this.dload_1(); | |
break; | |
case 2 : | |
this.dload_2(); | |
break; | |
case 3 : | |
this.dload_3(); | |
break; | |
default : | |
this.dload(resolvedPosition); | |
} | |
return; | |
} | |
// boolean, byte, char and short are handled as int | |
if ((typeBinding == ByteBinding) || (typeBinding == CharBinding) || (typeBinding == BooleanBinding) || (typeBinding == ShortBinding)) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.iload_0(); | |
break; | |
case 1 : | |
this.iload_1(); | |
break; | |
case 2 : | |
this.iload_2(); | |
break; | |
case 3 : | |
this.iload_3(); | |
break; | |
default : | |
this.iload(resolvedPosition); | |
} | |
return; | |
} | |
// Reference object | |
switch (resolvedPosition) { | |
case 0 : | |
this.aload_0(); | |
break; | |
case 1 : | |
this.aload_1(); | |
break; | |
case 2 : | |
this.aload_2(); | |
break; | |
case 3 : | |
this.aload_3(); | |
break; | |
default : | |
this.aload(resolvedPosition); | |
} | |
} | |
public final void loadInt(int resolvedPosition) { | |
// Using dedicated int bytecode | |
switch (resolvedPosition) { | |
case 0 : | |
this.iload_0(); | |
break; | |
case 1 : | |
this.iload_1(); | |
break; | |
case 2 : | |
this.iload_2(); | |
break; | |
case 3 : | |
this.iload_3(); | |
break; | |
default : | |
this.iload(resolvedPosition); | |
} | |
} | |
public final void loadObject(int resolvedPosition) { | |
switch (resolvedPosition) { | |
case 0 : | |
this.aload_0(); | |
break; | |
case 1 : | |
this.aload_1(); | |
break; | |
case 2 : | |
this.aload_2(); | |
break; | |
case 3 : | |
this.aload_3(); | |
break; | |
default : | |
this.aload(resolvedPosition); | |
} | |
} | |
final public void lookupswitch(CaseLabel defaultLabel, int[] keys, int[] sortedIndexes, CaseLabel[] casesLabel) { | |
countLabels = 0; | |
stackDepth--; | |
int length = keys.length; | |
int pos = position; | |
defaultLabel.placeInstruction(); | |
for (int i = 0; i < length; i++) { | |
casesLabel[i].placeInstruction(); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lookupswitch; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lookupswitch); | |
} | |
for (int i = (3 - (pos % 4)); i > 0; i--) { | |
position++; // Padding | |
classFileOffset++; | |
} | |
defaultLabel.branch(); | |
writeSignedWord(length); | |
for (int i = 0; i < length; i++) { | |
writeSignedWord(keys[sortedIndexes[i]]); | |
casesLabel[sortedIndexes[i]].branch(); | |
} | |
} | |
final public void lor() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lor; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lor); | |
} | |
} | |
final public void lrem() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lrem; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lrem); | |
} | |
} | |
final public void lreturn() { | |
countLabels = 0; | |
stackDepth -= 2; | |
// the stackDepth should be equal to 0 | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lreturn; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lreturn); | |
} | |
} | |
final public void lshl() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lshl; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lshl); | |
} | |
} | |
final public void lshr() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lshr; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lshr); | |
} | |
} | |
final public void lstore(int iArg) { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals <= iArg + 1) { | |
maxLocals = iArg + 2; | |
} | |
if (iArg > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lstore); | |
} | |
writeUnsignedShort(iArg); | |
} else { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lstore); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) iArg); | |
} | |
} | |
} | |
final public void lstore_0() { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 2) { | |
maxLocals = 2; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore_0; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lstore_0); | |
} | |
} | |
final public void lstore_1() { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 3) { | |
maxLocals = 3; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore_1; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lstore_1); | |
} | |
} | |
final public void lstore_2() { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 4) { | |
maxLocals = 4; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore_2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lstore_2); | |
} | |
} | |
final public void lstore_3() { | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 5) { | |
maxLocals = 5; | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore_3; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lstore_3); | |
} | |
} | |
final public void lsub() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lsub; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lsub); | |
} | |
} | |
final public void lushr() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lushr; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lushr); | |
} | |
} | |
final public void lxor() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lxor; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_lxor); | |
} | |
} | |
final public void monitorenter() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_monitorenter; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_monitorenter); | |
} | |
} | |
final public void monitorexit() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_monitorexit; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_monitorexit); | |
} | |
} | |
final public void multianewarray(TypeBinding typeBinding, int dimensions) { | |
countLabels = 0; | |
stackDepth += (1 - dimensions); | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_multianewarray; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_multianewarray); | |
} | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
writeUnsignedByte(dimensions); | |
} | |
public static void needImplementation() { | |
} | |
/** | |
* We didn't call it new, because there is a conflit with the new keyword | |
*/ | |
final public void new_(TypeBinding typeBinding) { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_new); | |
} | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
} | |
final public void newarray(int array_Type) { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_newarray; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_newarray); | |
} | |
writeUnsignedByte(array_Type); | |
} | |
public void newArray(Scope scope, ArrayBinding arrayBinding) { | |
TypeBinding component = arrayBinding.elementsType(scope); | |
switch (component.id) { | |
case T_int : | |
this.newarray(10); | |
break; | |
case T_byte : | |
this.newarray(8); | |
break; | |
case T_boolean : | |
this.newarray(4); | |
break; | |
case T_short : | |
this.newarray(9); | |
break; | |
case T_char : | |
this.newarray(5); | |
break; | |
case T_long : | |
this.newarray(11); | |
break; | |
case T_float : | |
this.newarray(6); | |
break; | |
case T_double : | |
this.newarray(7); | |
break; | |
default : | |
this.anewarray(component); | |
} | |
} | |
public void newJavaLangError() { | |
// new: java.lang.Error | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_new); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangError()); | |
} | |
public void newJavaLangAssertionError() { | |
// new: java.lang.AssertionError | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_new); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionError()); | |
} | |
public void newNoClassDefFoundError() { // new: java.lang.NoClassDefFoundError | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_new); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundError()); | |
} | |
public void newStringBuffer() { // new: java.lang.StringBuffer | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_new); | |
} | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuffer()); | |
} | |
public void newWrapperFor(int typeID) { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_new); | |
} | |
switch (typeID) { | |
case T_int : // new: java.lang.Integer | |
writeUnsignedShort(constantPool.literalIndexForJavaLangInteger()); | |
break; | |
case T_boolean : // new: java.lang.Boolean | |
writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean()); | |
break; | |
case T_byte : // new: java.lang.Byte | |
writeUnsignedShort(constantPool.literalIndexForJavaLangByte()); | |
break; | |
case T_char : // new: java.lang.Character | |
writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter()); | |
break; | |
case T_float : // new: java.lang.Float | |
writeUnsignedShort(constantPool.literalIndexForJavaLangFloat()); | |
break; | |
case T_double : // new: java.lang.Double | |
writeUnsignedShort(constantPool.literalIndexForJavaLangDouble()); | |
break; | |
case T_short : // new: java.lang.Short | |
writeUnsignedShort(constantPool.literalIndexForJavaLangShort()); | |
break; | |
case T_long : // new: java.lang.Long | |
writeUnsignedShort(constantPool.literalIndexForJavaLangLong()); | |
break; | |
case T_void : // new: java.lang.Void | |
writeUnsignedShort(constantPool.literalIndexForJavaLangVoid()); | |
} | |
} | |
final public void nop() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_nop; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_nop); | |
} | |
} | |
final public void pop() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_pop; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_pop); | |
} | |
} | |
final public void pop2() { | |
countLabels = 0; | |
stackDepth -= 2; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_pop2; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_pop2); | |
} | |
} | |
final public void putfield(FieldBinding fieldBinding) { | |
countLabels = 0; | |
int id; | |
if (((id = fieldBinding.type.id) == T_double) || (id == T_long)) | |
stackDepth -= 3; | |
else | |
stackDepth -= 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_putfield; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_putfield); | |
} | |
writeUnsignedShort(constantPool.literalIndex(fieldBinding)); | |
} | |
final public void putstatic(FieldBinding fieldBinding) { | |
countLabels = 0; | |
int id; | |
if (((id = fieldBinding.type.id) == T_double) || (id == T_long)) | |
stackDepth -= 2; | |
else | |
stackDepth -= 1; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_putstatic; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_putstatic); | |
} | |
writeUnsignedShort(constantPool.literalIndex(fieldBinding)); | |
} | |
public void record(LocalVariableBinding local) { | |
if (!generateLocalVariableTableAttributes) | |
return; | |
if (allLocalsCounter == locals.length) { | |
// resize the collection | |
System.arraycopy(locals, 0, (locals = new LocalVariableBinding[allLocalsCounter + LOCALS_INCREMENT]), 0, allLocalsCounter); | |
} | |
locals[allLocalsCounter++] = local; | |
local.initializationPCs = new int[4]; | |
local.initializationCount = 0; | |
} | |
public void recordPositionsFrom(int startPC, int sourcePos) { | |
/* Record positions in the table, only if nothing has | |
* already been recorded. Since we output them on the way | |
* up (children first for more specific info) | |
* The pcToSourceMap table is always sorted. | |
*/ | |
if (!generateLineNumberAttributes) | |
return; | |
if (sourcePos == 0) | |
return; | |
// no code generated for this node. e.g. field without any initialization | |
if (position == startPC) | |
return; | |
// Widening an existing entry that already has the same source positions | |
if (pcToSourceMapSize + 4 > pcToSourceMap.length) { | |
// resize the array pcToSourceMap | |
System.arraycopy(pcToSourceMap, 0, (pcToSourceMap = new int[pcToSourceMapSize << 1]), 0, pcToSourceMapSize); | |
} | |
int newLine = ClassFile.searchLineNumber(lineSeparatorPositions, sourcePos); | |
// lastEntryPC represents the endPC of the lastEntry. | |
if (pcToSourceMapSize > 0) { | |
// in this case there is already an entry in the table | |
if (pcToSourceMap[pcToSourceMapSize - 1] != newLine) { | |
if (startPC < lastEntryPC) { | |
// we forgot to add an entry. | |
// search if an existing entry exists for startPC | |
int insertionIndex = insertionIndex(pcToSourceMap, pcToSourceMapSize, startPC); | |
if (insertionIndex != -1) { | |
// there is no existing entry starting with startPC. | |
int existingEntryIndex = indexOfSameLineEntrySincePC(startPC, newLine); // index for PC | |
/* the existingEntryIndex corresponds to en entry with the same line and a PC >= startPC. | |
in this case it is relevant to widen this entry instead of creating a new one. | |
line1: this(a, | |
b, | |
c); | |
with this code we generate each argument. We generate a aload0 to invoke the constructor. There is no entry for this | |
aload0 bytecode. The first entry is the one for the argument a. | |
But we want the constructor call to start at the aload0 pc and not just at the pc of the first argument. | |
So we widen the existing entry (if there is one) or we create a new entry with the startPC. | |
*/ | |
if (existingEntryIndex != -1) { | |
// widen existing entry | |
pcToSourceMap[existingEntryIndex] = startPC; | |
} else { | |
// we have to add an entry that won't be sorted. So we sort the pcToSourceMap. | |
System.arraycopy(pcToSourceMap, insertionIndex, pcToSourceMap, insertionIndex + 2, pcToSourceMapSize - insertionIndex); | |
pcToSourceMap[insertionIndex++] = startPC; | |
pcToSourceMap[insertionIndex] = newLine; | |
pcToSourceMapSize += 2; | |
} | |
} | |
if (position != lastEntryPC) { // no bytecode since last entry pc | |
pcToSourceMap[pcToSourceMapSize++] = lastEntryPC; | |
pcToSourceMap[pcToSourceMapSize++] = newLine; | |
} | |
} else { | |
// we can safely add the new entry. The endPC of the previous entry is not in conflit with the startPC of the new entry. | |
pcToSourceMap[pcToSourceMapSize++] = startPC; | |
pcToSourceMap[pcToSourceMapSize++] = newLine; | |
} | |
} else { | |
/* the last recorded entry is on the same line. But it could be relevant to widen this entry. | |
we want to extend this entry forward in case we generated some bytecode before the last entry that are not related to any statement | |
*/ | |
if (startPC < pcToSourceMap[pcToSourceMapSize - 2]) { | |
int insertionIndex = insertionIndex(pcToSourceMap, pcToSourceMapSize, startPC); | |
if (insertionIndex != -1) { | |
// widen the existing entry | |
// we have to figure out if we need to move the last entry at another location to keep a sorted table | |
if ((pcToSourceMapSize > 4) && (pcToSourceMap[pcToSourceMapSize - 4] > startPC)) { | |
System.arraycopy(pcToSourceMap, insertionIndex, pcToSourceMap, insertionIndex + 2, pcToSourceMapSize - 2 - insertionIndex); | |
pcToSourceMap[insertionIndex++] = startPC; | |
pcToSourceMap[insertionIndex] = newLine; | |
} else { | |
pcToSourceMap[pcToSourceMapSize - 2] = startPC; | |
} | |
} | |
} | |
} | |
lastEntryPC = position; | |
} else { | |
// record the first entry | |
pcToSourceMap[pcToSourceMapSize++] = startPC; | |
pcToSourceMap[pcToSourceMapSize++] = newLine; | |
lastEntryPC = position; | |
} | |
} | |
/** | |
* @param anExceptionLabel org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel | |
*/ | |
public void registerExceptionHandler(ExceptionLabel anExceptionLabel) { | |
int length; | |
if (exceptionHandlersNumber >= (length = exceptionHandlers.length)) { | |
// resize the exception handlers table | |
System.arraycopy(exceptionHandlers, 0, exceptionHandlers = new ExceptionLabel[length + LABELS_INCREMENT], 0, length); | |
} | |
// no need to resize. So just add the new exception label | |
exceptionHandlers[exceptionHandlersNumber++] = anExceptionLabel; | |
} | |
public final void removeNotDefinitelyAssignedVariables(Scope scope, int initStateIndex) { | |
// given some flow info, make sure we did not loose some variables initialization | |
// if this happens, then we must update their pc entries to reflect it in debug attributes | |
if (!generateLocalVariableTableAttributes) | |
return; | |
/* if (initStateIndex == lastInitStateIndexWhenRemovingInits) | |
return; | |
lastInitStateIndexWhenRemovingInits = initStateIndex; | |
if (lastInitStateIndexWhenAddingInits != initStateIndex){ | |
lastInitStateIndexWhenAddingInits = -2;// reinitialize add index | |
// add(1)-remove(1)-add(1) -> ignore second add | |
// add(1)-remove(2)-add(1) -> perform second add | |
}*/ | |
for (int i = 0; i < visibleLocalsCount; i++) { | |
LocalVariableBinding localBinding = visibleLocals[i]; | |
if (localBinding != null) { | |
if (initStateIndex == -1 || !isDefinitelyAssigned(scope, initStateIndex, localBinding)) { | |
if (localBinding.initializationCount > 0) { | |
localBinding.recordInitializationEndPC(position); | |
} | |
} | |
} | |
} | |
} | |
/** | |
* @param methodDeclaration org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration | |
* @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile | |
*/ | |
public void reset(AbstractMethodDeclaration methodDeclaration, ClassFile classFile) { | |
init(classFile); | |
this.methodDeclaration = methodDeclaration; | |
preserveUnusedLocals = methodDeclaration.scope.problemReporter().options.preserveAllLocalVariables; | |
initializeMaxLocals(methodDeclaration.binding); | |
} | |
/** | |
* @param methodDeclaration org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration | |
* @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile | |
*/ | |
public void resetForProblemClinit(ClassFile classFile) { | |
init(classFile); | |
maxLocals = 0; | |
} | |
protected final void resizeByteArray() { | |
int actualLength = bCodeStream.length; | |
int requiredSize = actualLength + growFactor; | |
if (classFileOffset > requiredSize) { | |
requiredSize = classFileOffset + growFactor; | |
} | |
System.arraycopy(bCodeStream, 0, (bCodeStream = new byte[requiredSize]), 0, actualLength); | |
} | |
/** | |
* This method is used to resize the internal byte array in | |
* case of a ArrayOutOfBoundsException when adding the value b. | |
* Resize and add the new byte b inside the array. | |
* @param b byte | |
*/ | |
protected final void resizeByteArray(byte b) { | |
resizeByteArray(); | |
bCodeStream[classFileOffset - 1] = b; | |
} | |
final public void ret(int index) { | |
countLabels = 0; | |
if (index > 255) { // Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ret; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ret); | |
} | |
writeUnsignedShort(index); | |
} else { // Don't Widen | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ret; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_ret); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) index; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) index); | |
} | |
} | |
} | |
final public void return_() { | |
countLabels = 0; | |
// the stackDepth should be equal to 0 | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_return; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_return); | |
} | |
} | |
final public void saload() { | |
countLabels = 0; | |
stackDepth--; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_saload; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_saload); | |
} | |
} | |
final public void sastore() { | |
countLabels = 0; | |
stackDepth -= 3; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_sastore; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_sastore); | |
} | |
} | |
/** | |
* @param operatorConstant int | |
* @param type_ID int | |
*/ | |
public void sendOperator(int operatorConstant, int type_ID) { | |
switch (type_ID) { | |
case T_int : | |
case T_boolean : | |
case T_char : | |
case T_byte : | |
case T_short : | |
switch (operatorConstant) { | |
case PLUS : | |
this.iadd(); | |
break; | |
case MINUS : | |
this.isub(); | |
break; | |
case MULTIPLY : | |
this.imul(); | |
break; | |
case DIVIDE : | |
this.idiv(); | |
break; | |
case REMAINDER : | |
this.irem(); | |
break; | |
case LEFT_SHIFT : | |
this.ishl(); | |
break; | |
case RIGHT_SHIFT : | |
this.ishr(); | |
break; | |
case UNSIGNED_RIGHT_SHIFT : | |
this.iushr(); | |
break; | |
case AND : | |
this.iand(); | |
break; | |
case OR : | |
this.ior(); | |
break; | |
case XOR : | |
this.ixor(); | |
break; | |
} | |
break; | |
case T_long : | |
switch (operatorConstant) { | |
case PLUS : | |
this.ladd(); | |
break; | |
case MINUS : | |
this.lsub(); | |
break; | |
case MULTIPLY : | |
this.lmul(); | |
break; | |
case DIVIDE : | |
this.ldiv(); | |
break; | |
case REMAINDER : | |
this.lrem(); | |
break; | |
case LEFT_SHIFT : | |
this.lshl(); | |
break; | |
case RIGHT_SHIFT : | |
this.lshr(); | |
break; | |
case UNSIGNED_RIGHT_SHIFT : | |
this.lushr(); | |
break; | |
case AND : | |
this.land(); | |
break; | |
case OR : | |
this.lor(); | |
break; | |
case XOR : | |
this.lxor(); | |
break; | |
} | |
break; | |
case T_float : | |
switch (operatorConstant) { | |
case PLUS : | |
this.fadd(); | |
break; | |
case MINUS : | |
this.fsub(); | |
break; | |
case MULTIPLY : | |
this.fmul(); | |
break; | |
case DIVIDE : | |
this.fdiv(); | |
break; | |
case REMAINDER : | |
this.frem(); | |
} | |
break; | |
case T_double : | |
switch (operatorConstant) { | |
case PLUS : | |
this.dadd(); | |
break; | |
case MINUS : | |
this.dsub(); | |
break; | |
case MULTIPLY : | |
this.dmul(); | |
break; | |
case DIVIDE : | |
this.ddiv(); | |
break; | |
case REMAINDER : | |
this.drem(); | |
} | |
} | |
} | |
final public void sipush(int s) { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_sipush; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_sipush); | |
} | |
writeSignedShort(s); | |
} | |
public static final void sort(int[] tab, int lo0, int hi0, int[] result) { | |
int lo = lo0; | |
int hi = hi0; | |
int mid; | |
if (hi0 > lo0) { | |
/* Arbitrarily establishing partition element as the midpoint of | |
* the array. | |
*/ | |
mid = tab[ (lo0 + hi0) / 2]; | |
// loop through the array until indices cross | |
while (lo <= hi) { | |
/* find the first element that is greater than or equal to | |
* the partition element starting from the left Index. | |
*/ | |
while ((lo < hi0) && (tab[lo] < mid)) | |
++lo; | |
/* find an element that is smaller than or equal to | |
* the partition element starting from the right Index. | |
*/ | |
while ((hi > lo0) && (tab[hi] > mid)) | |
--hi; | |
// if the indexes have not crossed, swap | |
if (lo <= hi) { | |
swap(tab, lo, hi, result); | |
++lo; | |
--hi; | |
} | |
} | |
/* If the right index has not reached the left side of array | |
* must now sort the left partition. | |
*/ | |
if (lo0 < hi) | |
sort(tab, lo0, hi, result); | |
/* If the left index has not reached the right side of array | |
* must now sort the right partition. | |
*/ | |
if (lo < hi0) | |
sort(tab, lo, hi0, result); | |
} | |
} | |
public final void store(LocalVariableBinding localBinding, boolean valueRequired) { | |
TypeBinding type = localBinding.type; | |
int position = localBinding.resolvedPosition; | |
// Using dedicated int bytecode | |
if ((type == IntBinding) || (type == CharBinding) || (type == ByteBinding) || (type == ShortBinding) || (type == BooleanBinding)) { | |
if (valueRequired) | |
this.dup(); | |
switch (position) { | |
case 0 : | |
this.istore_0(); | |
break; | |
case 1 : | |
this.istore_1(); | |
break; | |
case 2 : | |
this.istore_2(); | |
break; | |
case 3 : | |
this.istore_3(); | |
break; | |
default : | |
this.istore(position); | |
} | |
return; | |
} | |
// Using dedicated float bytecode | |
if (type == FloatBinding) { | |
if (valueRequired) | |
this.dup(); | |
switch (position) { | |
case 0 : | |
this.fstore_0(); | |
break; | |
case 1 : | |
this.fstore_1(); | |
break; | |
case 2 : | |
this.fstore_2(); | |
break; | |
case 3 : | |
this.fstore_3(); | |
break; | |
default : | |
this.fstore(position); | |
} | |
return; | |
} | |
// Using dedicated long bytecode | |
if (type == LongBinding) { | |
if (valueRequired) | |
this.dup2(); | |
switch (position) { | |
case 0 : | |
this.lstore_0(); | |
break; | |
case 1 : | |
this.lstore_1(); | |
break; | |
case 2 : | |
this.lstore_2(); | |
break; | |
case 3 : | |
this.lstore_3(); | |
break; | |
default : | |
this.lstore(position); | |
} | |
return; | |
} | |
// Using dedicated double bytecode | |
if (type == DoubleBinding) { | |
if (valueRequired) | |
this.dup2(); | |
switch (position) { | |
case 0 : | |
this.dstore_0(); | |
break; | |
case 1 : | |
this.dstore_1(); | |
break; | |
case 2 : | |
this.dstore_2(); | |
break; | |
case 3 : | |
this.dstore_3(); | |
break; | |
default : | |
this.dstore(position); | |
} | |
return; | |
} | |
// Reference object | |
if (valueRequired) | |
this.dup(); | |
switch (position) { | |
case 0 : | |
this.astore_0(); | |
break; | |
case 1 : | |
this.astore_1(); | |
break; | |
case 2 : | |
this.astore_2(); | |
break; | |
case 3 : | |
this.astore_3(); | |
break; | |
default : | |
this.astore(position); | |
} | |
} | |
public final void store(TypeBinding type, int position) { | |
// Using dedicated int bytecode | |
if ((type == IntBinding) || (type == CharBinding) || (type == ByteBinding) || (type == ShortBinding) || (type == BooleanBinding)) { | |
switch (position) { | |
case 0 : | |
this.istore_0(); | |
break; | |
case 1 : | |
this.istore_1(); | |
break; | |
case 2 : | |
this.istore_2(); | |
break; | |
case 3 : | |
this.istore_3(); | |
break; | |
default : | |
this.istore(position); | |
} | |
return; | |
} | |
// Using dedicated float bytecode | |
if (type == FloatBinding) { | |
switch (position) { | |
case 0 : | |
this.fstore_0(); | |
break; | |
case 1 : | |
this.fstore_1(); | |
break; | |
case 2 : | |
this.fstore_2(); | |
break; | |
case 3 : | |
this.fstore_3(); | |
break; | |
default : | |
this.fstore(position); | |
} | |
return; | |
} | |
// Using dedicated long bytecode | |
if (type == LongBinding) { | |
switch (position) { | |
case 0 : | |
this.lstore_0(); | |
break; | |
case 1 : | |
this.lstore_1(); | |
break; | |
case 2 : | |
this.lstore_2(); | |
break; | |
case 3 : | |
this.lstore_3(); | |
break; | |
default : | |
this.lstore(position); | |
} | |
return; | |
} | |
// Using dedicated double bytecode | |
if (type == DoubleBinding) { | |
switch (position) { | |
case 0 : | |
this.dstore_0(); | |
break; | |
case 1 : | |
this.dstore_1(); | |
break; | |
case 2 : | |
this.dstore_2(); | |
break; | |
case 3 : | |
this.dstore_3(); | |
break; | |
default : | |
this.dstore(position); | |
} | |
return; | |
} | |
// Reference object | |
switch (position) { | |
case 0 : | |
this.astore_0(); | |
break; | |
case 1 : | |
this.astore_1(); | |
break; | |
case 2 : | |
this.astore_2(); | |
break; | |
case 3 : | |
this.astore_3(); | |
break; | |
default : | |
this.astore(position); | |
} | |
} | |
public final void storeInt(int position) { | |
switch (position) { | |
case 0 : | |
this.istore_0(); | |
break; | |
case 1 : | |
this.istore_1(); | |
break; | |
case 2 : | |
this.istore_2(); | |
break; | |
case 3 : | |
this.istore_3(); | |
break; | |
default : | |
this.istore(position); | |
} | |
} | |
public final void storeObject(int position) { | |
switch (position) { | |
case 0 : | |
this.astore_0(); | |
break; | |
case 1 : | |
this.astore_1(); | |
break; | |
case 2 : | |
this.astore_2(); | |
break; | |
case 3 : | |
this.astore_3(); | |
break; | |
default : | |
this.astore(position); | |
} | |
} | |
final public void swap() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_swap; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_swap); | |
} | |
} | |
private static final void swap(int a[], int i, int j, int result[]) { | |
int T; | |
T = a[i]; | |
a[i] = a[j]; | |
a[j] = T; | |
T = result[j]; | |
result[j] = result[i]; | |
result[i] = T; | |
} | |
final public void tableswitch(CaseLabel defaultLabel, int low, int high, int[] keys, int[] sortedIndexes, CaseLabel[] casesLabel) { | |
countLabels = 0; | |
stackDepth--; | |
int length = casesLabel.length; | |
int pos = position; | |
defaultLabel.placeInstruction(); | |
for (int i = 0; i < length; i++) | |
casesLabel[i].placeInstruction(); | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_tableswitch; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_tableswitch); | |
} | |
for (int i = (3 - (pos % 4)); i > 0; i--) { | |
position++; // Padding | |
classFileOffset++; | |
} | |
defaultLabel.branch(); | |
writeSignedWord(low); | |
writeSignedWord(high); | |
int i = low, j = low; | |
// the index j is used to know if the index i is one of the missing entries in case of an | |
// optimized tableswitch | |
while (true) { | |
int index; | |
int key = keys[index = sortedIndexes[j - low]]; | |
if (key == i) { | |
casesLabel[index].branch(); | |
j++; | |
if (i == high) break; // if high is maxint, then avoids wrapping to minint. | |
} else { | |
defaultLabel.branch(); | |
} | |
i++; | |
} | |
} | |
public String toString() { | |
StringBuffer buffer = new StringBuffer("( position:"); //$NON-NLS-1$ | |
buffer.append(position); | |
buffer.append(",\nstackDepth:"); //$NON-NLS-1$ | |
buffer.append(stackDepth); | |
buffer.append(",\nmaxStack:"); //$NON-NLS-1$ | |
buffer.append(stackMax); | |
buffer.append(",\nmaxLocals:"); //$NON-NLS-1$ | |
buffer.append(maxLocals); | |
buffer.append(")"); //$NON-NLS-1$ | |
return buffer.toString(); | |
} | |
public void updateLastRecordedEndPC(int pos) { | |
/* Tune positions in the table, this is due to some | |
* extra bytecodes being | |
* added to some user code (jumps). */ | |
/** OLD CODE | |
if (!generateLineNumberAttributes) | |
return; | |
pcToSourceMap[pcToSourceMapSize - 1][1] = position; | |
// need to update the initialization endPC in case of generation of local variable attributes. | |
updateLocalVariablesAttribute(pos); | |
*/ | |
if (!generateLineNumberAttributes) | |
return; | |
// need to update the initialization endPC in case of generation of local variable attributes. | |
updateLocalVariablesAttribute(pos); | |
} | |
public void updateLocalVariablesAttribute(int pos) { | |
// need to update the initialization endPC in case of generation of local variable attributes. | |
if (generateLocalVariableTableAttributes) { | |
for (int i = 0, max = locals.length; i < max; i++) { | |
LocalVariableBinding local = locals[i]; | |
if ((local != null) && (local.initializationCount > 0)) { | |
if (local.initializationPCs[((local.initializationCount - 1) << 1) + 1] == pos) { | |
local.initializationPCs[((local.initializationCount - 1) << 1) + 1] = position; | |
} | |
} | |
} | |
} | |
} | |
final public void wide() { | |
countLabels = 0; | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(OPC_wide); | |
} | |
} | |
public final void writeByte(byte b) { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = b; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(b); | |
} | |
} | |
public final void writeByteAtPos(int pos, byte b) { | |
try { | |
bCodeStream[pos] = b; | |
} catch (IndexOutOfBoundsException ex) { | |
resizeByteArray(); | |
bCodeStream[pos] = b; | |
} | |
} | |
/** | |
* Write a unsigned 8 bits value into the byte array | |
* @param b the signed byte | |
*/ | |
public final void writeSignedByte(int b) { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) b; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) b); | |
} | |
} | |
/** | |
* Write a signed 16 bits value into the byte array | |
* @param b the signed short | |
*/ | |
public final void writeSignedShort(int b) { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) (b >> 8); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) (b >> 8)); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) b; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) b); | |
} | |
} | |
public final void writeSignedShort(int pos, int b) { | |
int currentOffset = startingClassFileOffset + pos; | |
try { | |
bCodeStream[currentOffset] = (byte) (b >> 8); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(); | |
bCodeStream[currentOffset] = (byte) (b >> 8); | |
} | |
try { | |
bCodeStream[currentOffset + 1] = (byte) b; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(); | |
bCodeStream[currentOffset + 1] = (byte) b; | |
} | |
} | |
public final void writeSignedWord(int value) { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) ((value & 0xFF000000) >> 24); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) ((value & 0xFF000000) >> 24)); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) ((value & 0xFF0000) >> 16); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) ((value & 0xFF0000) >> 16)); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) ((value & 0xFF00) >> 8); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) ((value & 0xFF00) >> 8)); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) (value & 0xFF); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) (value & 0xFF)); | |
} | |
} | |
public final void writeSignedWord(int pos, int value) { | |
int currentOffset = startingClassFileOffset + pos; | |
try { | |
bCodeStream[currentOffset++] = (byte) ((value & 0xFF000000) >> 24); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(); | |
bCodeStream[currentOffset-1] = (byte) ((value & 0xFF000000) >> 24); | |
} | |
try { | |
bCodeStream[currentOffset++] = (byte) ((value & 0xFF0000) >> 16); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(); | |
bCodeStream[currentOffset-1] = (byte) ((value & 0xFF0000) >> 16); | |
} | |
try { | |
bCodeStream[currentOffset++] = (byte) ((value & 0xFF00) >> 8); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(); | |
bCodeStream[currentOffset-1] = (byte) ((value & 0xFF00) >> 8); | |
} | |
try { | |
bCodeStream[currentOffset++] = (byte) (value & 0xFF); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(); | |
bCodeStream[currentOffset-1] = (byte) (value & 0xFF); | |
} | |
} | |
/** | |
* Write a unsigned 8 bits value into the byte array | |
* @param b the unsigned byte | |
*/ | |
public final void writeUnsignedByte(int b) { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) b; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) b); | |
} | |
} | |
/** | |
* Write a unsigned 16 bits value into the byte array | |
* @param b the unsigned short | |
*/ | |
public final void writeUnsignedShort(int b) { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) (b >>> 8); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) (b >>> 8)); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) b; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) b); | |
} | |
} | |
/** | |
* Write a unsigned 32 bits value into the byte array | |
* @param value the unsigned word | |
*/ | |
public final void writeUnsignedWord(int value) { | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) (value >>> 24); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) (value >>> 24)); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) (value >>> 16); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) (value >>> 16)); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) (value >>> 8); | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) (value >>> 8)); | |
} | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = (byte) value; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray((byte) value); | |
} | |
} | |
public void generateWideConditionalBranch(byte opcode, Label lbl) { | |
/* we handle the goto_w problem inside an if.... with some macro expansion | |
* at the bytecode level | |
* instead of: | |
* if_...... lbl | |
* we have: | |
* ifne <l1> | |
* goto <l2> | |
* l1 gotow <l3> // l3 is a wide target | |
* l2 .... | |
*/ | |
Label l1 = new Label(this); | |
try { | |
position++; | |
bCodeStream[classFileOffset++] = opcode; | |
} catch (IndexOutOfBoundsException e) { | |
resizeByteArray(opcode); | |
} | |
l1.branch(); | |
Label l2 = new Label(this); | |
this.internal_goto_(l2); | |
l1.place(); | |
this.goto_w(lbl); | |
l2.place(); | |
} | |
} |