Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Patch for Scanner performance


Here is a patch that addresses some issues with the scanner that I found using a performance profiler.

A full scan of "w32api/windows.h" dropped by 30% with these changes.  

Here are some of the numbers before and after the patch

Before
        Scan:  2.2 s
        Scan + parse: 5.2 s

After
        Scan: 1.5 s
        Scan + parse: 4.4 s

Note that there are about 100,000 tokens read in the test!

For comparison, a scan + parse of stdio.h takes about 150ms.

        - Dave

Index: parser/org/eclipse/cdt/internal/core/parser/scanner/GCCScannerExtension.java
===================================================================
retrieving revision 1.5
diff -u -r1.5 GCCScannerExtension.java
--- parser/org/eclipse/cdt/internal/core/parser/scanner/GCCScannerExtension.java	11 Mar 2004 20:47:34 -0000	1.5
+++ parser/org/eclipse/cdt/internal/core/parser/scanner/GCCScannerExtension.java	16 Mar 2004 16:54:39 -0000
@@ -83,7 +83,8 @@
 			scannerData.getLogService().traceLog( "GCCScannerExtension handling #include_next directive" ); //$NON-NLS-1$
 			// figure out the name of the current file and its path
 			IScannerContext context = scannerData.getContextStack().getCurrentContext();
-			if( context.getKind() != IScannerContext.ContextKind.INCLUSION ) 
+//	There are times where context is null		
+//			if( context.getKind() != IScannerContext.ContextKind.INCLUSION ) 
 			{
 				//handle appropriate error
 			}
Index: parser/org/eclipse/cdt/internal/core/parser/scanner/Scanner.java
===================================================================
retrieving revision 1.22
diff -u -r1.22 Scanner.java
--- parser/org/eclipse/cdt/internal/core/parser/scanner/Scanner.java	11 Mar 2004 20:47:34 -0000	1.22
+++ parser/org/eclipse/cdt/internal/core/parser/scanner/Scanner.java	16 Mar 2004 16:54:41 -0000
@@ -721,7 +721,7 @@
 		return getChar();
 	}
 	
-	int getChar() throws ScannerException
+	final int getChar() throws ScannerException
 	{
 		return getChar( false );
 	}
@@ -731,12 +731,14 @@
 		
 		lastContext = scannerData.getContextStack().getCurrentContext();
 		
-		if (scannerData.getContextStack().getCurrentContext() == null)
+		if (lastContext == null)
 			// past the end of file
 			return c;
 
