# HG changeset patch # User Doug Simon # Date 1338998647 -7200 # Node ID 9f4783c0269e9c2fd223418f7c249697f99bb33c # Parent e26e6dca0bcfa02d5e5210dae916767d221c1ee7 folded -G:+CheckcastCounters functionality into checkcast snippets fixed bug in translation of @Parameter(multiple = true) parameters modified commands.py to appease jacoco diff -r e26e6dca0bcf -r 9f4783c0269e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Tue Jun 05 21:43:42 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Wed Jun 06 18:04:07 2012 +0200 @@ -67,12 +67,15 @@ @Snippet public static Object checkcastExact(@Parameter("object") Object object, @Parameter("exactHub") Object exactHub, @Constant("checkNull") boolean checkNull) { if (checkNull && object == null) { + isNull.inc(); return object; } Object objectHub = UnsafeLoadNode.loadObject(object, 0, hubOffset(), true); if (objectHub != exactHub) { + exactMiss.inc(); DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException); } + exactHit.inc(); return object; } @@ -86,12 +89,15 @@ @Snippet public static Object checkcastPrimary(@Parameter("hub") Object hub, @Parameter("object") Object object, @Constant("checkNull") boolean checkNull, @Constant("superCheckOffset") int superCheckOffset) { if (checkNull && object == null) { + isNull.inc(); return object; } Object objectHub = UnsafeLoadNode.loadObject(object, 0, hubOffset(), true); if (UnsafeLoadNode.loadObject(objectHub, 0, superCheckOffset, true) != hub) { + displayMiss.inc(); DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException); } + displayHit.inc(); return object; } @@ -101,6 +107,7 @@ @Snippet public static Object checkcastSecondary(@Parameter("hub") Object hub, @Parameter("object") Object object, @Parameter(value = "hints", multiple = true) Object[] hints, @Constant("checkNull") boolean checkNull) { if (checkNull && object == null) { + isNull.inc(); return object; } Object objectHub = UnsafeLoadNode.loadObject(object, 0, hubOffset(), true); @@ -109,6 +116,7 @@ for (int i = 0; i < hints.length; i++) { Object hintHub = hints[i]; if (hintHub == objectHub) { + hintsHit.inc(); return object; } } @@ -125,6 +133,7 @@ @Snippet public static Object checkcastUnknown(@Parameter("hub") Object hub, @Parameter("object") Object object, @Parameter(value = "hints", multiple = true) Object[] hints, @Constant("checkNull") boolean checkNull) { if (checkNull && object == null) { + isNull.inc(); return object; } Object objectHub = UnsafeLoadNode.loadObject(object, 0, hubOffset(), true); @@ -133,6 +142,7 @@ for (int i = 0; i < hints.length; i++) { Object hintHub = hints[i]; if (hintHub == objectHub) { + hintsHit.inc(); return object; } } @@ -150,11 +160,13 @@ static boolean checkSecondarySubType(Object t, Object s) { // if (S.cache == T) return true if (UnsafeLoadNode.loadObject(s, 0, secondarySuperCacheOffset(), true) == t) { + cacheHit.inc(); return true; } // if (T == S) return true if (s == t) { + T_equals_S.inc(); return true; } @@ -164,29 +176,38 @@ for (int i = 0; i < secondarySupers.length; i++) { if (t == loadNonNullObjectElement(secondarySupers, i)) { DirectObjectStoreNode.store(s, secondarySuperCacheOffset(), 0, t); + secondariesHit.inc(); return true; } } - + secondariesMiss.inc(); return false; } static boolean checkUnknownSubType(Object t, Object s) { // int off = T.offset int superCheckOffset = UnsafeLoadNode.load(t, 0, superCheckOffsetOffset(), CiKind.Int); + boolean primary = superCheckOffset != secondarySuperCacheOffset(); // if (T = S[off]) return true if (UnsafeLoadNode.loadObject(s, 0, superCheckOffset, true) == t) { + if (primary) { + cacheHit.inc(); + } else { + displayHit.inc(); + } return true; } // if (off != &cache) return false - if (superCheckOffset != secondarySuperCacheOffset()) { + if (primary) { + displayMiss.inc(); return false; } // if (T == S) return true if (s == t) { + T_equals_S.inc(); return true; } @@ -195,23 +216,29 @@ for (int i = 0; i < secondarySupers.length; i++) { if (t == loadNonNullObjectElement(secondarySupers, i)) { DirectObjectStoreNode.store(s, secondarySuperCacheOffset(), 0, t); + secondariesHit.inc(); return true; } } + secondariesMiss.inc(); return false; } /** - * Counters for the various code paths through a type check. + * Counters for the various code paths through a checkcast. */ public enum Counter { hintsHit("hit a hint type"), - hintsMissed("missed the hint types"), - exactType("tested type is (statically) final"), - noHints("profile information is not used"), - isNull("object tested is null"), - exception("type test failed with a ClassCastException"); + exactHit("exact type test succeeded"), + exactMiss("exact type test failed"), + isNull("object tested was null"), + cacheHit("secondary type cache hit"), + secondariesHit("secondaries scan succeeded"), + secondariesMiss("secondaries scan failed"), + displayHit("primary type test succeeded"), + displayMiss("primary type test failed"), + T_equals_S("object type was equal to secondary type"); final String description; final int index; @@ -246,51 +273,6 @@ static final boolean ENABLED = GraalOptions.CheckcastCounters; } - /** - * Type test used when {@link GraalOptions#CheckcastCounters} is enabled. - */ - @Snippet - public static Object checkcastCounters(@Parameter("hub") Object hub, @Parameter("object") Object object, @Parameter(value = "hints", multiple = true) Object[] hints, @Constant("hintsAreExact") boolean hintsAreExact) { - if (object == null) { - isNull.inc(); - return object; - } - Object objectHub = UnsafeLoadNode.loadObject(object, 0, hubOffset(), true); - if (hints.length == 0) { - noHints.inc(); - if (!checkUnknownSubType(hub, objectHub)) { - exception.inc(); - DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException); - } - } else { - // if we get an exact match: succeed immediately - ExplodeLoopNode.explodeLoop(); - for (int i = 0; i < hints.length; i++) { - Object hintHub = hints[i]; - if (hintHub == objectHub) { - if (hintsAreExact) { - exactType.inc(); - } else { - hintsHit.inc(); - } - return object; - } - } - if (!hintsAreExact) { - if (!checkUnknownSubType(hub, objectHub)) { - exception.inc(); - DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException); - } else { - hintsMissed.inc(); - } - } else { - exception.inc(); - DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException); - } - } - return object; - } - @Fold private static int superCheckOffsetOffset() { return CompilerImpl.getInstance().getConfig().superCheckOffsetOffset; @@ -353,7 +335,6 @@ private final RiResolvedMethod primary; private final RiResolvedMethod secondary; private final RiResolvedMethod unknown; - private final RiResolvedMethod counters; private final RiRuntime runtime; public Templates(RiRuntime runtime) { @@ -364,7 +345,6 @@ primary = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastPrimary", Object.class, Object.class, boolean.class, int.class)); secondary = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastSecondary", Object.class, Object.class, Object[].class, boolean.class)); unknown = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastUnknown", Object.class, Object.class, Object[].class, boolean.class)); - counters = runtime.getRiMethod(CheckCastSnippets.class.getDeclaredMethod("checkcastCounters", Object.class, Object.class, Object[].class, boolean.class)); } catch (NoSuchMethodException e) { throw new GraalInternalError(e); } @@ -383,11 +363,7 @@ Arguments arguments; SnippetTemplate.Key key; - if (GraalOptions.CheckcastCounters) { - HotSpotKlassOop[] hints = createHints(hintInfo); - key = new SnippetTemplate.Key(counters).add("hints", multiple(Object.class, hints.length)).add("hintsAreExact", hintInfo.exact); - arguments = arguments("hub", hub).add("object", object).add("hints", hints); - } else if (target == null) { + if (target == null) { HotSpotKlassOop[] hints = createHints(hintInfo); key = new SnippetTemplate.Key(unknown).add("hints", multiple(Object.class, hints.length)).add("checkNull", checkNull); arguments = arguments("hub", hub).add("object", object).add("hints", hints); diff -r e26e6dca0bcf -r 9f4783c0269e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Tue Jun 05 21:43:42 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Wed Jun 06 18:04:07 2012 +0200 @@ -24,8 +24,6 @@ import java.lang.reflect.*; -import sun.misc.*; - import com.oracle.graal.cri.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; diff -r e26e6dca0bcf -r 9f4783c0269e graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Tue Jun 05 21:43:42 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Wed Jun 06 18:04:07 2012 +0200 @@ -35,6 +35,7 @@ import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.snippets.Snippet.Arguments; import com.oracle.graal.snippets.Snippet.Constant; @@ -158,6 +159,7 @@ int parameterCount = signature.argumentCount(false); Parameter[] parameterAnnotations = new Parameter[parameterCount]; + ConstantNode[] placeholders = new ConstantNode[parameterCount]; for (int i = 0; i < parameterCount; i++) { Constant c = CiUtil.getParameterAnnotation(Constant.class, i, method); if (c != null) { @@ -176,7 +178,9 @@ assert multiple != null : method + ": requires a Multiple named " + name; assert checkMultipleArgument(method, signature, i, name, multiple); Object array = ((Multiple) multiple).array; - replacements.put(snippetGraph.getLocal(i), ConstantNode.forObject(array, runtime, snippetCopy)); + ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy); + replacements.put(snippetGraph.getLocal(i), placeholder); + placeholders[i] = placeholder; } parameterAnnotations[i] = p; } @@ -193,28 +197,36 @@ for (int i = 0; i < parameterCount; i++) { Parameter p = parameterAnnotations[i]; if (p != null) { - ValueNode parameter; if (p.multiple()) { - parameter = null; assert snippetCopy.getLocal(i) == null; - ConstantNode array = (ConstantNode) replacements.get(snippetGraph.getLocal(i)); - for (LoadIndexedNode loadIndexed : snippetCopy.getNodes(LoadIndexedNode.class)) { - if (loadIndexed.array() == array) { + Object array = ((Multiple) key.get(p.value())).array; + int length = Array.getLength(array); + LocalNode[] locals = new LocalNode[length]; + Stamp stamp = StampFactory.forKind(runtime.getType(array.getClass().getComponentType()).kind(false)); + for (int j = 0; j < length; j++) { + assert (parameterCount & 0xFFFF) == parameterCount; + int idx = i << 16 | j; + LocalNode local = snippetCopy.unique(new LocalNode(idx, stamp)); + locals[j] = local; + } + parameters.put(p.value(), locals); + + ConstantNode placeholder = placeholders[i]; + assert placeholder != null; + for (Node usage : placeholder.usages().snapshot()) { + if (usage instanceof LoadIndexedNode) { + LoadIndexedNode loadIndexed = (LoadIndexedNode) usage; Debug.dump(snippetCopy, "Before replacing %s", loadIndexed); - LoadMultipleParameterNode lmp = new LoadMultipleParameterNode(array, i, loadIndexed.index(), loadIndexed.stamp()); - StructuredGraph g = (StructuredGraph) loadIndexed.graph(); - g.add(lmp); - g.replaceFixedWithFixed(loadIndexed, lmp); - parameter = lmp; + LoadSnippetParameterNode loadSnippetParameter = snippetCopy.add(new LoadSnippetParameterNode(locals, loadIndexed.index(), loadIndexed.stamp())); + snippetCopy.replaceFixedWithFixed(loadIndexed, loadSnippetParameter); Debug.dump(snippetCopy, "After replacing %s", loadIndexed); - break; } } } else { - parameter = snippetCopy.getLocal(i); + LocalNode local = snippetCopy.getLocal(i); + assert local != null; + parameters.put(p.value(), local); } - assert parameter != null; - parameters.put(p.value(), parameter); } } @@ -274,6 +286,8 @@ new DeadCodeEliminationPhase().apply(snippetCopy); + assert checkAllMultipleParameterPlaceholdersAreDeleted(parameterCount, placeholders); + this.graph = snippetCopy; nodes = new ArrayList<>(graph.getNodeCount()); ReturnNode retNode = null; @@ -291,6 +305,15 @@ this.returnNode = retNode; } + private static boolean checkAllMultipleParameterPlaceholdersAreDeleted(int parameterCount, ConstantNode[] placeholders) { + for (int i = 0; i < parameterCount; i++) { + if (placeholders[i] != null) { + assert placeholders[i].isDeleted() : placeholders[i]; + } + } + return true; + } + private static boolean checkConstantArgument(final RiResolvedMethod method, RiSignature signature, int i, String name, Object arg, CiKind kind) { if (kind.isObject()) { Class type = signature.argumentTypeAt(i, method.holder()).resolve(method.holder()).toJava(); @@ -320,9 +343,9 @@ /** * The named parameters of this template that must be bound to values during instantiation. - * Each parameter is either a {@link LocalNode} or a {@link LoadMultipleParameterNode} instance. + * Each value in this map is either a {@link LocalNode} instance or a {@link LocalNode} array. */ - private final Map parameters; + private final Map parameters; /** * The return node (if any) of the snippet. @@ -344,28 +367,28 @@ for (Map.Entry e : args) { String name = e.getKey(); - ValueNode parameter = parameters.get(name); + Object parameter = parameters.get(name); assert parameter != null : this + " has no parameter named " + name; Object argument = e.getValue(); if (parameter instanceof LocalNode) { if (argument instanceof ValueNode) { - replacements.put(parameter, (ValueNode) argument); + replacements.put((LocalNode) parameter, (ValueNode) argument); } else { CiKind kind = ((LocalNode) parameter).kind(); CiConstant constant = CiConstant.forBoxed(kind, argument); - replacements.put(parameter, ConstantNode.forCiConstant(constant, runtime, replaceeGraph)); + replacements.put((LocalNode) parameter, ConstantNode.forCiConstant(constant, runtime, replaceeGraph)); } } else { - assert parameter instanceof LoadMultipleParameterNode; + assert parameter instanceof LocalNode[]; + LocalNode[] locals = (LocalNode[]) parameter; Object array = argument; assert array != null && array.getClass().isArray(); - int length = Array.getLength(array); - LoadMultipleParameterNode lmp = (LoadMultipleParameterNode) parameter; - assert length == lmp.getLocalCount() : length + " != " + lmp.getLocalCount(); + int length = locals.length; + assert Array.getLength(array) == length : length + " != " + Array.getLength(array); for (int j = 0; j < length; j++) { - LocalNode local = lmp.getLocal(j); + LocalNode local = locals[j]; assert local != null; - CiConstant constant = CiConstant.forBoxed(lmp.kind(), Array.get(array, j)); + CiConstant constant = CiConstant.forBoxed(local.kind(), Array.get(array, j)); ConstantNode element = ConstantNode.forCiConstant(constant, runtime, replaceeGraph); replacements.put(local, element); } @@ -434,16 +457,18 @@ public String toString() { StringBuilder buf = new StringBuilder(graph.toString()).append('('); String sep = ""; - for (Map.Entry e : parameters.entrySet()) { + for (Map.Entry e : parameters.entrySet()) { String name = e.getKey(); - ValueNode value = e.getValue(); + Object value = e.getValue(); buf.append(sep); sep = ", "; if (value instanceof LocalNode) { - buf.append(value.kind().name()).append(' ').append(name); + LocalNode local = (LocalNode) value; + buf.append(local.kind().name()).append(' ').append(name); } else { - LoadMultipleParameterNode lmp = (LoadMultipleParameterNode) value; - buf.append(value.kind().name()).append('[').append(lmp.getLocalCount()).append("] ").append(name); + LocalNode[] locals = (LocalNode[]) value; + String kind = locals.length == 0 ? "?" : locals[0].kind().name(); + buf.append(kind).append('[').append(locals.length).append("] ").append(name); } } return buf.append(')').toString(); diff -r e26e6dca0bcf -r 9f4783c0269e graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/LoadMultipleParameterNode.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/LoadMultipleParameterNode.java Tue Jun 05 21:43:42 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.snippets.nodes; - -import java.lang.reflect.*; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.Snippet.Parameter; - -/** - * Implements the semantics of a snippet {@link Parameter} whose {@link Parameter#multiple()} element is {@code true}. - */ -public final class LoadMultipleParameterNode extends FixedWithNextNode implements Canonicalizable { - - @Input private ValueNode index; - - private final LocalNode[] locals; - - public ValueNode index() { - return index; - } - - public LoadMultipleParameterNode(ConstantNode array, int localIndex, ValueNode index, Stamp stamp) { - super(stamp); - int length = Array.getLength(array.asConstant().asObject()); - this.index = index; - locals = new LocalNode[length]; - for (int i = 0; i < length; i++) { - int idx = localIndex << 16 | i; - LocalNode local = array.graph().unique(new LocalNode(idx, stamp())); - locals[i] = local; - } - } - - public LocalNode getLocal(int idx) { - assert idx < locals.length; - return locals[idx]; - } - - public int getLocalCount() { - return locals.length; - } - - @Override - public ValueNode canonical(CanonicalizerTool tool) { - assert index.isConstant(); - return getLocal(index().asConstant().asInt()); - } -} diff -r e26e6dca0bcf -r 9f4783c0269e graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/LoadSnippetParameterNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/LoadSnippetParameterNode.java Wed Jun 06 18:04:07 2012 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.snippets.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.snippets.Snippet.Parameter; + +/** + * Implements the semantics of a snippet {@link Parameter} whose {@link Parameter#multiple()} element is {@code true}. + */ +public final class LoadSnippetParameterNode extends FixedWithNextNode implements Canonicalizable { + + @Input private ValueNode index; + + private final LocalNode[] locals; + + public LoadSnippetParameterNode(LocalNode[] locals, ValueNode index, Stamp stamp) { + super(stamp); + this.index = index; + this.locals = locals; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (index.isConstant()) { + return locals[index.asConstant().asInt()]; + } + return this; + } +} diff -r e26e6dca0bcf -r 9f4783c0269e mx/commands.py --- a/mx/commands.py Tue Jun 05 21:43:42 2012 +0200 +++ b/mx/commands.py Wed Jun 06 18:04:07 2012 +0200 @@ -565,9 +565,8 @@ # Exclude all compiler tests and snippets excludes = ['com.oracle.graal.compiler.tests.*'] for p in mx.projects(): - for s in p.source_dirs(): - _add_classes_with_annotation(excludes, s, None, '@Snippet') - _add_classes_with_annotation(excludes, s, None, '@ClassSubstitution') + _add_classes_with_annotation(excludes, p, None, '@Snippet', includeInnerClasses=True) + _add_classes_with_annotation(excludes, p, None, '@ClassSubstitution', includeInnerClasses=True) agentOptions = { 'append' : 'true' if _jacoco == 'append' else 'false', 'bootclasspath' : 'true', @@ -578,32 +577,41 @@ exe = join(_jdk(build), 'bin', mx.exe_suffix('java')) return mx.run([exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) -def _add_classes_with_annotation(classes, srcDir, pkgRoot, annotation): +def _add_classes_with_annotation(classes, p, pkgRoot, annotation, includeInnerClasses=False): """ - Scan 'srcDir' for Java source files containing a line starting with 'annotation' + Scan the sources of project 'p' for Java source files containing a line starting with 'annotation' (ignoring preceding whitespace) and add the fully qualified class name to 'classes' for each Java source file matched. """ pkgDecl = re.compile(r"^package\s+([a-zA-Z_][\w\.]*)\s*;$") - for root, _, files in os.walk(srcDir): - for name in files: - if name.endswith('.java') and name != 'package-info.java': - hasTest = False - with open(join(root, name)) as f: - pkg = None - for line in f: - if line.startswith("package "): - match = pkgDecl.match(line) - if match: - pkg = match.group(1) - else: - if line.strip().startswith(annotation): - hasTest = True - break - if hasTest: - assert pkg is not None - if pkgRoot is None or pkg.startswith(pkgRoot): - classes.append(pkg + '.' + name[:-len('.java')]) + for srcDir in p.source_dirs(): + outputDir = p.output_dir() + for root, _, files in os.walk(srcDir): + for name in files: + if name.endswith('.java') and name != 'package-info.java': + hasTest = False + with open(join(root, name)) as f: + pkg = None + for line in f: + if line.startswith("package "): + match = pkgDecl.match(line) + if match: + pkg = match.group(1) + else: + if line.strip().startswith(annotation): + hasTest = True + break + if hasTest: + basename = name[:-len('.java')] + assert pkg is not None + if pkgRoot is None or pkg.startswith(pkgRoot): + pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep)) + for e in os.listdir(pkgOutputDir): + if includeInnerClasses: + if e.endswith('.class') and (e.startswith(basename) or e.startswith(basename + '$')): + classes.append(pkg + '.' + e[:-len('.class')]) + elif e == basename + '.class': + classes.append(pkg + '.' + basename) # Table of unit tests. @@ -639,7 +647,7 @@ p = mx.project(proj) classes = [] for pkg in _unittests[proj]: - _add_classes_with_annotation(classes, join(p.dir, 'src'), pkg, '@Test') + _add_classes_with_annotation(classes, p, pkg, '@Test') if len(pos) != 0: classes = [c for c in classes if containsAny(c, pos)] @@ -669,7 +677,7 @@ p = mx.project(proj) classes = [] for pkg in _jtttests[proj]: - _add_classes_with_annotation(classes, join(p.dir, 'src'), pkg, '@Test') + _add_classes_with_annotation(classes, p, pkg, '@Test') if len(pos) != 0: classes = [c for c in classes if containsAny(c, pos)]