/*******************************************************************************
* Copyright (c) 2000, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.ext.java.jdt.internal.compiler.codegen;
public class BranchLabel extends Label {
private int[] forwardReferences = new int[10]; // Add an overflow check here.
private int forwardReferenceCount = 0;
BranchLabel delegate; //
public final static int USED = 2;
// Label tagbits
public int tagBits;
public BranchLabel() {
// for creating labels ahead of code generation
}
/** Makes the current label inline all references to the other label */
public void becomeDelegateFor(BranchLabel otherLabel) {
// other label is delegating to receiver from now on
otherLabel.delegate = this;
// all existing forward refs to other label are inlined into current label
final int otherCount = otherLabel.forwardReferenceCount;
if (otherCount == 0)
return;
// need to merge the two sorted arrays of forward references
int[] mergedForwardReferences = new int[this.forwardReferenceCount + otherCount];
int indexInMerge = 0;
int j = 0;
int i = 0;
int max = this.forwardReferenceCount;
int max2 = otherLabel.forwardReferenceCount;
loop1:
for (; i < max; i++) {
final int value1 = this.forwardReferences[i];
for (; j < max2; j++) {
final int value2 = otherLabel.forwardReferences[j];
if (value1 < value2) {
mergedForwardReferences[indexInMerge++] = value1;
continue loop1;
} else if (value1 == value2) {
mergedForwardReferences[indexInMerge++] = value1;
j++;
continue loop1;
} else {
mergedForwardReferences[indexInMerge++] = value2;
}
}
mergedForwardReferences[indexInMerge++] = value1;
}
for (; j < max2; j++) {
mergedForwardReferences[indexInMerge++] = otherLabel.forwardReferences[j];
}
this.forwardReferences = mergedForwardReferences;
this.forwardReferenceCount = indexInMerge;
}
// /*
// * Put down a reference to the array at the location in the codestream.
// */
// void branch()
// {
// this.tagBits |= BranchLabel.USED;
// if (this.delegate != null)
// {
// this.delegate.branch();
// return;
// }
// if (this.position == Label.POS_NOT_SET)
// {
// addForwardReference(this.codeStream.position);
// // Leave two bytes free to generate the jump afterwards
// this.codeStream.position += 2;
// this.codeStream.classFileOffset += 2;
// }
// else
// {
// /*
// * Position is set. Write it if it is not a wide branch.
// */
// this.codeStream.writePosition(this);
// }
// }
// /*
// * No support for wide branches yet
// */
// void branchWide()
// {
// this.tagBits |= BranchLabel.USED;
// if (this.delegate != null)
// {
// this.delegate.branchWide();
// return;
// }
// if (this.position == Label.POS_NOT_SET)
// {
// addForwardReference(this.codeStream.position);
// // Leave 4 bytes free to generate the jump offset afterwards
// this.tagBits |= BranchLabel.WIDE;
// this.codeStream.position += 4;
// this.codeStream.classFileOffset += 4;
// }
// else
// { //Position is set. Write it!
// this.codeStream.writeWidePosition(this);
// }
// }
public int forwardReferenceCount() {
if (this.delegate != null)
this.delegate.forwardReferenceCount();
return this.forwardReferenceCount;
}
public int[] forwardReferences() {
if (this.delegate != null)
this.delegate.forwardReferences();
return this.forwardReferences;
}
// public void initialize(CodeStream stream)
// {
// this.codeStream = stream;
// this.position = Label.POS_NOT_SET;
// this.forwardReferenceCount = 0;
// this.delegate = null;
// }
public boolean isCaseLabel() {
return false;
}
public boolean isStandardLabel() {
return true;
}
// /*
// * Place the label. If we have forward references resolve them.
// */
// public void place()
// { // Currently lacking wide support.
// // if ((this.tagBits & USED) == 0 && this.forwardReferenceCount == 0) {
// // return;
// // }
//
// //TODO how can position be set already ? cannot place more than once
// if (this.position == Label.POS_NOT_SET)
// {
// this.position = this.codeStream.position;
// this.codeStream.addLabel(this);
// int oldPosition = this.position;
// boolean isOptimizedBranch = false;
// if (this.forwardReferenceCount != 0)
// {
// isOptimizedBranch =
// (this.forwardReferences[this.forwardReferenceCount - 1] + 2 == this.position)
// && (this.codeStream.bCodeStream[this.codeStream.classFileOffset - 3] == Opcodes.OPC_goto);
// if (isOptimizedBranch)
// {
// if (this.codeStream.lastAbruptCompletion == this.position)
// {
// this.codeStream.lastAbruptCompletion = -1;
// }
// this.codeStream.position = (this.position -= 3);
// this.codeStream.classFileOffset -= 3;
// this.forwardReferenceCount--;
// if (this.codeStream.lastEntryPC == oldPosition)
// {
// this.codeStream.lastEntryPC = this.position;
// }
// // end of new code
// if ((this.codeStream.generateAttributes & (ClassFileConstants.ATTR_VARS
// | ClassFileConstants.ATTR_STACK_MAP_TABLE | ClassFileConstants.ATTR_STACK_MAP)) != 0)
// {
// LocalVariableBinding locals[] = this.codeStream.locals;
// 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] == oldPosition)
// {
// // we want to prevent interval of size 0 to have a negative size.
// // see PR 1GIRQLA: ITPJCORE:ALL - ClassFormatError for local variable attribute
// local.initializationPCs[((local.initializationCount - 1) << 1) + 1] = this.position;
// }
// if (local.initializationPCs[(local.initializationCount - 1) << 1] == oldPosition)
// {
// local.initializationPCs[(local.initializationCount - 1) << 1] = this.position;
// }
// }
// }
// }
// if ((this.codeStream.generateAttributes & ClassFileConstants.ATTR_LINES) != 0)
// {
// // we need to remove all entries that is beyond this.position inside the pcToSourcerMap table
// this.codeStream.removeUnusedPcToSourceMapEntries();
// }
// }
// }
// for (int i = 0; i < this.forwardReferenceCount; i++)
// {
// this.codeStream.writePosition(this, this.forwardReferences[i]);
// }
// // For all labels placed at that position we check if we need to rewrite the jump
// // offset. It is the case each time a label had a forward reference to the current position.
// // Like we change the current position, we have to change the jump offset. See 1F4IRD9 for more details.
// if (isOptimizedBranch)
// {
// this.codeStream.optimizeBranch(oldPosition, this);
// }
// }
// }
/** Print out the receiver */
public String toString() {
String basic = getClass().getName();
basic = basic.substring(basic.lastIndexOf('.') + 1);
StringBuilder buffer = new StringBuilder(basic);
buffer.append('@').append(Integer.toHexString(hashCode()));
buffer.append("(position=").append(this.position); //$NON-NLS-1$
if (this.delegate != null)
buffer.append("delegate=").append(this.delegate); //$NON-NLS-1$
buffer.append(", forwards = ["); //$NON-NLS-1$
for (int i : forwardReferences) {
buffer.append(forwardReferences[i] + ", "); //$NON-NLS-1$
}
buffer.deleteCharAt(buffer.length() - 1).deleteCharAt(buffer.length() - 1).append("] )"); //$NON-NLS-1$
return buffer.toString();
}
}