Index: compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java,v retrieving revision 1.52 diff -u -r1.52 SwitchStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java 28 Feb 2005 06:36:20 -0000 1.52 +++ compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java 9 Mar 2005 02:27:58 -0000 @@ -163,6 +163,7 @@ // generate the switch block statements int caseIndex = 0; + int pcBeforeLastStatement = codeStream.position; if (this.statements != null) { for (int i = 0, maxCases = this.statements.length; i < maxCases; i++) { Statement statement = this.statements[i]; @@ -180,13 +181,19 @@ } } } + pcBeforeLastStatement = codeStream.position; statement.generateCode(scope, codeStream); } } // place the trailing labels (for break and default case) + int pcToSourceMapSize = codeStream.pcToSourceMapSize; this.breakLabel.place(); if (defaultCase == null) { defaultLabel.place(); + } + if (pcToSourceMapSize != codeStream.pcToSourceMapSize) { + // optimize goto next bytecode + codeStream.recordPositionsFrom(pcBeforeLastStatement, this.sourceEnd, true); } // May loose some local variable initializations : affecting the local variable attributes if (mergedInitStateIndex != -1) { Index: compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java =================================================================== RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java,v retrieving revision 1.103 diff -u -r1.103 CodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 23 Feb 2005 02:47:47 -0000 1.103 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 9 Mar 2005 02:28:00 -0000 @@ -5364,6 +5364,103 @@ lastEntryPC = position; } } +public void recordPositionsFrom(int startPC, int sourcePos, boolean alwaysInsert) { + + /* 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 (!alwaysInsert && 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.jdt.internal.compiler.codegen.ExceptionLabel */