/******************************************************************************* | |
* Copyright (c) 2000, 2004 IBM Corporation and others. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Common Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/cpl-v10.html | |
* | |
* Contributors: | |
* IBM Corporation - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.wst.jsdt.internal.compiler.codegen; | |
import org.eclipse.wst.jsdt.internal.compiler.*; | |
import org.eclipse.wst.jsdt.internal.compiler.impl.*; | |
import org.eclipse.wst.jsdt.internal.compiler.ast.*; | |
import org.eclipse.wst.jsdt.internal.compiler.classfmt.*; | |
import org.eclipse.wst.jsdt.internal.compiler.flow.*; | |
import org.eclipse.wst.jsdt.internal.compiler.lookup.*; | |
public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, BaseTypes, TypeConstants, TypeIds { | |
public static final boolean DEBUG = false; | |
// 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 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 exceptionHandlersIndex; | |
public int exceptionHandlersCounter; | |
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, 0); | |
// target level to manage different code generation between different target levels | |
private long targetLevel; | |
public CodeStream(ClassFile classFile, long targetLevel) { | |
this.targetLevel = targetLevel; | |
this.generateLineNumberAttributes = (classFile.produceDebugAttributes & CompilerOptions.Lines) != 0; | |
this.generateLocalVariableTableAttributes = (classFile.produceDebugAttributes & CompilerOptions.Vars) != 0; | |
if (this.generateLineNumberAttributes) { | |
this.lineSeparatorPositions = classFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions; | |
} | |
} | |
final public void aaload() { | |
if (DEBUG) System.out.println(position + "\t\taaload"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aaload; | |
} | |
final public void aastore() { | |
if (DEBUG) System.out.println(position + "\t\taastore"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 3; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aastore; | |
} | |
final public void aconst_null() { | |
if (DEBUG) System.out.println(position + "\t\taconst_null"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) { | |
stackMax = stackDepth; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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) { | |
if (DEBUG) System.out.println(position + "\t\taload:"+iArg); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (iArg > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_aload; | |
writeUnsignedShort(iArg); | |
} else { | |
// Don't need to use the wide bytecode | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_aload; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void aload_0() { | |
if (DEBUG) System.out.println(position + "\t\taload_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) { | |
stackMax = stackDepth; | |
} | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload_0; | |
} | |
final public void aload_1() { | |
if (DEBUG) System.out.println(position + "\t\taload_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload_1; | |
} | |
final public void aload_2() { | |
if (DEBUG) System.out.println(position + "\t\taload_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload_2; | |
} | |
final public void aload_3() { | |
if (DEBUG) System.out.println(position + "\t\taload_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_aload_3; | |
} | |
public final void anewarray(TypeBinding typeBinding) { | |
if (DEBUG) System.out.println(position + "\t\tanewarray: " + typeBinding); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_anewarray; | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
} | |
final public void areturn() { | |
if (DEBUG) System.out.println(position + "\t\tareturn"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
// the stackDepth should be equal to 0 | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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() { | |
if (DEBUG) System.out.println(position + "\t\tarraylength"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_arraylength; | |
} | |
final public void astore(int iArg) { | |
if (DEBUG) System.out.println(position + "\t\tastore:"+iArg); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (iArg > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position+=2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_astore; | |
writeUnsignedShort(iArg); | |
} else { | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position+=2; | |
bCodeStream[classFileOffset++] = OPC_astore; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void astore_0() { | |
if (DEBUG) System.out.println(position + "\t\tastore_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore_0; | |
} | |
final public void astore_1() { | |
if (DEBUG) System.out.println(position + "\t\tastore_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore_1; | |
} | |
final public void astore_2() { | |
if (DEBUG) System.out.println(position + "\t\tastore_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore_2; | |
} | |
final public void astore_3() { | |
if (DEBUG) System.out.println(position + "\t\tastore_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_astore_3; | |
} | |
final public void athrow() { | |
if (DEBUG) System.out.println(position + "\t\tathrow"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_athrow; | |
} | |
final public void baload() { | |
if (DEBUG) System.out.println(position + "\t\tbaload"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_baload; | |
} | |
final public void bastore() { | |
if (DEBUG) System.out.println(position + "\t\tbastore"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 3; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_bastore; | |
} | |
final public void bipush(byte b) { | |
if (DEBUG) System.out.println(position + "\t\tbipush "+b); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_bipush; | |
bCodeStream[classFileOffset++] = b; | |
} | |
final public void caload() { | |
if (DEBUG) System.out.println(position + "\t\tcaload"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_caload; | |
} | |
final public void castore() { | |
if (DEBUG) System.out.println(position + "\t\tcastore"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 3; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_castore; | |
} | |
public final void checkcast(TypeBinding typeBinding) { | |
if (DEBUG) System.out.println(position + "\t\tcheckcast:"+typeBinding); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_checkcast; | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
} | |
final public void d2f() { | |
if (DEBUG) System.out.println(position + "\t\td2f"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_d2f; | |
} | |
final public void d2i() { | |
if (DEBUG) System.out.println(position + "\t\td2i"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_d2i; | |
} | |
final public void d2l() { | |
if (DEBUG) System.out.println(position + "\t\td2l"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_d2l; | |
} | |
final public void dadd() { | |
if (DEBUG) System.out.println(position + "\t\tdadd"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dadd; | |
} | |
final public void daload() { | |
if (DEBUG) System.out.println(position + "\t\tdaload"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_daload; | |
} | |
final public void dastore() { | |
if (DEBUG) System.out.println(position + "\t\tdastore"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 4; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dastore; | |
} | |
final public void dcmpg() { | |
if (DEBUG) System.out.println(position + "\t\tdcmpg"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 3; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dcmpg; | |
} | |
final public void dcmpl() { | |
if (DEBUG) System.out.println(position + "\t\tdcmpl"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 3; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dcmpl; | |
} | |
final public void dconst_0() { | |
if (DEBUG) System.out.println(position + "\t\tdconst_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dconst_0; | |
} | |
final public void dconst_1() { | |
if (DEBUG) System.out.println(position + "\t\tdconst_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dconst_1; | |
} | |
final public void ddiv() { | |
if (DEBUG) System.out.println(position + "\t\tddiv"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ddiv; | |
} | |
public void decrStackSize(int offset) { | |
stackDepth -= offset; | |
} | |
final public void dload(int iArg) { | |
if (DEBUG) System.out.println(position + "\t\tdload:"+iArg); //$NON-NLS-1$ | |
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 | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_dload; | |
writeUnsignedShort(iArg); | |
} else { | |
// Don't need to use the wide bytecode | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_dload; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void dload_0() { | |
if (DEBUG) System.out.println(position + "\t\tdload_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals < 2) { | |
maxLocals = 2; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload_0; | |
} | |
final public void dload_1() { | |
if (DEBUG) System.out.println(position + "\t\tdload_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals < 3) { | |
maxLocals = 3; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload_1; | |
} | |
final public void dload_2() { | |
if (DEBUG) System.out.println(position + "\t\tdload_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals < 4) { | |
maxLocals = 4; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload_2; | |
} | |
final public void dload_3() { | |
if (DEBUG) System.out.println(position + "\t\tdload_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (maxLocals < 5) { | |
maxLocals = 5; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dload_3; | |
} | |
final public void dmul() { | |
if (DEBUG) System.out.println(position + "\t\tdmul"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dmul; | |
} | |
final public void dneg() { | |
if (DEBUG) System.out.println(position + "\t\tdneg"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dneg; | |
} | |
final public void drem() { | |
if (DEBUG) System.out.println(position + "\t\tdrem"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_drem; | |
} | |
final public void dreturn() { | |
if (DEBUG) System.out.println(position + "\t\tdreturn"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
// the stackDepth should be equal to 0 | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dreturn; | |
} | |
final public void dstore(int iArg) { | |
if (DEBUG) System.out.println(position + "\t\tdstore:"+iArg); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals <= iArg + 1) { | |
maxLocals = iArg + 2; | |
} | |
if (iArg > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_dstore; | |
writeUnsignedShort(iArg); | |
} else { | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_dstore; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void dstore_0() { | |
if (DEBUG) System.out.println(position + "\t\tdstore_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 2) { | |
maxLocals = 2; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore_0; | |
} | |
final public void dstore_1() { | |
if (DEBUG) System.out.println(position + "\t\tdstore_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 3) { | |
maxLocals = 3; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore_1; | |
} | |
final public void dstore_2() { | |
if (DEBUG) System.out.println(position + "\t\tdstore_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 4) { | |
maxLocals = 4; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore_2; | |
} | |
final public void dstore_3() { | |
if (DEBUG) System.out.println(position + "\t\tdstore_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 5) { | |
maxLocals = 5; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dstore_3; | |
} | |
final public void dsub() { | |
if (DEBUG) System.out.println(position + "\t\tdsub"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dsub; | |
} | |
final public void dup() { | |
if (DEBUG) System.out.println(position + "\t\tdup"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) { | |
stackMax = stackDepth; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup; | |
} | |
final public void dup_x1() { | |
if (DEBUG) System.out.println(position + "\t\tdup_x1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup_x1; | |
} | |
final public void dup_x2() { | |
if (DEBUG) System.out.println(position + "\t\tdup_x2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup_x2; | |
} | |
final public void dup2() { | |
if (DEBUG) System.out.println(position + "\t\tdup2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup2; | |
} | |
final public void dup2_x1() { | |
if (DEBUG) System.out.println(position + "\t\tdup2_x1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_dup2_x1; | |
} | |
final public void dup2_x2() { | |
if (DEBUG) System.out.println(position + "\t\tdup2_x2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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() { | |
if (DEBUG) System.out.println(position + "\t\tf2d"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_f2d; | |
} | |
final public void f2i() { | |
if (DEBUG) System.out.println(position + "\t\tf2i"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_f2i; | |
} | |
final public void f2l() { | |
if (DEBUG) System.out.println(position + "\t\tf2l"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_f2l; | |
} | |
final public void fadd() { | |
if (DEBUG) System.out.println(position + "\t\tfadd"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fadd; | |
} | |
final public void faload() { | |
if (DEBUG) System.out.println(position + "\t\tfaload"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_faload; | |
} | |
final public void fastore() { | |
if (DEBUG) System.out.println(position + "\t\tfaload"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 3; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fastore; | |
} | |
final public void fcmpg() { | |
if (DEBUG) System.out.println(position + "\t\tfcmpg"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fcmpg; | |
} | |
final public void fcmpl() { | |
if (DEBUG) System.out.println(position + "\t\tfcmpl"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fcmpl; | |
} | |
final public void fconst_0() { | |
if (DEBUG) System.out.println(position + "\t\tfconst_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fconst_0; | |
} | |
final public void fconst_1() { | |
if (DEBUG) System.out.println(position + "\t\tfconst_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fconst_1; | |
} | |
final public void fconst_2() { | |
if (DEBUG) System.out.println(position + "\t\tfconst_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fconst_2; | |
} | |
final public void fdiv() { | |
if (DEBUG) System.out.println(position + "\t\tfdiv"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fdiv; | |
} | |
final public void fload(int iArg) { | |
if (DEBUG) System.out.println(position + "\t\tfload:"+iArg); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (iArg > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_fload; | |
writeUnsignedShort(iArg); | |
} else { | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_fload; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void fload_0() { | |
if (DEBUG) System.out.println(position + "\t\tfload_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload_0; | |
} | |
final public void fload_1() { | |
if (DEBUG) System.out.println(position + "\t\tfload_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload_1; | |
} | |
final public void fload_2() { | |
if (DEBUG) System.out.println(position + "\t\tfload_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload_2; | |
} | |
final public void fload_3() { | |
if (DEBUG) System.out.println(position + "\t\tfload_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fload_3; | |
} | |
final public void fmul() { | |
if (DEBUG) System.out.println(position + "\t\tfmul"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fmul; | |
} | |
final public void fneg() { | |
if (DEBUG) System.out.println(position + "\t\tfneg"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fneg; | |
} | |
final public void frem() { | |
if (DEBUG) System.out.println(position + "\t\tfrem"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_frem; | |
} | |
final public void freturn() { | |
if (DEBUG) System.out.println(position + "\t\tfreturn"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
// the stackDepth should be equal to 0 | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_freturn; | |
} | |
final public void fstore(int iArg) { | |
if (DEBUG) System.out.println(position + "\t\tfstore:"+iArg); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (iArg > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_fstore; | |
writeUnsignedShort(iArg); | |
} else { | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_fstore; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void fstore_0() { | |
if (DEBUG) System.out.println(position + "\t\tfstore_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore_0; | |
} | |
final public void fstore_1() { | |
if (DEBUG) System.out.println(position + "\t\tfstore_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore_1; | |
} | |
final public void fstore_2() { | |
if (DEBUG) System.out.println(position + "\t\tfstore_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore_2; | |
} | |
final public void fstore_3() { | |
if (DEBUG) System.out.println(position + "\t\tfstore_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_fstore_3; | |
} | |
final public void fsub() { | |
if (DEBUG) System.out.println(position + "\t\tfsub"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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; | |
} | |
if (this.targetLevel >= ClassFileConstants.JDK1_5) { | |
// generation using the new ldc_w bytecode | |
this.ldc(accessedType); | |
} else { | |
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, BaseTypes.NullBinding /* represents ClassNotFoundException*/); | |
this.ldc(accessedType == BaseTypes.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$ | |
this.invokeClassForName(); | |
/* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565 | |
if (accessedType == BaseTypes.NullBinding) { | |
this.ldc("java.lang.Object"); //$NON-NLS-1$ | |
} else if (accessedType.isArrayType()) { | |
this.ldc(String.valueOf(accessedType.constantPoolName()).replace('/', '.')); | |
} else { | |
// we make it an array type (to avoid class initialization) | |
this.ldc("[L" + String.valueOf(accessedType.constantPoolName()).replace('/', '.') + ";"); //$NON-NLS-1$//$NON-NLS-2$ | |
} | |
this.invokeClassForName(); | |
if (!accessedType.isArrayType()) { // extract the component type, which doesn't initialize the class | |
this.invokeJavaLangClassGetComponentType(); | |
} | |
*/ | |
/* 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(); | |
stackDepth = saveStackSize; | |
endLabel.place(); | |
} | |
} | |
/** | |
* This method generates the code attribute bytecode | |
*/ | |
final public void generateCodeAttributeForProblemMethod(String problemMessage) { | |
newJavaLangError(); | |
dup(); | |
ldc(problemMessage); | |
invokeJavaLangErrorConstructor(); | |
athrow(); | |
} | |
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; | |
default : //String or Object | |
ldc(constant.stringValue()); | |
} | |
} | |
/** | |
* Generates the sequence of instructions which will perform the conversion of the expression | |
* on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted). | |
* @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(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, Binding target, Scope scope) { | |
if (mappingSequence == null) { | |
if (target instanceof LocalVariableBinding) { | |
scope.problemReporter().needImplementation(); //TODO (philippe) should improve local emulation failure reporting | |
} else { | |
scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, false); | |
} | |
return; | |
} | |
if (mappingSequence == BlockScope.NoEnclosingInstanceInConstructorCall) { | |
scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, true); | |
return; | |
} else if (mappingSequence == BlockScope.NoEnclosingInstanceInStaticContext) { | |
scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, false); | |
return; | |
} | |
if (mappingSequence == BlockScope.EmulationPathToImplicitThis) { | |
this.aload_0(); | |
return; | |
} else if (mappingSequence[0] instanceof FieldBinding) { | |
FieldBinding fieldBinding = (FieldBinding) mappingSequence[0]; | |
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 blockScope the given blockScope | |
* @param oper1 the first expression | |
* @param oper2 the second expression | |
*/ | |
public void generateStringConcatenationAppend(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.newStringContatenation(); | |
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.invokeStringConcatenationStringConstructor(); | |
} else { | |
pc = position; | |
oper1.generateOptimizedStringConcatenationCreation(blockScope, this, oper1.implicitConversion & 0xF); | |
this.recordPositionsFrom(pc, oper1.sourceStart); | |
} | |
pc = position; | |
oper2.generateOptimizedStringConcatenation(blockScope, this, oper2.implicitConversion & 0xF); | |
this.recordPositionsFrom(pc, oper2.sourceStart); | |
this.invokeStringConcatenationToString(); | |
} | |
/** | |
* Code responsible to generate the suitable code to supply values for the synthetic enclosing | |
* instance arguments of a constructor invocation of a nested type. | |
*/ | |
public void generateSyntheticEnclosingInstanceValues( | |
BlockScope currentScope, | |
ReferenceBinding targetType, | |
Expression enclosingInstance, | |
ASTNode invocationSite) { | |
// supplying enclosing instance for the anonymous type's superclass | |
ReferenceBinding checkedTargetType = targetType.isAnonymousType() ? targetType.superclass() : targetType; | |
boolean hasExtraEnclosingInstance = enclosingInstance != null; | |
if (hasExtraEnclosingInstance | |
&& (!checkedTargetType.isNestedType() || checkedTargetType.isStatic())) { | |
currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType); | |
return; | |
} | |
// perform some emulation work in case there is some and we are inside a local type only | |
ReferenceBinding[] syntheticArgumentTypes; | |
if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes()) != null) { | |
ReferenceBinding targetEnclosingType = checkedTargetType.enclosingType(); | |
boolean complyTo14 = currentScope.environment().options.complianceLevel >= ClassFileConstants.JDK1_4; | |
// deny access to enclosing instance argument for allocation and super constructor call (if 1.4) | |
boolean ignoreEnclosingArgInConstructorCall = invocationSite instanceof AllocationExpression | |
|| (complyTo14 && ((invocationSite instanceof ExplicitConstructorCall && ((ExplicitConstructorCall)invocationSite).isSuperAccess()))); | |
for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) { | |
ReferenceBinding syntheticArgType = syntheticArgumentTypes[i]; | |
if (hasExtraEnclosingInstance && syntheticArgType == targetEnclosingType) { | |
hasExtraEnclosingInstance = false; | |
enclosingInstance.generateCode(currentScope, this, true); | |
if (complyTo14){ | |
dup(); | |
invokeObjectGetClass(); // will perform null check | |
pop(); | |
} | |
} else { | |
Object[] emulationPath = currentScope.getEmulationPath( | |
syntheticArgType, | |
false /*not only exact match (that is, allow compatible)*/, | |
ignoreEnclosingArgInConstructorCall); | |
this.generateOuterAccess(emulationPath, invocationSite, syntheticArgType, currentScope); | |
} | |
} | |
if (hasExtraEnclosingInstance){ | |
currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType); | |
} | |
} | |
} | |
/** | |
* Code responsible to generate the suitable code to supply values for the synthetic outer local | |
* variable arguments of a constructor invocation of a nested type. | |
* (bug 26122) - synthetic values for outer locals must be passed after user arguments, e.g. new X(i = 1){} | |
*/ | |
public void generateSyntheticOuterArgumentValues(BlockScope currentScope, ReferenceBinding targetType, ASTNode invocationSite) { | |
// generate the synthetic outer arguments then | |
SyntheticArgumentBinding syntheticArguments[]; | |
if ((syntheticArguments = targetType.syntheticOuterLocalVariables()) != null) { | |
for (int i = 0, max = syntheticArguments.length; i < max; i++) { | |
LocalVariableBinding targetVariable = syntheticArguments[i].actualOuterLocalVariable; | |
VariableBinding[] emulationPath = currentScope.getEmulationPath(targetVariable); | |
this.generateOuterAccess(emulationPath, invocationSite, targetVariable, currentScope); | |
} | |
} | |
} | |
/** | |
* @param accessBinding the access method binding to generate | |
*/ | |
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++; | |
} | |
} | |
for (int i = 0; i < length; i++) { | |
load(parameters[i], resolvedPosition); | |
if ((parameters[i] == DoubleBinding) || (parameters[i] == LongBinding)) | |
resolvedPosition += 2; | |
else | |
resolvedPosition++; | |
} | |
if (constructorBinding.declaringClass.isNestedType()) { | |
NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass; | |
SyntheticArgumentBinding[] 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++; | |
} | |
} | |
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; | |
TypeBinding[] arguments = accessBinding.accessType == SyntheticAccessMethodBinding.BridgeMethodAccess | |
? accessBinding.parameters | |
: null; | |
int resolvedPosition; | |
if (methodBinding.isStatic()) | |
resolvedPosition = 0; | |
else { | |
this.aload_0(); | |
resolvedPosition = 1; | |
} | |
for (int i = 0; i < length; i++) { | |
TypeBinding parameter = parameters[i]; | |
if (arguments != null) { // for bridge methods | |
TypeBinding argument = arguments[i]; | |
load(argument, resolvedPosition); | |
if (argument != parameter) | |
checkcast(parameter); | |
} else { | |
load(parameter, resolvedPosition); | |
} | |
if ((parameter == DoubleBinding) || (parameter == 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 | |
|| accessBinding.accessType == SyntheticAccessMethodBinding.SuperMethodAccess){ | |
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) { | |
if (DEBUG) System.out.println(position + "\t\tgetfield:"+fieldBinding); //$NON-NLS-1$ | |
countLabels = 0; | |
if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) { | |
if (++stackDepth > stackMax) | |
stackMax = stackDepth; | |
} | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_getfield; | |
writeUnsignedShort(constantPool.literalIndex(fieldBinding)); | |
} | |
final public void getstatic(FieldBinding fieldBinding) { | |
if (DEBUG) System.out.println(position + "\t\tgetstatic:"+fieldBinding); //$NON-NLS-1$ | |
countLabels = 0; | |
if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) | |
stackDepth += 2; | |
else | |
stackDepth += 1; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_getstatic; | |
writeUnsignedShort(constantPool.literalIndex(fieldBinding)); | |
} | |
public void getTYPE(int baseTypeID) { | |
countLabels = 0; | |
if (++stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_getstatic; | |
switch (baseTypeID) { | |
case T_byte : | |
// getstatic: java.lang.Byte.TYPE | |
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Byte.TYPE"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangByteTYPE()); | |
break; | |
case T_short : | |
// getstatic: java.lang.Short.TYPE | |
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Short.TYPE"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangShortTYPE()); | |
break; | |
case T_char : | |
// getstatic: java.lang.Character.TYPE | |
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Character.TYPE"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangCharacterTYPE()); | |
break; | |
case T_int : | |
// getstatic: java.lang.Integer.TYPE | |
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Integer.TYPE"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangIntegerTYPE()); | |
break; | |
case T_long : | |
// getstatic: java.lang.Long.TYPE | |
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Long.TYPE"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangLongTYPE()); | |
break; | |
case T_float : | |
// getstatic: java.lang.Float.TYPE | |
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Float.TYPE"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangFloatTYPE()); | |
break; | |
case T_double : | |
// getstatic: java.lang.Double.TYPE | |
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Double.TYPE"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangDoubleTYPE()); | |
break; | |
case T_boolean : | |
// getstatic: java.lang.Boolean.TYPE | |
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Boolean.TYPE"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangBooleanTYPE()); | |
break; | |
case T_void : | |
// getstatic: java.lang.Void.TYPE | |
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Void.TYPE"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangVoidTYPE()); | |
break; | |
} | |
} | |
/** | |
* We didn't call it goto, because there is a conflit with the goto keyword | |
*/ | |
final public void goto_(Label label) { | |
if (this.wideMode) { | |
this.goto_w(label); | |
return; | |
} | |
if (DEBUG) System.out.println(position + "\t\tgoto:"+label); //$NON-NLS-1$ | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
label.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; | |
label.branch(); | |
} | |
final public void goto_w(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tgotow:"+lbl); //$NON-NLS-1$ | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_goto_w; | |
lbl.branchWide(); | |
} | |
final public void i2b() { | |
if (DEBUG) System.out.println(position + "\t\ti2b"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2b; | |
} | |
final public void i2c() { | |
if (DEBUG) System.out.println(position + "\t\ti2c"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2c; | |
} | |
final public void i2d() { | |
if (DEBUG) System.out.println(position + "\t\ti2d"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2d; | |
} | |
final public void i2f() { | |
if (DEBUG) System.out.println(position + "\t\ti2f"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2f; | |
} | |
final public void i2l() { | |
if (DEBUG) System.out.println(position + "\t\ti2l"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2l; | |
} | |
final public void i2s() { | |
if (DEBUG) System.out.println(position + "\t\ti2s"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_i2s; | |
} | |
final public void iadd() { | |
if (DEBUG) System.out.println(position + "\t\tiadd"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iadd; | |
} | |
final public void iaload() { | |
if (DEBUG) System.out.println(position + "\t\tiaload"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iaload; | |
} | |
final public void iand() { | |
if (DEBUG) System.out.println(position + "\t\tiand"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iand; | |
} | |
final public void iastore() { | |
if (DEBUG) System.out.println(position + "\t\tiastore"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 3; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iastore; | |
} | |
final public void iconst_0() { | |
if (DEBUG) System.out.println(position + "\t\ticonst_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_0; | |
} | |
final public void iconst_1() { | |
if (DEBUG) System.out.println(position + "\t\ticonst_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_1; | |
} | |
final public void iconst_2() { | |
if (DEBUG) System.out.println(position + "\t\ticonst_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_2; | |
} | |
final public void iconst_3() { | |
if (DEBUG) System.out.println(position + "\t\ticonst_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_3; | |
} | |
final public void iconst_4() { | |
if (DEBUG) System.out.println(position + "\t\ticonst_4"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_4; | |
} | |
final public void iconst_5() { | |
if (DEBUG) System.out.println(position + "\t\ticonst_5"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_5; | |
} | |
final public void iconst_m1() { | |
if (DEBUG) System.out.println(position + "\t\ticonst_m1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iconst_m1; | |
} | |
final public void idiv() { | |
if (DEBUG) System.out.println(position + "\t\tidiv"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_idiv; | |
} | |
final public void if_acmpeq(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tif_acmpeq:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth-=2; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_if_acmpne, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_acmpeq; | |
lbl.branch(); | |
} | |
} | |
final public void if_acmpne(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tif_acmpne:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth-=2; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_if_acmpeq, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_acmpne; | |
lbl.branch(); | |
} | |
} | |
final public void if_icmpeq(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tif_cmpeq:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_if_icmpne, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmpeq; | |
lbl.branch(); | |
} | |
} | |
final public void if_icmpge(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tif_iacmpge:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_if_icmplt, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmpge; | |
lbl.branch(); | |
} | |
} | |
final public void if_icmpgt(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tif_iacmpgt:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_if_icmple, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmpgt; | |
lbl.branch(); | |
} | |
} | |
final public void if_icmple(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tif_iacmple:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_if_icmpgt, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmple; | |
lbl.branch(); | |
} | |
} | |
final public void if_icmplt(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tif_iacmplt:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_if_icmpge, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmplt; | |
lbl.branch(); | |
} | |
} | |
final public void if_icmpne(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tif_iacmpne:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_if_icmpeq, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_if_icmpne; | |
lbl.branch(); | |
} | |
} | |
final public void ifeq(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tifeq:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_ifne, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifeq; | |
lbl.branch(); | |
} | |
} | |
final public void ifge(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tifge:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_iflt, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifge; | |
lbl.branch(); | |
} | |
} | |
final public void ifgt(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tifgt:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_ifle, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifgt; | |
lbl.branch(); | |
} | |
} | |
final public void ifle(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tifle:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_ifgt, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifle; | |
lbl.branch(); | |
} | |
} | |
final public void iflt(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tiflt:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_ifge, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iflt; | |
lbl.branch(); | |
} | |
} | |
final public void ifne(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tifne:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_ifeq, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifne; | |
lbl.branch(); | |
} | |
} | |
final public void ifnonnull(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tifnonnull:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_ifnull, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifnonnull; | |
lbl.branch(); | |
} | |
} | |
final public void ifnull(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tifnull:"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (this.wideMode) { | |
generateWideRevertedConditionalBranch(OPC_ifnonnull, lbl); | |
} else { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ifnull; | |
lbl.branch(); | |
} | |
} | |
final public void iinc(int index, int value) { | |
if (DEBUG) System.out.println(position + "\t\tiinc:"+index+","+value); //$NON-NLS-1$ //$NON-NLS-2$ | |
countLabels = 0; | |
if ((index > 255) || (value < -128 || value > 127)) { // have to widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_iinc; | |
writeUnsignedShort(index); | |
writeSignedShort(value); | |
} else { | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 3; | |
bCodeStream[classFileOffset++] = OPC_iinc; | |
bCodeStream[classFileOffset++] = (byte) index; | |
bCodeStream[classFileOffset++] = (byte) value; | |
} | |
} | |
final public void iload(int iArg) { | |
if (DEBUG) System.out.println(position + "\t\tiload:"+iArg); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (iArg > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_iload; | |
writeUnsignedShort(iArg); | |
} else { | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_iload; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void iload_0() { | |
if (DEBUG) System.out.println(position + "\t\tiload_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 0) { | |
maxLocals = 1; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload_0; | |
} | |
final public void iload_1() { | |
if (DEBUG) System.out.println(position + "\t\tiload_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload_1; | |
} | |
final public void iload_2() { | |
if (DEBUG) System.out.println(position + "\t\tiload_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload_2; | |
} | |
final public void iload_3() { | |
if (DEBUG) System.out.println(position + "\t\tiload_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iload_3; | |
} | |
final public void imul() { | |
if (DEBUG) System.out.println(position + "\t\timul"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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() { | |
if (DEBUG) System.out.println(position + "\t\tineg"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ineg; | |
} | |
public void init(ClassFile targetClassFile) { | |
this.classFile = targetClassFile; | |
this.constantPool = targetClassFile.constantPool; | |
this.bCodeStream = targetClassFile.contents; | |
this.classFileOffset = targetClassFile.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); | |
exceptionHandlersIndex = 0; | |
exceptionHandlersCounter = 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 methodBinding the given method binding to initialize the max locals | |
*/ | |
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 pcToSourceMap the given pcToSourceMap array | |
* @param length the given length | |
* @param pc the given 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) { | |
if (DEBUG) System.out.println(position + "\t\tinstance_of:"+typeBinding); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_instanceof; | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
} | |
public void invokeClassForName() { | |
// invokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; | |
if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokestatic; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangClassForName()); | |
} | |
public void invokeJavaLangClassDesiredAssertionStatus() { | |
// invokevirtual: java.lang.Class.desiredAssertionStatus()Z; | |
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.desiredAssertionStatus()Z;"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangClassDesiredAssertionStatus()); | |
} | |
public void invokeJavaLangClassGetComponentType() { | |
// invokevirtual: java.lang.Class.getComponentType()java.lang.Class; | |
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.getComponentType()java.lang.Class;"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangClassGetComponentType()); | |
} | |
final public void invokeinterface(MethodBinding methodBinding) { | |
// initialized to 1 to take into account this immediately | |
if (DEBUG) System.out.println(position + "\t\tinvokeinterface: " + methodBinding); //$NON-NLS-1$ | |
countLabels = 0; | |
int argCount = 1; | |
int id; | |
if (classFileOffset + 4 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 3; | |
bCodeStream[classFileOffset++] = 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; | |
bCodeStream[classFileOffset++] = (byte) 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. | |
bCodeStream[classFileOffset++] = 0; | |
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 | |
if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.Error<init>(Ljava.lang.String;)V"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
stackDepth -= 2; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangErrorConstructor()); | |
} | |
public void invokeNoClassDefFoundErrorStringConstructor() { | |
// invokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V | |
if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
stackDepth -= 2; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundErrorStringConstructor()); | |
} | |
public void invokeObjectGetClass() { | |
// invokevirtual: java.lang.Object.getClass()Ljava.lang.Class; | |
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Object.getClass()Ljava.lang.Class;"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangObjectGetClass()); | |
} | |
final public void invokespecial(MethodBinding methodBinding) { | |
if (DEBUG) System.out.println(position + "\t\tinvokespecial:"+methodBinding); //$NON-NLS-1$ | |
// initialized to 1 to take into account this immediately | |
countLabels = 0; | |
int argCount = 1; | |
int id; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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) { | |
if (DEBUG) System.out.println(position + "\t\tinvokestatic:"+methodBinding); //$NON-NLS-1$ | |
// initialized to 0 to take into account that there is no this for | |
// a static method | |
countLabels = 0; | |
int argCount = 0; | |
int id; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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 invokeStringConcatenationAppendForType(int typeID) { | |
if (DEBUG) { | |
if (this.targetLevel >= JDK1_5) { | |
System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuilder.append(...)"); //$NON-NLS-1$ | |
} else { | |
System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuffer.append(...)"); //$NON-NLS-1$ | |
} | |
} | |
countLabels = 0; | |
int usedTypeID; | |
if (typeID == T_null) { | |
usedTypeID = T_String; | |
} else { | |
usedTypeID = typeID; | |
} | |
// invokevirtual | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
if (this.targetLevel >= JDK1_5) { | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuilderAppend(typeID)); | |
} else { | |
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 | |
if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.<init>(typeBindingID)V"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorConstructor(typeBindingID)); | |
stackDepth -= 2; | |
} | |
public void invokeJavaLangAssertionErrorDefaultConstructor() { | |
// invokespecial: java.lang.AssertionError.<init>()V | |
if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.<init>()V"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorDefaultConstructor()); | |
stackDepth --; | |
} | |
public void invokeJavaUtilIteratorHasNext() { | |
// invokeinterface java.util.Iterator.hasNext()Z | |
if (DEBUG) System.out.println(position + "\t\tinvokeinterface: java.util.Iterator.hasNext()Z"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 4 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 3; | |
bCodeStream[classFileOffset++] = OPC_invokeinterface; | |
writeUnsignedShort(constantPool.literalIndexForJavaUtilIteratorHasNext()); | |
bCodeStream[classFileOffset++] = 1; | |
// Generate a 0 into the byte array. Like the array is already fill with 0, we just need to increment | |
// the number of bytes. | |
bCodeStream[classFileOffset++] = 0; | |
} | |
public void invokeJavaUtilIteratorNext() { | |
// invokeinterface java.util.Iterator.next()java.lang.Object | |
if (DEBUG) System.out.println(position + "\t\tinvokeinterface: java.util.Iterator.next()java.lang.Object"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 4 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 3; | |
bCodeStream[classFileOffset++] = OPC_invokeinterface; | |
writeUnsignedShort(constantPool.literalIndexForJavaUtilIteratorNext()); | |
bCodeStream[classFileOffset++] = 1; | |
// Generate a 0 into the byte array. Like the array is already fill with 0, we just need to increment | |
// the number of bytes. | |
bCodeStream[classFileOffset++] = 0; | |
} | |
public void invokeStringConcatenationDefaultConstructor() { | |
// invokespecial: java.lang.StringBuffer.<init>()V | |
if (DEBUG) { | |
if (this.targetLevel >= JDK1_5) { | |
System.out.println(position + "\t\tinvokespecial: java.lang.StringBuilder.<init>()V"); //$NON-NLS-1$ | |
} else { | |
System.out.println(position + "\t\tinvokespecial: java.lang.StringBuffer.<init>()V"); //$NON-NLS-1$ | |
} | |
} | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
if (this.targetLevel >= JDK1_5) { | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuilderDefaultConstructor()); | |
} else { | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferDefaultConstructor()); | |
} | |
stackDepth--; | |
} | |
public void invokeStringConcatenationStringConstructor() { | |
if (DEBUG) { | |
if (this.targetLevel >= JDK1_5) { | |
System.out.println(position + "\t\tjava.lang.StringBuilder.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$ | |
} else { | |
System.out.println(position + "\t\tjava.lang.StringBuffer.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$ | |
} | |
} | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokespecial; | |
if (this.targetLevel >= JDK1_5) { | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuilderConstructor()); | |
} else { | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferConstructor()); | |
} | |
stackDepth -= 2; | |
} | |
public void invokeStringConcatenationToString() { | |
if (DEBUG) { | |
if (this.targetLevel >= JDK1_5) { | |
System.out.println(position + "\t\tinvokevirtual: StringBuilder.toString()Ljava.lang.String;"); //$NON-NLS-1$ | |
} else { | |
System.out.println(position + "\t\tinvokevirtual: StringBuffer.toString()Ljava.lang.String;"); //$NON-NLS-1$ | |
} | |
} | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
if (this.targetLevel >= JDK1_5) { | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuilderToString()); | |
} else { | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferToString()); | |
} | |
} | |
public void invokeStringIntern() { | |
// invokevirtual: java.lang.String.intern() | |
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.String.intern()"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringIntern()); | |
} | |
public void invokeStringValueOf(int typeID) { | |
// invokestatic: java.lang.String.valueOf(argumentType) | |
if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.String.valueOf(...)"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokestatic; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringValueOf(typeID)); | |
} | |
public void invokeThrowableGetMessage() { | |
// invokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String; | |
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_invokevirtual; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangThrowableGetMessage()); | |
} | |
final public void invokevirtual(MethodBinding methodBinding) { | |
if (DEBUG) System.out.println(position + "\t\tinvokevirtual:"+methodBinding); //$NON-NLS-1$ | |
// initialized to 1 to take into account this immediately | |
countLabels = 0; | |
int argCount = 1; | |
int id; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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() { | |
if (DEBUG) System.out.println(position + "\t\tior"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ior; | |
} | |
final public void irem() { | |
if (DEBUG) System.out.println(position + "\t\tirem"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_irem; | |
} | |
final public void ireturn() { | |
if (DEBUG) System.out.println(position + "\t\tireturn"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
// the stackDepth should be equal to 0 | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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 localPosition = local.id + maxFieldCount; | |
MethodScope methodScope = scope.methodScope(); | |
// id is zero-based | |
if (localPosition < UnconditionalFlowInfo.BitCacheSize) { | |
return (methodScope.definiteInits[initStateIndex] & (1L << localPosition)) != 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 = (localPosition / UnconditionalFlowInfo.BitCacheSize) - 1) >= extraInits.length) | |
return false; // if not enough room in vector, then not initialized | |
return ((extraInits[vectorIndex]) & (1L << (localPosition % UnconditionalFlowInfo.BitCacheSize))) != 0; | |
} | |
final public void ishl() { | |
if (DEBUG) System.out.println(position + "\t\tishl"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ishl; | |
} | |
final public void ishr() { | |
if (DEBUG) System.out.println(position + "\t\tishr"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ishr; | |
} | |
final public void istore(int iArg) { | |
if (DEBUG) System.out.println(position + "\t\tistore:"+iArg); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= iArg) { | |
maxLocals = iArg + 1; | |
} | |
if (iArg > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_istore; | |
writeUnsignedShort(iArg); | |
} else { | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_istore; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void istore_0() { | |
if (DEBUG) System.out.println(position + "\t\tistore_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals == 0) { | |
maxLocals = 1; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore_0; | |
} | |
final public void istore_1() { | |
if (DEBUG) System.out.println(position + "\t\tistore_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 1) { | |
maxLocals = 2; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore_1; | |
} | |
final public void istore_2() { | |
if (DEBUG) System.out.println(position + "\t\tistore_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 2) { | |
maxLocals = 3; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore_2; | |
} | |
final public void istore_3() { | |
if (DEBUG) System.out.println(position + "\t\tistore_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (maxLocals <= 3) { | |
maxLocals = 4; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_istore_3; | |
} | |
final public void isub() { | |
if (DEBUG) System.out.println(position + "\t\tisub"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_isub; | |
} | |
final public void iushr() { | |
if (DEBUG) System.out.println(position + "\t\tiushr"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_iushr; | |
} | |
final public void ixor() { | |
if (DEBUG) System.out.println(position + "\t\tixor"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ixor; | |
} | |
final public void jsr(Label lbl) { | |
if (this.wideMode) { | |
this.jsr_w(lbl); | |
return; | |
} | |
if (DEBUG) System.out.println(position + "\t\tjsr"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_jsr; | |
lbl.branch(); | |
} | |
final public void jsr_w(Label lbl) { | |
if (DEBUG) System.out.println(position + "\t\tjsr_w"+lbl); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_jsr_w; | |
lbl.branchWide(); | |
} | |
final public void l2d() { | |
if (DEBUG) System.out.println(position + "\t\tl2d"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_l2d; | |
} | |
final public void l2f() { | |
if (DEBUG) System.out.println(position + "\t\tl2f"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_l2f; | |
} | |
final public void l2i() { | |
if (DEBUG) System.out.println(position + "\t\tl2i"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_l2i; | |
} | |
final public void ladd() { | |
if (DEBUG) System.out.println(position + "\t\tladd"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ladd; | |
} | |
final public void laload() { | |
if (DEBUG) System.out.println(position + "\t\tlaload"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_laload; | |
} | |
final public void land() { | |
if (DEBUG) System.out.println(position + "\t\tland"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_land; | |
} | |
final public void lastore() { | |
if (DEBUG) System.out.println(position + "\t\tlastore"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 4; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lastore; | |
} | |
final public void lcmp() { | |
if (DEBUG) System.out.println(position + "\t\tlcmp"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 3; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lcmp; | |
} | |
final public void lconst_0() { | |
if (DEBUG) System.out.println(position + "\t\tlconst_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lconst_0; | |
} | |
final public void lconst_1() { | |
if (DEBUG) System.out.println(position + "\t\tlconst_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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) { | |
if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$ | |
// Generate a ldc_w | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
writeUnsignedShort(index); | |
} else { | |
if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$ | |
// Generate a ldc | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
bCodeStream[classFileOffset++] = (byte) index; | |
} | |
} | |
final public void ldc(int constant) { | |
countLabels = 0; | |
int index = constantPool.literalIndex(constant); | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (index > 255) { | |
if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$ | |
// Generate a ldc_w | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
writeUnsignedShort(index); | |
} else { | |
if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$ | |
// Generate a ldc | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
bCodeStream[classFileOffset++] = (byte) 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) { | |
if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$ | |
// Generate a ldc_w | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
writeUnsignedShort(index); | |
} else { | |
if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$ | |
// Generate a ldc | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
bCodeStream[classFileOffset++] = (byte) 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 | |
newStringContatenation(); | |
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 | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
writeUnsignedShort(index); | |
} else { | |
// Generate a ldc | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
bCodeStream[classFileOffset++] = (byte) index; | |
} | |
// write the remaining part | |
invokeStringConcatenationStringConstructor(); | |
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 | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
writeUnsignedShort(index); | |
} else { | |
// Generate a ldc | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
bCodeStream[classFileOffset++] = (byte) index; | |
} | |
// now on the stack it should be a StringBuffer and a string. | |
invokeStringConcatenationAppendForType(T_String); | |
} | |
invokeStringConcatenationToString(); | |
invokeStringIntern(); | |
} | |
} | |
final public void ldc(TypeBinding typeBinding) { | |
countLabels = 0; | |
int index = constantPool.literalIndex(typeBinding); | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (index > 255) { | |
if (DEBUG) System.out.println(position + "\t\tldc_w:"+ typeBinding); //$NON-NLS-1$ | |
// Generate a ldc_w | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc_w; | |
writeUnsignedShort(index); | |
} else { | |
if (DEBUG) System.out.println(position + "\t\tldw:"+ typeBinding); //$NON-NLS-1$ | |
// Generate a ldc | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_ldc; | |
bCodeStream[classFileOffset++] = (byte) index; | |
} | |
} | |
final public void ldc2_w(double constant) { | |
if (DEBUG) System.out.println(position + "\t\tldc2_w:"+constant); //$NON-NLS-1$ | |
countLabels = 0; | |
int index = constantPool.literalIndex(constant); | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
// Generate a ldc2_w | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc2_w; | |
writeUnsignedShort(index); | |
} | |
final public void ldc2_w(long constant) { | |
if (DEBUG) System.out.println(position + "\t\tldc2_w:"+constant); //$NON-NLS-1$ | |
countLabels = 0; | |
int index = constantPool.literalIndex(constant); | |
stackDepth += 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
// Generate a ldc2_w | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldc2_w; | |
writeUnsignedShort(index); | |
} | |
final public void ldiv() { | |
if (DEBUG) System.out.println(position + "\t\tldiv"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_ldiv; | |
} | |
final public void lload(int iArg) { | |
if (DEBUG) System.out.println(position + "\t\tlload:"+iArg); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals <= iArg + 1) { | |
maxLocals = iArg + 2; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (iArg > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_lload; | |
writeUnsignedShort(iArg); | |
} else { | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_lload; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void lload_0() { | |
if (DEBUG) System.out.println(position + "\t\tlload_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals < 2) { | |
maxLocals = 2; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload_0; | |
} | |
final public void lload_1() { | |
if (DEBUG) System.out.println(position + "\t\tlload_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals < 3) { | |
maxLocals = 3; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload_1; | |
} | |
final public void lload_2() { | |
if (DEBUG) System.out.println(position + "\t\tlload_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals < 4) { | |
maxLocals = 4; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload_2; | |
} | |
final public void lload_3() { | |
if (DEBUG) System.out.println(position + "\t\tlload_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth += 2; | |
if (maxLocals < 5) { | |
maxLocals = 5; | |
} | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lload_3; | |
} | |
final public void lmul() { | |
if (DEBUG) System.out.println(position + "\t\tlmul"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lmul; | |
} | |
final public void lneg() { | |
if (DEBUG) System.out.println(position + "\t\tlneg"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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; | |
//case -1 : | |
// internal failure: trying to load variable not supposed to be generated | |
// 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) { | |
if (DEBUG) System.out.println(position + "\t\tlookupswitch"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
int length = keys.length; | |
int pos = position; | |
defaultLabel.placeInstruction(); | |
for (int i = 0; i < length; i++) { | |
casesLabel[i].placeInstruction(); | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lookupswitch; | |
for (int i = (3 - (pos % 4)); i > 0; i--) { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 0; | |
} | |
defaultLabel.branch(); | |
writeSignedWord(length); | |
for (int i = 0; i < length; i++) { | |
writeSignedWord(keys[sortedIndexes[i]]); | |
casesLabel[sortedIndexes[i]].branch(); | |
} | |
} | |
final public void lor() { | |
if (DEBUG) System.out.println(position + "\t\tlor"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lor; | |
} | |
final public void lrem() { | |
if (DEBUG) System.out.println(position + "\t\tlrem"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lrem; | |
} | |
final public void lreturn() { | |
if (DEBUG) System.out.println(position + "\t\tlreturn"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
// the stackDepth should be equal to 0 | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lreturn; | |
} | |
final public void lshl() { | |
if (DEBUG) System.out.println(position + "\t\tlshl"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lshl; | |
} | |
final public void lshr() { | |
if (DEBUG) System.out.println(position + "\t\tlshr"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lshr; | |
} | |
final public void lstore(int iArg) { | |
if (DEBUG) System.out.println(position + "\t\tlstore:"+iArg); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals <= iArg + 1) { | |
maxLocals = iArg + 2; | |
} | |
if (iArg > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_lstore; | |
writeUnsignedShort(iArg); | |
} else { | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_lstore; | |
bCodeStream[classFileOffset++] = (byte) iArg; | |
} | |
} | |
final public void lstore_0() { | |
if (DEBUG) System.out.println(position + "\t\tlstore_0"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 2) { | |
maxLocals = 2; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore_0; | |
} | |
final public void lstore_1() { | |
if (DEBUG) System.out.println(position + "\t\tlstore_1"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 3) { | |
maxLocals = 3; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore_1; | |
} | |
final public void lstore_2() { | |
if (DEBUG) System.out.println(position + "\t\tlstore_2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 4) { | |
maxLocals = 4; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore_2; | |
} | |
final public void lstore_3() { | |
if (DEBUG) System.out.println(position + "\t\tlstore_3"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (maxLocals < 5) { | |
maxLocals = 5; | |
} | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lstore_3; | |
} | |
final public void lsub() { | |
if (DEBUG) System.out.println(position + "\t\tlsub"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lsub; | |
} | |
final public void lushr() { | |
if (DEBUG) System.out.println(position + "\t\tlushr"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lushr; | |
} | |
final public void lxor() { | |
if (DEBUG) System.out.println(position + "\t\tlxor"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_lxor; | |
} | |
final public void monitorenter() { | |
if (DEBUG) System.out.println(position + "\t\tmonitorenter"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_monitorenter; | |
} | |
final public void monitorexit() { | |
if (DEBUG) System.out.println(position + "\t\tmonitorexit"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_monitorexit; | |
} | |
final public void multianewarray(TypeBinding typeBinding, int dimensions) { | |
if (DEBUG) System.out.println(position + "\t\tmultinewarray:"+typeBinding+","+dimensions); //$NON-NLS-1$ //$NON-NLS-2$ | |
countLabels = 0; | |
stackDepth += (1 - dimensions); | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_multianewarray; | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
bCodeStream[classFileOffset++] = (byte) dimensions; | |
} | |
/** | |
* We didn't call it new, because there is a conflit with the new keyword | |
*/ | |
final public void new_(TypeBinding typeBinding) { | |
if (DEBUG) System.out.println(position + "\t\tnew:"+typeBinding); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
writeUnsignedShort(constantPool.literalIndex(typeBinding)); | |
} | |
final public void newarray(int array_Type) { | |
if (DEBUG) System.out.println(position + "\t\tnewarray:"+array_Type); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_newarray; | |
bCodeStream[classFileOffset++] = (byte) array_Type; | |
} | |
public void newArray(Scope scope, ArrayBinding arrayBinding) { | |
TypeBinding component = arrayBinding.elementsType(); | |
switch (component.id) { | |
case T_int : | |
this.newarray(INT_ARRAY); | |
break; | |
case T_byte : | |
this.newarray(BYTE_ARRAY); | |
break; | |
case T_boolean : | |
this.newarray(BOOLEAN_ARRAY); | |
break; | |
case T_short : | |
this.newarray(SHORT_ARRAY); | |
break; | |
case T_char : | |
this.newarray(CHAR_ARRAY); | |
break; | |
case T_long : | |
this.newarray(LONG_ARRAY); | |
break; | |
case T_float : | |
this.newarray(FLOAT_ARRAY); | |
break; | |
case T_double : | |
this.newarray(DOUBLE_ARRAY); | |
break; | |
default : | |
this.anewarray(component); | |
} | |
} | |
public void newJavaLangError() { | |
// new: java.lang.Error | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Error"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangError()); | |
} | |
public void newJavaLangAssertionError() { | |
// new: java.lang.AssertionError | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.AssertionError"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionError()); | |
} | |
public void newNoClassDefFoundError() { | |
// new: java.lang.NoClassDefFoundError | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.NoClassDefFoundError"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundError()); | |
} | |
public void newStringContatenation() { | |
// new: java.lang.StringBuffer | |
// new: java.lang.StringBuilder | |
if (DEBUG) { | |
if (this.targetLevel >= JDK1_5) { | |
System.out.println(position + "\t\tnew: java.lang.StringBuilder"); //$NON-NLS-1$ | |
} else { | |
System.out.println(position + "\t\tnew: java.lang.StringBuffer"); //$NON-NLS-1$ | |
} | |
} | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) { | |
stackMax = stackDepth; | |
} | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
if (this.targetLevel >= JDK1_5) { | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuilder()); | |
} else { | |
writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuffer()); | |
} | |
} | |
public void newWrapperFor(int typeID) { | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_new; | |
switch (typeID) { | |
case T_int : // new: java.lang.Integer | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Integer"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangInteger()); | |
break; | |
case T_boolean : // new: java.lang.Boolean | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Boolean"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean()); | |
break; | |
case T_byte : // new: java.lang.Byte | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Byte"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangByte()); | |
break; | |
case T_char : // new: java.lang.Character | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Character"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter()); | |
break; | |
case T_float : // new: java.lang.Float | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Float"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangFloat()); | |
break; | |
case T_double : // new: java.lang.Double | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Double"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangDouble()); | |
break; | |
case T_short : // new: java.lang.Short | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Short"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangShort()); | |
break; | |
case T_long : // new: java.lang.Long | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Long"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangLong()); | |
break; | |
case T_void : // new: java.lang.Void | |
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Void"); //$NON-NLS-1$ | |
writeUnsignedShort(constantPool.literalIndexForJavaLangVoid()); | |
} | |
} | |
final public void nop() { | |
if (DEBUG) System.out.println(position + "\t\tnop"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_nop; | |
} | |
final public void pop() { | |
if (DEBUG) System.out.println(position + "\t\tpop"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_pop; | |
} | |
final public void pop2() { | |
if (DEBUG) System.out.println(position + "\t\tpop2"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 2; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_pop2; | |
} | |
final public void putfield(FieldBinding fieldBinding) { | |
if (DEBUG) System.out.println(position + "\t\tputfield:"+fieldBinding); //$NON-NLS-1$ | |
countLabels = 0; | |
int id; | |
if (((id = fieldBinding.type.id) == T_double) || (id == T_long)) | |
stackDepth -= 3; | |
else | |
stackDepth -= 2; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_putfield; | |
writeUnsignedShort(constantPool.literalIndex(fieldBinding)); | |
} | |
final public void putstatic(FieldBinding fieldBinding) { | |
if (DEBUG) System.out.println(position + "\t\tputstatic:"+fieldBinding); //$NON-NLS-1$ | |
countLabels = 0; | |
int id; | |
if (((id = fieldBinding.type.id) == T_double) || (id == T_long)) | |
stackDepth -= 2; | |
else | |
stackDepth -= 1; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset + 2 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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 if (insertionIndex < 1 || pcToSourceMap[insertionIndex - 1] != newLine) { | |
// 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; | |
} | |
} else 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 | |
/* First we need to check if at the insertion position there is not an existing entry | |
* that includes the one we want to insert. This is the case if pcToSourceMap[insertionIndex - 1] == newLine. | |
* In this case we don't want to change the table. If not, we want to insert a new entry. Prior to insertion | |
* we want to check if it is worth doing an arraycopy. If not we simply update the recorded pc. | |
*/ | |
if (!((insertionIndex > 1) && (pcToSourceMap[insertionIndex - 1] == newLine))) { | |
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.wst.jsdt.internal.compiler.codegen.ExceptionLabel | |
*/ | |
public void registerExceptionHandler(ExceptionLabel anExceptionLabel) { | |
int length; | |
if (exceptionHandlersIndex >= (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[exceptionHandlersIndex++] = anExceptionLabel; | |
exceptionHandlersCounter++; | |
} | |
public void removeExceptionHandler(ExceptionLabel exceptionLabel) { | |
for (int i = 0; i < exceptionHandlersIndex; i++) { | |
if (exceptionHandlers[i] == exceptionLabel) { | |
exceptionHandlers[i] = null; | |
exceptionHandlersCounter--; | |
return; | |
} | |
} | |
} | |
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 referenceMethod org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration | |
* @param targetClassFile org.eclipse.wst.jsdt.internal.compiler.codegen.ClassFile | |
*/ | |
public void reset(AbstractMethodDeclaration referenceMethod, ClassFile targetClassFile) { | |
init(targetClassFile); | |
this.methodDeclaration = referenceMethod; | |
preserveUnusedLocals = referenceMethod.scope.problemReporter().options.preserveAllLocalVariables; | |
initializeMaxLocals(referenceMethod.binding); | |
} | |
/** | |
* @param targetClassFile The given classfile to reset the code stream | |
*/ | |
public void resetForProblemClinit(ClassFile targetClassFile) { | |
init(targetClassFile); | |
maxLocals = 0; | |
} | |
private final void resizeByteArray() { | |
int length = bCodeStream.length; | |
int requiredSize = length + length; | |
if (classFileOffset > requiredSize) { | |
// must be sure to grow by enough | |
requiredSize = classFileOffset + length; | |
} | |
System.arraycopy(bCodeStream, 0, bCodeStream = new byte[requiredSize], 0, length); | |
} | |
final public void ret(int index) { | |
if (DEBUG) System.out.println(position + "\t\tret:"+index); //$NON-NLS-1$ | |
countLabels = 0; | |
if (index > 255) { // Widen | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_wide; | |
bCodeStream[classFileOffset++] = OPC_ret; | |
writeUnsignedShort(index); | |
} else { // Don't Widen | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = OPC_ret; | |
bCodeStream[classFileOffset++] = (byte) index; | |
} | |
} | |
final public void return_() { | |
if (DEBUG) System.out.println(position + "\t\treturn"); //$NON-NLS-1$ | |
countLabels = 0; | |
// the stackDepth should be equal to 0 | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_return; | |
} | |
final public void saload() { | |
if (DEBUG) System.out.println(position + "\t\tsaload"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_saload; | |
} | |
final public void sastore() { | |
if (DEBUG) System.out.println(position + "\t\tsastore"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth -= 3; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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) { | |
if (DEBUG) System.out.println(position + "\t\tsipush:"+s); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth++; | |
if (stackDepth > stackMax) | |
stackMax = stackDepth; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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) { | |
int localPosition = localBinding.resolvedPosition; | |
// Using dedicated int bytecode | |
switch(localBinding.type.id) { | |
case TypeIds.T_int : | |
case TypeIds.T_char : | |
case TypeIds.T_byte : | |
case TypeIds.T_short : | |
case TypeIds.T_boolean : | |
if (valueRequired) | |
this.dup(); | |
switch (localPosition) { | |
case 0 : | |
this.istore_0(); | |
break; | |
case 1 : | |
this.istore_1(); | |
break; | |
case 2 : | |
this.istore_2(); | |
break; | |
case 3 : | |
this.istore_3(); | |
break; | |
//case -1 : | |
// internal failure: trying to store into variable not supposed to be generated | |
// break; | |
default : | |
this.istore(localPosition); | |
} | |
break; | |
case TypeIds.T_float : | |
if (valueRequired) | |
this.dup(); | |
switch (localPosition) { | |
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(localPosition); | |
} | |
break; | |
case TypeIds.T_double : | |
if (valueRequired) | |
this.dup2(); | |
switch (localPosition) { | |
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(localPosition); | |
} | |
break; | |
case TypeIds.T_long : | |
if (valueRequired) | |
this.dup2(); | |
switch (localPosition) { | |
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(localPosition); | |
} | |
break; | |
default: | |
// Reference object | |
if (valueRequired) | |
this.dup(); | |
switch (localPosition) { | |
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(localPosition); | |
} | |
} | |
} | |
public final void store(TypeBinding type, int localPosition) { | |
// Using dedicated int bytecode | |
if ((type == IntBinding) || (type == CharBinding) || (type == ByteBinding) || (type == ShortBinding) || (type == BooleanBinding)) { | |
switch (localPosition) { | |
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(localPosition); | |
} | |
return; | |
} | |
// Using dedicated float bytecode | |
if (type == FloatBinding) { | |
switch (localPosition) { | |
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(localPosition); | |
} | |
return; | |
} | |
// Using dedicated long bytecode | |
if (type == LongBinding) { | |
switch (localPosition) { | |
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(localPosition); | |
} | |
return; | |
} | |
// Using dedicated double bytecode | |
if (type == DoubleBinding) { | |
switch (localPosition) { | |
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(localPosition); | |
} | |
return; | |
} | |
// Reference object | |
switch (localPosition) { | |
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(localPosition); | |
} | |
} | |
public final void storeInt(int localPosition) { | |
switch (localPosition) { | |
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(localPosition); | |
} | |
} | |
public final void storeObject(int localPosition) { | |
switch (localPosition) { | |
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(localPosition); | |
} | |
} | |
final public void swap() { | |
if (DEBUG) System.out.println(position + "\t\tswap"); //$NON-NLS-1$ | |
countLabels = 0; | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 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) { | |
if (DEBUG) System.out.println(position + "\t\ttableswitch"); //$NON-NLS-1$ | |
countLabels = 0; | |
stackDepth--; | |
int length = casesLabel.length; | |
int pos = position; | |
defaultLabel.placeInstruction(); | |
for (int i = 0; i < length; i++) | |
casesLabel[i].placeInstruction(); | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = OPC_tableswitch; | |
for (int i = (3 - (pos % 4)); i > 0; i--) { | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = 0; | |
} | |
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; | |
this.lastEntryPC = pos; | |
// 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; | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Write a signed 16 bits value into the byte array | |
* @param value the signed short | |
*/ | |
public final void writeSignedShort(int value) { | |
// we keep the resize in here because it is used outside the code stream | |
if (classFileOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 2; | |
bCodeStream[classFileOffset++] = (byte) (value >> 8); | |
bCodeStream[classFileOffset++] = (byte) value; | |
} | |
public final void writeSignedShort(int pos, int value) { | |
int currentOffset = startingClassFileOffset + pos; | |
if (currentOffset + 1 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
bCodeStream[currentOffset] = (byte) (value >> 8); | |
bCodeStream[currentOffset + 1] = (byte) value; | |
} | |
public final void writeSignedWord(int value) { | |
// we keep the resize in here because it is used outside the code stream | |
if (classFileOffset + 3 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position += 4; | |
bCodeStream[classFileOffset++] = (byte) ((value & 0xFF000000) >> 24); | |
bCodeStream[classFileOffset++] = (byte) ((value & 0xFF0000) >> 16); | |
bCodeStream[classFileOffset++] = (byte) ((value & 0xFF00) >> 8); | |
bCodeStream[classFileOffset++] = (byte) (value & 0xFF); | |
} | |
public final void writeSignedWord(int pos, int value) { | |
int currentOffset = startingClassFileOffset + pos; | |
if (currentOffset + 4 >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
bCodeStream[currentOffset++] = (byte) ((value & 0xFF000000) >> 24); | |
bCodeStream[currentOffset++] = (byte) ((value & 0xFF0000) >> 16); | |
bCodeStream[currentOffset++] = (byte) ((value & 0xFF00) >> 8); | |
bCodeStream[currentOffset++] = (byte) (value & 0xFF); | |
} | |
/** | |
* Write a unsigned 16 bits value into the byte array | |
* @param value the unsigned short | |
*/ | |
protected final void writeUnsignedShort(int value) { | |
position += 2; | |
bCodeStream[classFileOffset++] = (byte) (value >>> 8); | |
bCodeStream[classFileOffset++] = (byte) value; | |
} | |
/* | |
* Wide conditional branch compare, improved by swapping comparison opcode | |
* ifeq WideTarget | |
* becomes | |
* ifne Intermediate | |
* gotow WideTarget | |
* Intermediate: | |
*/ | |
public void generateWideRevertedConditionalBranch(byte revertedOpcode, Label wideTarget) { | |
Label intermediate = new Label(this); | |
if (classFileOffset >= bCodeStream.length) { | |
resizeByteArray(); | |
} | |
position++; | |
bCodeStream[classFileOffset++] = revertedOpcode; | |
intermediate.branch(); | |
this.goto_w(wideTarget); | |
intermediate.place(); | |
} | |
} |