Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,8 @@ public JMethod getStaticImpl(JMethod method) {
return staticImpl;
}

public JArrayType getTypeArray(JType elementType) {
// Synchronized because CodeSplitter reaches this from concurrent CFA traversals.
public synchronized JArrayType getTypeArray(JType elementType) {
JArrayType arrayType = arrayTypes.get(elementType);
if (arrayType == null) {
arrayType = new JArrayType(elementType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
* <p>
Expand Down Expand Up @@ -274,6 +279,12 @@ private List<JsStatement> statementsForFragment(int fragmentId,
*/
private Map<Fragment, ControlFlowAnalyzer> computeNotExclusiveCfaForFragments(
Collection<Fragment> exclusiveFragments) {
// Recording a dependency graph is order sensitive, so it keeps the serial loop below.
if (dependencyRecorder == MultipleDependencyGraphRecorder.NULL_RECORDER
&& exclusiveFragments.size() > 1) {
return computeNotExclusiveCfaForFragmentsInParallel(exclusiveFragments);
}

String dependencyGraphNameAfterInitialSequence = dependencyGraphNameAfterInitialSequence();

Map<Fragment, ControlFlowAnalyzer> notExclusiveCfaByFragment = Maps.newHashMap();
Expand Down Expand Up @@ -304,6 +315,59 @@ private Map<Fragment, ControlFlowAnalyzer> computeNotExclusiveCfaForFragments(
return notExclusiveCfaByFragment;
}

/**
* Runs {@link #computeNotExclusiveCfaForFragment} for every fragment in parallel. The iterations
* are independent: each builds its own ControlFlowAnalyzer, whose copy constructor duplicates
* every mutable set, and otherwise only reads the program.
*/
private Map<Fragment, ControlFlowAnalyzer> computeNotExclusiveCfaForFragmentsInParallel(
final Collection<Fragment> exclusiveFragments) {
Map<Fragment, ControlFlowAnalyzer> notExclusiveCfaByFragment = Maps.newLinkedHashMap();
int threads = Math.min(Runtime.getRuntime().availableProcessors(), exclusiveFragments.size());
ExecutorService executor = Executors.newFixedThreadPool(threads);
try {
Map<Fragment, Future<ControlFlowAnalyzer>> futures = Maps.newLinkedHashMap();
for (final Fragment fragment : exclusiveFragments) {
assert fragment.isExclusive();
futures.put(fragment, executor.submit(new Callable<ControlFlowAnalyzer>() {
@Override
public ControlFlowAnalyzer call() {
return computeNotExclusiveCfaForFragment(fragment, exclusiveFragments);
}
}));
}
for (Map.Entry<Fragment, Future<ControlFlowAnalyzer>> entry : futures.entrySet()) {
try {
notExclusiveCfaByFragment.put(entry.getKey(), entry.getValue().get());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e.getCause());
}
}
} finally {
executor.shutdown();
}
return notExclusiveCfaByFragment;
}

private ControlFlowAnalyzer computeNotExclusiveCfaForFragment(Fragment fragment,
Collection<Fragment> exclusiveFragments) {
ControlFlowAnalyzer cfa = new ControlFlowAnalyzer(initialSequenceCfa);
for (Fragment otherFragment : exclusiveFragments) {
// don't trace the initial fragments as they have already been traced and their atoms are
// already in {@code initialSequenceCfa}.
if (otherFragment.isInitial() || otherFragment == fragment) {
continue;
}
for (JRunAsync otherRunAsync : otherFragment.getRunAsyncs()) {
cfa.traverseFromRunAsync(otherRunAsync);
}
}
return cfa;
}

/**
* Compute a CFA that covers the entire live code of the program.
*/
Expand Down