/******************************************************************************* * 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(); } }