-        c = accountForUndo(c);
-    	int baseOffset = lastContext.getOffset() - lastContext.undoStackSize() - 1;
+       	if (lastContext.undoStackSize() != 0 )
+    		c = lastContext.popUndo();
+    	else
+    		c = readFromStream();
 		
 		if (enableTrigraphReplacement && (!insideString || enableTrigraphReplacementInStrings)) {
 			// Trigraph processing
@@ -747,39 +749,39 @@
 					c = getChar(insideString);
 					switch (c) {
 						case '(':
-							expandDefinition("??(", "[", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+							expandDefinition("??(", "[", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 							c = getChar(insideString);
 							break;
 						case ')':
-							expandDefinition("??)", "]", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+							expandDefinition("??)", "]", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 							c = getChar(insideString);
 							break;
 						case '<':
-							expandDefinition("??<", "{", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+							expandDefinition("??<", "{", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 							c = getChar(insideString);
 							break;
 						case '>':
-							expandDefinition("??>", "}", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+							expandDefinition("??>", "}", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 							c = getChar(insideString);
 							break;
 						case '=':
-							expandDefinition("??=", "#", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+							expandDefinition("??=", "#", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 							c = getChar(insideString);
 							break;
 						case '/':
-							expandDefinition("??/", "\\", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+							expandDefinition("??/", "\\", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 							c = getChar(insideString);
 							break;
 						case '\'':
-							expandDefinition("??\'", "^", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+							expandDefinition("??\'", "^", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 							c = getChar(insideString);
 							break;
 						case '!':
-							expandDefinition("??!", "|", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+							expandDefinition("??!", "|", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 							c = getChar(insideString);
 							break;
 						case '-':
-							expandDefinition("??-", "~", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+							expandDefinition("??-", "~", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 							c = getChar(insideString);
 							break;
 						default:
@@ -805,10 +807,10 @@
 				if (c == '<') {
 					c = getChar(false);
 					if (c == '%') {
-						expandDefinition("<%", "{", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+						expandDefinition("<%", "{", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 						c = getChar(false);
 					} else if (c == ':') {
-						expandDefinition("<:", "[", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+						expandDefinition("<:", "[", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 						c = getChar(false);
 					} else {
 						// Not a digraph
@@ -818,7 +820,7 @@
 				} else if (c == ':') {
 					c = getChar(false);
 					if (c == '>') {
-						expandDefinition(":>", "]", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+						expandDefinition(":>", "]", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 						c = getChar(false);
 					} else {
 						// Not a digraph
@@ -828,10 +830,10 @@
 				} else if (c == '%') {
 					c = getChar(false);
 					if (c == '>') {
-						expandDefinition("%>", "}", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+						expandDefinition("%>", "}", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 						c = getChar(false);
 					} else if (c == ':') {
-						expandDefinition("%:", "#", baseOffset); //$NON-NLS-1$ //$NON-NLS-2$
+						expandDefinition("%:", "#", lastContext.getOffset() - lastContext.undoStackSize() - 1); //$NON-NLS-1$ //$NON-NLS-2$
 						c = getChar(false);
 					} else {
 						// Not a digraph
@@ -845,38 +847,29 @@
 		return c;
 	}
 
-    protected int accountForUndo(int c)
+    protected int readFromStream()
     {
-        boolean done;
-        do {
-        	done = true;
-        
-        	if (scannerData.getContextStack().getCurrentContext().undoStackSize() != 0 ) {
-        		c = scannerData.getContextStack().getCurrentContext().popUndo();
-        	} else {
-        		try {
-        			c = scannerData.getContextStack().getCurrentContext().read();
-        			if (c == NOCHAR) {
-        				if (scannerData.getContextStack().rollbackContext(scannerData.getClientRequestor()) == false) {
-        					c = NOCHAR;
-        					break;
-        				} else {
-        					done = false;
-        				}
-        			}
-        		} catch (IOException e) {
-        			if (scannerData.getContextStack().rollbackContext(scannerData.getClientRequestor()) == false) {
-        				c = NOCHAR;
-        			} else {
-        				done = false;
-        			}
-        		}
-        	}
-        } while (!done);
-        return c;
+    	int c;
+    	try {
+    		c = scannerData.getContextStack().getCurrentContext().read();
+    	}
+    	catch (IOException e) {
+    		c = NOCHAR;
+    	}
+    	
+    	if (c != NOCHAR)
+    		return c;
+    	
+    	if (scannerData.getContextStack().rollbackContext(scannerData.getClientRequestor()) == false)
+    		return NOCHAR;
+    	
+    	if (scannerData.getContextStack().getCurrentContext().undoStackSize() != 0 )
+    		return scannerData.getContextStack().getCurrentContext().popUndo();
+    	
+    	return readFromStream();
     }
 
-	void ungetChar(int c) throws ScannerException{
+	final void ungetChar(int c) throws ScannerException{
 		scannerData.getContextStack().getCurrentContext().pushUndo(c);
 		try
 		{
@@ -1220,9 +1213,12 @@
 		if (directive == null) {
 			if( scannerExtension.canHandlePreprocessorDirective( token ) )
 				scannerExtension.handlePreprocessorDirective( token, getRestOfPreprocessorLine() );
-			StringBuffer buffer = new StringBuffer( "#"); //$NON-NLS-1$
-			buffer.append( token );
-			handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, buffer.toString(), beginningOffset, false, true );
+			else
+			{
+				StringBuffer buffer = new StringBuffer( "#"); //$NON-NLS-1$
+				buffer.append( token );
+				handleProblem( IProblem.PREPROCESSOR_INVALID_DIRECTIVE, buffer.toString(), beginningOffset, false, true );
+			}
 			return null;
 		}
 
@@ -1432,12 +1428,12 @@
 
 		c = getChar();				
 		
+		// do the least expensive tests first!
 		while (
-				Character.isUnicodeIdentifierPart( (char)c)
-//			((c >= 'a') && (c <= 'z'))
-//			|| ((c >= 'A') && (c <= 'Z'))
-//			|| ((c >= '0') && (c <= '9'))
-//			|| (c == '_')
+			((c >= 'a') && (c <= 'z'))
+			|| ((c >= 'A') && (c <= 'Z'))
+			|| ((c >= '0') && (c <= '9'))
+			|| (c == '_') || Character.isUnicodeIdentifierPart( (char)c)
 			) {
 			buff.append((char) c);
 			c = getChar();
@@ -2545,7 +2541,37 @@
 		return macroReplacementTokens;
 	}
 	
+	protected IMacroDescriptor createObjectMacroDescriptor(String key, String value ) {
+		StringBuffer signatureBuffer  = new StringBuffer();
+		signatureBuffer.append( key );
+		signatureBuffer.append( ' ' );
+		signatureBuffer.append( value );
+
+//		List macroReplacementTokens;
+//		if (value.trim().equals( "" ))
+//			macroReplacementTokens = new ArrayList();
+//		else
+//			macroReplacementTokens = tokenizeReplacementString( NO_OFFSET_LIMIT, key, value, null ); 
+		
+		List macroReplacementTokens = new ArrayList();
+		if( !value.trim().equals( "" ) )  //$NON-NLS-1$
+		{	
+
+			Token t = new Token(
+					IToken.tIDENTIFIER, 
+					value, 
+					scannerData.getContextStack().getCurrentContext(),
+					scannerData.getContextStack().getCurrentLineNumber()
+					);
+			macroReplacementTokens.add( t );
+		}
 	
+		return new ObjectMacroDescriptor( key, 
+				signatureBuffer.toString(), 
+				macroReplacementTokens, 
+				value);
+		}
+
 	protected void poundDefine(int beginning, int beginningLine ) throws ScannerException, EndOfFileException {
 		StringBuffer potentialErrorMessage = new StringBuffer( POUND_DEFINE );
 		skipOverWhitespace();
@@ -2636,8 +2662,9 @@
 		}
 		else if ((c == '\n') || (c == '\r'))
 		{
-			checkValidMacroRedefinition(key, previousDefinition, "", beginning);				 //$NON-NLS-1$
-			addDefinition( key, "" ); //$NON-NLS-1$
+			descriptor = createObjectMacroDescriptor(key, ""); //$NON-NLS-1$
+			checkValidMacroRedefinition(key, previousDefinition, descriptor, beginning);
+			addDefinition( key, descriptor ); 
 		}
 		else if ((c == ' ') || (c == '\t') ) {
 			// this is a simple definition 
@@ -2646,8 +2673,9 @@
 			// get what we are to map the name to and add it to the definitions list
 			String value = getRestOfPreprocessorLine();
 			
-			checkValidMacroRedefinition(key, previousDefinition, value, beginning);
-			addDefinition( key, value ); 
+			descriptor = createObjectMacroDescriptor(key, value);
+			checkValidMacroRedefinition(key, previousDefinition, descriptor, beginning);
+			addDefinition( key, descriptor ); 
 		
 		} else if (c == '/') {
 			// this could be a comment	
@@ -2655,20 +2683,23 @@
 			if (c == '/') // one line comment
 				{
 				skipOverSinglelineComment();
-				checkValidMacroRedefinition(key, previousDefinition, "", beginning); //$NON-NLS-1$
-				addDefinition(key, ""); //$NON-NLS-1$
+				descriptor = createObjectMacroDescriptor(key, ""); //$NON-NLS-1$
+				checkValidMacroRedefinition(key, previousDefinition, descriptor, beginning);
+				addDefinition(key, descriptor); 
 			} else if (c == '*') // multi-line comment
 				{
 				if (skipOverMultilineComment()) {
 					// we have gone over a newline
 					// therefore, this symbol was defined to an empty string
-					checkValidMacroRedefinition(key, previousDefinition, "", beginning); //$NON-NLS-1$
-					addDefinition(key, ""); //$NON-NLS-1$
+					descriptor = createObjectMacroDescriptor(key, ""); //$NON-NLS-1$
+					checkValidMacroRedefinition(key, previousDefinition, descriptor, beginning); 
+					addDefinition(key, descriptor);
 				} else {
 					String value = getRestOfPreprocessorLine();
 					
-					checkValidMacroRedefinition(key, previousDefinition, "", beginning); //$NON-NLS-1$
-					addDefinition(key, value);
+					descriptor = createObjectMacroDescriptor(key, value);
+					checkValidMacroRedefinition(key, previousDefinition, descriptor, beginning); 
+					addDefinition(key, descriptor);
 				}
 			} else {
 				// this is not a comment 
@@ -2698,40 +2729,6 @@
             /* do nothing */
         } 
 	}
-
-	protected void checkValidMacroRedefinition(
-			String key,
-			IMacroDescriptor previousDefinition,
-			String newDefinition, int beginningOffset )
-	throws ScannerException 
-	{
-		StringBuffer buffer = new StringBuffer(key);
-		buffer.append( ' ');
-		buffer.append(newDefinition);
-		IMacroDescriptor newMacro = new ObjectMacroDescriptor( key, buffer.toString(), 
-				tokenizeReplacementString( NO_OFFSET_LIMIT, key, newDefinition, null ), newDefinition );
-		checkValidMacroRedefinition( key, previousDefinition, newMacro, beginningOffset );
-	}
-	
-	
-	protected void checkValidMacroRedefinition(
-			String key,
-			String previousDefinition,
-			String newDefinition, int beginningOffset )
-	throws ScannerException 
-	{
-		StringBuffer oldMacro = new StringBuffer( key );
-		oldMacro.append( ' ');
-		StringBuffer newMacro = new StringBuffer( oldMacro.toString() );
-		oldMacro.append( previousDefinition );
-		newMacro.append( newDefinition );
-		IMacroDescriptor prevMacroDescriptor = new ObjectMacroDescriptor( key, oldMacro.toString(), 
-				tokenizeReplacementString( NO_OFFSET_LIMIT, key, previousDefinition, null ), previousDefinition );
-		IMacroDescriptor newMacroDescriptor = new ObjectMacroDescriptor( key, newMacro.toString(), 
-				tokenizeReplacementString( NO_OFFSET_LIMIT, key, newDefinition, null ), newDefinition );
-		checkValidMacroRedefinition( key, prevMacroDescriptor, newMacroDescriptor, beginningOffset );
-	}
-	
 
 	protected void checkValidMacroRedefinition(
 		String key,
Index: parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java
===================================================================
retrieving revision 1.1
diff -u -r1.1 ScannerContext.java
--- parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java	22 Jan 2004 20:15:26 -0000	1.1
+++ parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java	16 Mar 2004 16:54:42 -0000
@@ -12,7 +12,6 @@
 
 import java.io.IOException;
 import java.io.Reader;
-import java.util.Stack;
 
 import org.eclipse.cdt.core.parser.ast.IASTInclusion;
 
@@ -24,7 +23,6 @@
     private int macroLength = -1;
 	private int line = 1;
 	private int offset;
-	private Stack undo = new Stack(); 
 	private ContextKind kind; 
 				
     /* (non-Javadoc)
@@ -108,18 +106,15 @@
 		return line;
 	}
 
-	/**
-	 * Returns the reader.
-	 * @return Reader
+	/*	 there are never more than 2 elements in the unget stack! 
+	 *   trigraphs may involve 2, but in general there is a single element
+	 *	 I have made room for 10 -- just in case :-) 
 	 */
-	public final Reader getReader()
-	{
-		return reader;
-	}
-
+	private int pos = 0;
+	private int undo[] = new int[10];  
 	public final int undoStackSize()
 	{
-		return undo.size();
+		return pos;
 	}
 
 	/**
@@ -128,7 +123,7 @@
 	 */
 	public final int popUndo()
 	{
-		int c = ((Integer)undo.pop()).intValue();
+		int c = undo[--pos];
 		if ((char)c == '\n') line++;
 		return c;
 	}
@@ -137,10 +132,18 @@
 	 * Sets the undo.
 	 * @param undo The undo to set
 	 */
-	public void pushUndo(int undo)
+	public final void pushUndo(int c)
 	{
-		if ((char)undo == '\n') line--;
-		this.undo.push( new Integer( undo )); 
+		if ((char)c == '\n') line--;
+		undo[pos++] = c; 
+	}
+	/**
+	 * Returns the reader.
+	 * @return Reader
+	 */
+	public final Reader getReader()
+	{
+		return reader;
 	}
 

Back to the top