This is an automated email from the ASF dual-hosted git repository.

lkishalmi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 2d565fe  [NETBEANS-3693] Create only one instance of javac
2d565fe is described below

commit 2d565fe02be31e33009fefb4880254ba0a692f47
Author: Akshay-Gupta-Oracle <[email protected]>
AuthorDate: Sun Aug 9 19:04:59 2020 +0530

    [NETBEANS-3693] Create only one instance of javac
---
 .../java/source/parsing/CompilationInfoImpl.java   |  18 +++-
 .../modules/java/source/parsing/JavacParser.java   | 118 ++++++++++++++-------
 .../java/source/parsing/ModuleOraculumTest.java    |   5 +-
 3 files changed, 98 insertions(+), 43 deletions(-)

diff --git 
a/java/java.source.base/src/org/netbeans/modules/java/source/parsing/CompilationInfoImpl.java
 
b/java/java.source.base/src/org/netbeans/modules/java/source/parsing/CompilationInfoImpl.java
index fe95c1f..c06c5a2 100644
--- 
a/java/java.source.base/src/org/netbeans/modules/java/source/parsing/CompilationInfoImpl.java
+++ 
b/java/java.source.base/src/org/netbeans/modules/java/source/parsing/CompilationInfoImpl.java
@@ -89,7 +89,9 @@ public final class CompilationInfoImpl {
     private final boolean isDetached;
     JavaSource.Phase parserCrashed = JavaSource.Phase.UP_TO_DATE;      //When 
javac throws an error, the moveToPhase sets this to the last safe phase
     private final Map<CacheClearPolicy, Map<Object, Object>> userCache = new 
EnumMap<CacheClearPolicy, Map<Object, Object>>(CacheClearPolicy.class);
-
+    //cache of already parsed files
+    private Map<String, CompilationUnitTree> parsedTrees;
+    
     /**
      * Creates a new CompilationInfoImpl for given source file
      * @param parser used to parse the file
@@ -330,7 +332,11 @@ public final class CompilationInfoImpl {
         }
         return null;
     }
-        
+
+    public Map<String, CompilationUnitTree> getParsedTrees() {
+        return this.parsedTrees;
+    }
+
                                 
     /**
      * Moves the state to required phase. If given state was already reached 
@@ -483,8 +489,12 @@ public final class CompilationInfoImpl {
         assert compilationUnit != null;
         this.compilationUnit = compilationUnit;
     }
-                
-    private boolean hasSource () {
+
+    public void setParsedTrees(Map<String, CompilationUnitTree> parsedTrees) {
+        this.parsedTrees = parsedTrees;
+    }
+
+    private boolean hasSource() {
         return this.jfo != null && !isClassFile;
     }
 
diff --git 
a/java/java.source.base/src/org/netbeans/modules/java/source/parsing/JavacParser.java
 
b/java/java.source.base/src/org/netbeans/modules/java/source/parsing/JavacParser.java
index ca0f9bd..9d1d6d5 100644
--- 
a/java/java.source.base/src/org/netbeans/modules/java/source/parsing/JavacParser.java
+++ 
b/java/java.source.base/src/org/netbeans/modules/java/source/parsing/JavacParser.java
@@ -56,6 +56,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumMap;
 import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -153,6 +154,8 @@ public class JavacParser extends Parser {
     public static final String MIME_TYPE = "text/x-java";
     //No output writer like /dev/null
     private static final PrintWriter DEV_NULL = new PrintWriter(new 
NullWriter(), false);
+    //Maximum threshold size after which parse use one instance for one file
+    private static final int MAX_FILE_SIZE = (5 << 20);   
     //Max number of dump files
     private static final int MAX_DUMPS = 
Integer.getInteger("org.netbeans.modules.java.source.parsing.JavacParser.maxDumps",
 255);  //NOI18N
     //Command line switch disabling partial reparse
@@ -187,8 +190,10 @@ public class JavacParser extends Parser {
     private FileObject root;
     //ClassPaths used by the parser
     private ClasspathInfo cpInfo;
-    //Count of files the parser was created for
-    private final int sourceCount;
+    //all the files for which parser was created for
+    private final Collection<Snapshot> snapshots;
+    //size of all the files to check the memory leack
+    private long snapshotSize;
     //Incremental parsing support
     private final boolean supportsReparse;
     //Incremental parsing support
@@ -218,9 +223,13 @@ public class JavacParser extends Parser {
 
     JavacParser (final Collection<Snapshot> snapshots, boolean privateParser) {
         this.privateParser = privateParser;
-        this.sourceCount = snapshots.size();
-        final boolean singleJavaFile = this.sourceCount == 1 && 
MIME_TYPE.equals(snapshots.iterator().next().getSource().getMimeType());
+        this.snapshots = snapshots;
+        final boolean singleJavaFile = this.snapshots.size() == 1 && 
MIME_TYPE.equals(snapshots.iterator().next().getSource().getMimeType());
         this.supportsReparse = singleJavaFile && !DISABLE_PARTIAL_REPARSE;
+        this.snapshotSize=0;
+        for (Snapshot snapshot : snapshots) {
+            this.snapshotSize+=snapshot.getSource().getFileObject().getSize();
+        }
         JavaFileFilterImplementation filter = null;
         if (singleJavaFile) {
             final Source source = snapshots.iterator().next().getSource();
@@ -236,7 +245,7 @@ public class JavacParser extends Parser {
             new Runnable() {
                 @Override
                 public void run() {
-                    if (sourceCount == 0) {
+                    if (snapshots.size() == 0) {
                         invalidate(true);
                     }
                 }
@@ -390,9 +399,10 @@ public class JavacParser extends Parser {
             task.toString(),
             snapshot == null ? "null" : snapshot.getText()});      //NOI18N
         final CompilationInfoImpl oldInfo = ciImpl;
+        Map<String, CompilationUnitTree> oldParsedTrees = new HashMap<>();
         boolean success = false;
         try {
-            switch (this.sourceCount) {
+            switch (this.snapshots.size()) {
                 case 0:
                     if (shouldParse(task)) {
                         init(task);
@@ -415,7 +425,7 @@ public class JavacParser extends Parser {
                     }
                     if (needsFullReparse) {
                         positions.clear();
-                        ciImpl = createCurrentInfo (this, file, root, 
snapshot, null, null);
+                        ciImpl = createCurrentInfo(this, file, root, snapshot, 
null, null, oldParsedTrees);
                         LOGGER.fine("\t:created new javac");                   
                 //NOI18N
                     } else if (VERIFY_PARTIAL_REPARSE) {
                         CompilationInfoImpl verifyInfo = new 
CompilationInfoImpl(this, file, root, null, null, snapshot, true);
@@ -423,10 +433,29 @@ public class JavacParser extends Parser {
                     }
                     break;
                 default:
-                    init (snapshot, task, false);
+                    init(snapshot, task, false);
+                    DiagnosticListener<JavaFileObject> diagnosticListener;
+                    JavacTaskImpl javacTask;
+                    boolean 
oneInstanceJava=Boolean.getBoolean("java.enable.single.javac") && 
this.snapshotSize <= this.MAX_FILE_SIZE;
+                    if (sequentialParsing == null && ciImpl == null && 
oneInstanceJava) {
+                        List<JavaFileObject> jfos = new ArrayList<>();
+                        for (Snapshot s : snapshots) {
+                            
jfos.add(FileObjects.sourceFileObject(s.getSource().getFileObject(), root, 
JavaFileFilterQuery.getFilter(s.getSource().getFileObject()), s.getText()));
+                        }
+                        diagnosticListener = new 
CompilationInfoImpl.DiagnosticListenerImpl(this.root, jfos.get(0), this.cpInfo);
+                        javacTask = JavacParser.createJavacTask(this.file, 
jfos, this.root, this.cpInfo,
+                                this, diagnosticListener, false);
+                     } else if (ciImpl != null && (sequentialParsing != null 
|| oneInstanceJava)) {
+                        diagnosticListener = ciImpl.getDiagnosticListener();
+                        javacTask = ciImpl.getJavacTask();
+                        oldParsedTrees = ciImpl.getParsedTrees();
+                    } else {
+                        diagnosticListener = null;
+                        javacTask = null;
+                    }
                     ciImpl = createCurrentInfo(this, file, root, snapshot,
-                        sequentialParsing == null || ciImpl == null ? null : 
ciImpl.getJavacTask(),
-                        sequentialParsing == null || ciImpl == null ? null : 
ciImpl.getDiagnosticListener());
+                        javacTask,
+                        diagnosticListener,oldParsedTrees);
             }
             success = true;
         } finally {
@@ -459,14 +488,14 @@ public class JavacParser extends Parser {
             if (isClasspathInfoProvider) {
                 final ClasspathInfo providedInfo = 
((ClasspathInfo.Provider)task).getClasspathInfo();
                 if (providedInfo != null && !providedInfo.equals(cpInfo)) {
-                    if (sourceCount != 0) {
+                    if (snapshots.size() != 0) {
                         LOGGER.log (Level.FINE, "Task {0} has changed 
ClasspathInfo form: {1} to:{2}", new Object[]{task, cpInfo, providedInfo}); 
//NOI18N
                     }
                     invalidate(true); //Reset initialized, world has changed.
                 }
             }
             if (invalid) {
-                assert cachedSnapShot != null || sourceCount == 0;
+                assert cachedSnapShot != null || snapshots.size() == 0;
                 try {
                     parseImpl(cachedSnapShot, task);
                 } catch (FileObjects.InvalidFileException ife) {
@@ -583,37 +612,50 @@ public class JavacParser extends Parser {
         assert parserError != null;
         Phase currentPhase = currentInfo.getPhase();
         try {
-            if (currentPhase.compareTo(Phase.PARSED)<0 && 
phase.compareTo(Phase.PARSED)>=0 && phase.compareTo(parserError)<=0) {
+            if (currentPhase.compareTo(Phase.PARSED) < 0 && 
phase.compareTo(Phase.PARSED) >= 0 && phase.compareTo(parserError) <= 0) {
                 if (cancellable && parserCanceled.get()) {
                     //Keep the currentPhase unchanged, it may happen that an 
userActionTask
                     //runnig after the phace completion task may still use it.
                     return Phase.MODIFIED;
                 }
                 long start = System.currentTimeMillis();
-                // XXX - this might be with wrong encoding
-                Iterable<? extends CompilationUnitTree> trees;
-                if (sequentialParsing != null) {
-                    trees = 
sequentialParsing.parse(currentInfo.getJavacTask(), currentInfo.jfo);
+                Iterable<? extends CompilationUnitTree> trees = null;
+                Iterator<? extends CompilationUnitTree> it = null;
+                CompilationUnitTree unit = null;
+                if (snapshots.size() > 1 && currentInfo.getParsedTrees() != 
null && currentInfo.getParsedTrees().containsKey(currentInfo.jfo.getName())) {
+                    unit = 
currentInfo.getParsedTrees().get(currentInfo.jfo.getName());
                 } else {
-                    trees = currentInfo.getJavacTask(forcedSources).parse();
-                }
-                if (trees == null) {
-                    LOGGER.log( Level.INFO, "Did not parse anything for: {0}", 
currentInfo.jfo.toUri()); //NOI18N
-                    return Phase.MODIFIED;
-                }
-                Iterator<? extends CompilationUnitTree> it = trees.iterator();
-                if (!it.hasNext()) {
-                    LOGGER.log( Level.INFO, "Did not parse anything for: {0}", 
currentInfo.jfo.toUri()); //NOI18N
-                    return Phase.MODIFIED;
+
+                    if (sequentialParsing != null) {
+                        trees = 
sequentialParsing.parse(currentInfo.getJavacTask(), currentInfo.jfo);
+                    } else {
+                        trees = 
currentInfo.getJavacTask(forcedSources).parse();
+                    }
+                    if (unit == null) {
+                        if (trees == null) {
+                            LOGGER.log(Level.INFO, "Did not parse anything 
for: {0}", currentInfo.jfo.toUri()); //NOI18N
+                            return Phase.MODIFIED;
+                        }
+                        it = trees.iterator();
+                        if (!it.hasNext()) {
+                            LOGGER.log(Level.INFO, "Did not parse anything 
for: {0}", currentInfo.jfo.toUri()); //NOI18N
+                            return Phase.MODIFIED;
+                        }
+
+                        List<JavaFileObject> parsedFiles = new ArrayList<>();
+                        while (it.hasNext()) {
+                            CompilationUnitTree oneFileTree = it.next();
+                            parsedFiles.add(oneFileTree.getSourceFile());
+                            CompilationUnitTree put = 
currentInfo.getParsedTrees().put(oneFileTree.getSourceFile().getName(), 
oneFileTree);
+                        }
+                        currentInfo.setParsedFiles(parsedFiles);
+                        unit = trees.iterator().next();
+                    }
+
                 }
-                CompilationUnitTree unit = it.next();
+
                 currentInfo.setCompilationUnit(unit);
-                List<JavaFileObject> parsedFiles = new ArrayList<>();
-                parsedFiles.add(unit.getSourceFile());
-                while (it.hasNext()) {
-                    parsedFiles.add(it.next().getSourceFile());
-                }
-                currentInfo.setParsedFiles(parsedFiles);
+
                 final Document doc = currentInfo.getDocument();
                 if (doc != null && supportsReparse) {
                     final FindMethodRegionsVisitor v = new 
FindMethodRegionsVisitor(doc,Trees.instance(currentInfo.getJavacTask()).getSourcePositions(),this.parserCanceled,
 unit);
@@ -729,18 +771,20 @@ public class JavacParser extends Parser {
             final FileObject root,
             final Snapshot snapshot,
             final JavacTaskImpl javac,
-            final DiagnosticListener<JavaFileObject> diagnosticListener) 
throws IOException {
+            final DiagnosticListener<JavaFileObject> diagnosticListener,
+            final Map<String, CompilationUnitTree> parsedTrees) throws 
IOException {
         CompilationInfoImpl info = new CompilationInfoImpl(parser, file, root, 
javac, diagnosticListener, snapshot, false);
         if (file != null) {
             Logger.getLogger("TIMER").log(Level.FINE, "CompilationInfo",    
//NOI18N
                     new Object[] {file, info});
         }
+        info.setParsedTrees(parsedTrees);
         return info;
     }
 
     static JavacTaskImpl createJavacTask(
             final FileObject file,
-            final List<JavaFileObject> jfos,
+            final Iterable<? extends JavaFileObject> jfos,
             final FileObject root,
             final ClasspathInfo cpInfo,
             final JavacParser parser,
@@ -761,7 +805,7 @@ public class JavacParser extends Parser {
         }
         final Set<ConfigFlags> flags = EnumSet.noneOf(ConfigFlags.class);
         final Optional<JavacParser> mayBeParser = Optional.ofNullable(parser);
-        if (mayBeParser.filter((p)->p.sourceCount>1).isPresent()) {
+        if (mayBeParser.filter((p) -> p.snapshots.size() > 1).isPresent()) {
             flags.add(ConfigFlags.MULTI_SOURCE);
         }
         if (Optional.ofNullable(mayBeParser.map(p->(p.file))
diff --git 
a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/parsing/ModuleOraculumTest.java
 
b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/parsing/ModuleOraculumTest.java
index d0e86e4..bcc3c80 100644
--- 
a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/parsing/ModuleOraculumTest.java
+++ 
b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/parsing/ModuleOraculumTest.java
@@ -461,8 +461,9 @@ public class ModuleOraculumTest extends NbTestCase {
             final DiagnosticListener<? super JavaFileObject> 
diagnosticListener,
             final boolean detached) {
         try {
-            List<JavaFileObject> jfo = file != null ? 
Arrays.asList(FileObjects.sourceFileObject(file, root, null, false)) : 
Collections.emptyList();
-            return JavacParser.createJavacTask(file, jfo, root, cpInfo, 
parser, diagnosticListener, detached);
+            JavaFileObject jfo = file != null ? 
FileObjects.sourceFileObject(file, root, null, false) : null;
+            Iterable<? extends JavaFileObject> jfos = jfo != null ? 
Arrays.asList(jfo) : Collections.emptyList();
+            return JavacParser.createJavacTask(file, jfos, root, cpInfo, 
parser, diagnosticListener, detached);
         } catch (IOException ex) {
             throw new IllegalStateException(ex);
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to