Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception exit support #91

Open
wants to merge 43 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
dece759
Philipp Hirch's changes to support exception exits from methods.
markro49 Jul 11, 2017
64f2bd3
fix a couple of typos
markro49 Jul 11, 2017
bdb64d0
missed a new goal file
markro49 Jul 11, 2017
91fe6e5
a little source clean up
markro49 Jul 11, 2017
e839f68
Merge github.com:codespecs/daikon into exception-exit-support
mernst Jul 17, 2017
57e3338
Add changelog entry [ci skip]
mernst Jul 18, 2017
85bda2f
clean up after code review
markro49 Jul 24, 2017
832a572
Merge branch 'exception-exit-support' of github.com:markro49/daikon i…
markro49 Jul 24, 2017
4d26244
Merge branch 'master' into exception-exit-support
markro49 Jul 24, 2017
32b43ff
Merge branch 'master' into exception-exit-support
markro49 Jul 25, 2017
809c7a3
Check point changes in response to pull request review.
markro49 Jul 28, 2017
e9def80
Merge branch 'master' into exception-exit-support
markro49 Jul 28, 2017
d982c93
javadoc fix; update new exception goal files
markro49 Jul 28, 2017
c344ace
Merge branch 'master' into exception-exit-support
markro49 Jul 31, 2017
49eb2d7
update docs to reflect new ppt names and relationships
markro49 Jul 31, 2017
a5bef21
remove exception-handling switch; make it the default
markro49 Aug 1, 2017
491ff39
update java7 goal files
markro49 Aug 1, 2017
f4d90c4
Merge branch 'master' into exception-exit-support
markro49 Aug 28, 2017
c35be22
Merge branch 'master' into exception-exit-support
markro49 Oct 16, 2017
907f505
update goal files due to String EqualityComparison change.
markro49 Oct 16, 2017
9477798
Merge branch 'master' into exception-exit-support
markro49 Jul 24, 2018
a60986d
Merge branch 'master' into exception-exit-support
markro49 Jul 30, 2018
251de7d
undo refilling of paragraphs
markro49 Jul 31, 2018
bb75d9b
Merge ../daikon into exception-exit-support
mernst Aug 1, 2018
cfa8943
Tweak changelog
mernst Aug 1, 2018
feb20e5
Changes from code review
mernst Aug 1, 2018
e8cc02e
Documentation improvements
mernst Aug 1, 2018
8c461ec
Fix cross-reference
mernst Aug 1, 2018
29c06b6
Merge branch 'master' into exception-exit-support
markro49 Aug 7, 2018
bce5892
merge branch master; address most of comments from mernst
markro49 Aug 7, 2018
82061a1
Merge branch 'exception-exit-support' of github.com:markro49/daikon i…
markro49 Aug 7, 2018
e7f147d
Merge branch 'master' into exception-exit-support
markro49 Aug 13, 2018
2ec156a
add missing javadoc documentation
markro49 Aug 13, 2018
51ed8c4
Remove unused variables
mernst Aug 14, 2018
5662498
Merge ../daikon-branch-master into exception-exit-support
mernst Aug 15, 2018
f3e6bdc
Merge ../daikon-branch-master into exception-exit-support
mernst Aug 15, 2018
a6879b7
Merge branch 'master' into exception-exit-support
markro49 Aug 20, 2018
118ebb0
fix Require Java 8 merge error
markro49 Aug 20, 2018
1101880
Merge ../daikon-branch-master into exception-exit-support
mernst Sep 4, 2018
a5d33eb
Small changes
mernst Sep 4, 2018
133f01f
Merge ../daikon-branch-master into exception-exit-support
mernst Sep 4, 2018
177c11a
add missing CLASSPATH changes
markro49 Sep 4, 2018
d28c06f
Merge ../daikon-branch-master into exception-exit-support
mernst Sep 17, 2018
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
8 changes: 8 additions & 0 deletions doc/CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ Further documentation can be found in:

===========================================================================

Chicory:
- We now instrument exceptional exits. That means that Daikon is able
to infer invariants about when a Java method throws an exception.

===========================================================================

5.6.8 (?, ?, 2018)

Daikon no longer uses the plume-lib repository, but smaller ones such as
plume-scripts.

Expand Down
1 change: 1 addition & 0 deletions doc/daikon.dict
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ABI
accessor
accessors
acyclic
ADDR
AFS
AMD
Expand Down
35 changes: 25 additions & 10 deletions doc/daikon.texinfo
Original file line number Diff line number Diff line change
Expand Up @@ -2077,6 +2077,17 @@ source rather than a single location. This concept is represented in
Daikon by the dataflow hierarchy, see
@ref{Dataflow hierarchy,,,developer,Daikon Developer Manual}.

@cindex :::EXCEPTION program point
@cindex EXCEPTION program point

In a similar manner, @code{foo():::EXCEPTION} is the program point that
represents all the procedure's exceptional exits,
and invariants there are postconditions. When there are multiple
exception exits from a procedure (for instance, because of multiple
@code{throw} statements), the different exits are differentiated by
suffixing them with their line numbers; for instance,
@code{StackAr.top():::EXCEPTION59}.

The Java instrumenter Chicory selects names for program
points that include an indication of the argument and return types for
each method. These signatures are presented in @code{Class.getName} format: one
Expand Down Expand Up @@ -2247,10 +2258,11 @@ Static variables of a class have names of the form
@cindex pre-state variables
@code{orig(x)} refers to the value of variable @code{x} upon
entry to a procedure (because the procedure body might modify the value
of @code{x}). These variables appear only at @code{:::EXIT} program
points. Typically, @code{orig()} variables do not appear in the trace,
but are automatically created by Daikon when it matches up
@code{:::ENTER} and @code{:::EXIT@var{nn}} program points.
of @code{x}). These variables appear only at @code{:::EXIT} and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't refill paragraphs (that is, don't remove line breaks). It makes the diffs bigger and harder to read.

@code{:::EXCEPTION} program points. Typically, @code{orig()}
variables do not appear in the trace, but are automatically created by
Daikon when it matches up a @code{:::ENTER} with a @code{:::EXIT@var{nn}}
or with a @code{:::EXCEPTION@var{nn}} program point.
@xref{orig variable example}.

This variable prints as @code{orig} when using Daikon output format
Expand Down Expand Up @@ -7989,15 +8001,17 @@ answer is 0, but you believe that there are samples in the file you are
feeding to Daikon.

Using the normal dataflow hierarchy, Daikon explicitly processes
@code{:::EXIT} program points only. Other program points, such as
@code{:::ENTER} program points, are processed indirectly when their
corresponding @code{:::EXIT} points are encountered.
@code{:::EXIT} and @code{:::EXCEPTION} program points only. Other
program points, such as @code{:::ENTER} program points, are processed
indirectly when their corresponding @code{:::EXIT} or @code{:::EXCEPTION}
points are encountered.
(You can disable this behavior with the
@option{--nohierarchy} switch to Daikon;
see @ref{Options to control invariant detection}.)
If no @code{:::EXIT} program points are present (perhaps every
execution threw an exception, you filtered out all the
@code{:::EXIT} program points, or the data trace is obtained from
If no @code{:::EXIT} or @code{:::EXCEPTION} program points are present
(perhaps every execution threw an exception or you filtered out
all the @code{:::EXIT} and @code{:::EXCEPTION} program points, or the
data trace is obtained from
spreadsheet data instead of from a program execution),
then Daikon will not process any of the other program points, such as
the @code{:::ENTER} program points. You can make Daikon print information
Expand Down Expand Up @@ -9179,6 +9193,7 @@ Florian Gross,
Philip Guo,
Melissa Hao,
Michael Harder,
Philipp Hirch,
Dieter von Holten,
Greg Jay,
Josh Kataoka,
Expand Down
54 changes: 42 additions & 12 deletions doc/developer.texinfo
Original file line number Diff line number Diff line change
Expand Up @@ -1241,20 +1241,42 @@ at which they apply.
@c points are related to the @samp{orig} versions at @code{:::EXIT} program points.

@ref{Program point declarations} describe how program points are
declared in a Daikon input file. Here we will describe how the
@code{parent} records are typically used to connect program points into
a dataflow hierarchy.
declared in a Daikon input file.
Note that Daikon creates additional, internal program points
that do not appear in a input trace file generated by a front end, such as Chicory.
In particular, it creates a common (aka combined) @code{EXIT} point that is the parent of all
@code{EXIT<id>} program points in a method and a common (aka combined) @code{EXCEPTION}
point that is the parent of all @code{EXCPETION<id>} and @code{EXCEPTIONUNCAUGHT}
program points in a method.

Daikon uses three primary relationship types
(@code{PARENT}, @code{ENTER-EXIT} and @code{EXIT-EXITNN}) to connect the program points
into an acyclic dataflow hierarchy.

@itemize
@item
A program point that represents the @code{ENTRY} or @code{EXIT} of a
static method will have a @code{parent} record that points to the
@code{CLASS} program point for the containing class.
A program point that represents the @code{ENTRY}, @code{EXCEPTION}
or @code{EXIT} of a static method will have a @code{parent} record that
points to the @code{CLASS} program point for the containing class.

@item
A program point that represents the @code{ENTRY} or @code{EXIT} of a
non-static (instance) method will have a @code{parent} record that points to the
@code{OBJECT} program point for the containing object.
A program point that represents the @code{ENTRY}, @code{EXCEPTION}
or @code{EXIT} of a non-static (instance) method will have a
@code{parent} record that points to the @code{OBJECT} program point for
the containing object.

@item
An @code{ENTER-EXIT} edge connects each method's @code{ENTER} program
point with its corresponding @code{EXCEPTION} and @code{EXIT} program points.

@item
An @code{EXIT-EXITNN} edge connects each method's @code{EXIT} program
point with each of its corresponding @code{EXIT<id>} program points.

@item
An @code{EXIT-EXITNN} edge connects each method's @code{EXCEPTION} program
point with each of its corresponding @code{EXCEPTION<id>} and @code{EXCEPTIONUNCAUGHT}
program points.

@item
A program point that represents a @code{CLASS}
Expand All @@ -1271,7 +1293,8 @@ hierarchy may result in some true invariants that are not reported at
some program points. However, the invariant will be present in some
parent program point. The dataflow hierarchy is used by default, but
can be disabled by the @option{--nohierarchy} flag. When dataflow is enabled,
the only samples that are examined by Daikon are the @code{:::EXIT} program
the only samples that are examined by Daikon are the @code{:::EXIT}
and @code{:::EXCEPTION} program
points (plus @samp{orig} variables) since these contain a complete view of
the data, from which invariants at all other locations can be inferred.
For example, Daikon does not need to examine data at @code{:::ENTER} or
Expand Down Expand Up @@ -3173,16 +3196,23 @@ Program point names must be distinct.

While Daikon does not infer program point relationships from @code{ppt-name}s,
it does require these names to conform to a set syntax.
The following patterns are for the @code{enter}, @code{subexit},
The following patterns are for the @code{enter},
@code{class} and @code{object} @code{ppt-type}s, respectively.

@example
<fully qualified class name>.<method/function name>(<argument types>):::ENTER
<fully qualified class name>.<method/function name>(<argument types>):::EXIT<id>
<fully qualified class name>:::CLASS
<fully qualified class name>:::OBJECT
@end example

The @code{subexit} @code{ppt-type} may have one of three patterns:

@example
<fully qualified class name>.<method/function name>(<argument types>):::EXIT<id>
<fully qualified class name>.<method/function name>(<argument types>):::EXCEPTION<id>
<fully qualified class name>.<method/function name>(<argument types>):::EXCEPTIONUNCAUGHT
@end example

@noindent
Since in most languages a method or function may have multiple exit points,
the @code{ppt-name} for a @code{subexit} @code{ppt-type} must be appended
Expand Down
17 changes: 14 additions & 3 deletions java/daikon/AnnotateNullable.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,8 @@ public static void main(String[] args) throws IOException {
// static method can be identified because it will not have the OBJECT
// point as a parent.
for (PptTopLevel ppt : ppts.pptIterable()) {
if (!ppt.is_combined_exit() || !is_static_method(ppt)) {
if (!ppt.is_combined_exit() || !ppt.is_combined_exception() || !is_static_method(ppt))
continue;
}

String name = ppt.name().replaceFirst("[(].*$", "");
int lastdot = name.lastIndexOf('.');
Expand Down Expand Up @@ -344,7 +343,11 @@ public static void process_method(PptTopLevel ppt) {
System.out.printf("); // %d samples%n", ppt.num_samples());
} else {
System.out.printf(" method %s : // %d samples%n", jvm_signature(ppt), ppt.num_samples());
System.out.printf(" return: %s%n", return_annotation);
if (return_annotation != "") {
System.out.printf(" return: %s%n", return_annotation);
} else {
System.out.printf(" return:%n");
}
for (int i = 0; i < params.size(); i++) {
// Print the annotation for this parameter
System.out.printf(" parameter #%d : %s // %s%n", i, annos.get(i), names.get(i));
Expand Down Expand Up @@ -413,6 +416,14 @@ public static String jvm_signature(PptTopLevel ppt) {
// returnVar is non-null), because we are processing a Java program
String returnType =
returnVar == null ? "V" : JvmUtil.binaryNameToFieldDescriptor(returnVar.type.toString());
// Or an throw point
if (returnVar == null) {
returnVar = ppt.find_var_by_name("exception");
returnType =
returnVar == null
? "V"
: "V throws " + JvmUtil.binaryNameToFieldDescriptor(returnVar.type.toString());
}

return method + JvmUtil.arglistToJvm(java_args) + returnType;
}
Expand Down
15 changes: 11 additions & 4 deletions java/daikon/Chicory.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ public class Chicory {
@Option("Number of calls after which sampling will begin")
public static int sample_start = 0;

@Option("Enable remote debug")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a Javadoc comment, explaining what this does or how to use it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added and used by Philipp Hirch. I do not know how to use it. Should I comment out or just delete?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a new change -- it already existed, and he just moved it to be a command-line option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that now and presumably his changes made it work (better?). I get the jist of what this does and I think all the debug arguments are just magic. I will write up something.

public static boolean remote_debug = false;

/** Daikon port number. Daikon writes this to stdout when it is started in online mode. */
private static int daikon_port = -1;

Expand All @@ -152,8 +155,6 @@ public class Chicory {
/** flag to use if we want to turn on the static initialization checks */
public static final boolean checkStaticInit = true;

private static final boolean RemoteDebug = false;

/** Flag to initiate a purity analysis and use results to create add vars */
private static boolean purityAnalysis = false;

Expand Down Expand Up @@ -376,9 +377,10 @@ void start_target(String premain_args, String[] target_args) {
List<String> cmdlist = new ArrayList<String>();
cmdlist.add("java");

if (RemoteDebug) {
if (remote_debug) {
// -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=4142,suspend=n
cmdlist.add("-Xdebug -Xrunjdwp:server=n,transport=dt_socket,address=8000,suspend=y");
cmdlist.add("-agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=y");
// cmdlist.add("-Xdebug -Xrunjdwp:server=n,transport=dt_socket,address=8000,suspend=y");
// cmdlist.add("-Xdebug -Xnoagent
// -Xrunjdwp:transport=dt_socket,server=n,suspend=n,address=8000 -Djava.compiler=NONE");
}
Expand Down Expand Up @@ -498,6 +500,11 @@ public void runDaikon() {
heap_size, cp, daikon_args, output_dir, dtrace_file);
}

if (remote_debug) {
cmdstr =
cmdstr.replace(
"java", "java -agentlib:jdwp=transport=dt_socket,server=y,address=8001,suspend=y");
}
// System.out.println("daikon command is " + daikon_cmd);
// System.out.println("daikon command cmdstr " + cmdstr);

Expand Down
11 changes: 8 additions & 3 deletions java/daikon/Daikon.java
Original file line number Diff line number Diff line change
Expand Up @@ -1646,7 +1646,12 @@ public static void create_combined_exits(PptMap ppts) {

PptTopLevel exitnn_ppt = ppt;
PptName exitnn_name = exitnn_ppt.ppt_name;
PptName exit_name = ppt.ppt_name.makeExit();
PptName exit_name;
if (exitnn_name.isExitPoint()) {
exit_name = ppt.ppt_name.makeExit();
} else {
exit_name = ppt.ppt_name.makeExceptionExit();
}
PptTopLevel exit_ppt = exit_ppts.get(exit_name);

if (debugInit.isLoggable(Level.FINE)) {
Expand Down Expand Up @@ -1733,7 +1738,7 @@ static List<Invariant> filter_invs(List<Invariant> invs) {
* EXIT/EXITnn.
*/
private static void create_orig_vars(PptTopLevel exit_ppt, PptMap ppts) {
if (!exit_ppt.ppt_name.isExitPoint()) {
if (!exit_ppt.ppt_name.isExitPoint() && !exit_ppt.ppt_name.isExceptionPoint()) {
if (VarInfo.assertionsEnabled()) {
for (VarInfo vi : exit_ppt.var_infos) {
try {
Expand Down Expand Up @@ -2321,8 +2326,8 @@ public static void setupEquality(PptTopLevel ppt) {
// named program points such as :::POINT (used by convertcsv.pl)
// will be treated as leaves.
if (p.ppt_name.isCombinedExitPoint()
|| p.ppt_name.isCombinedExceptionPoint()
|| p.ppt_name.isEnterPoint()
|| p.ppt_name.isThrowsPoint()
|| p.ppt_name.isObjectInstanceSynthetic()
|| p.ppt_name.isClassStaticSynthetic()) {
return;
Expand Down
28 changes: 20 additions & 8 deletions java/daikon/FileIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,20 @@ private FileIO() {

// Program point name tags
public static final String ppt_tag_separator = ":::";
public static final String enter_suffix = "ENTER";
public static final String enter_tag = ppt_tag_separator + enter_suffix;
public static final String entry_suffix = "ENTER";
public static final String entry_tag = ppt_tag_separator + entry_suffix;
// EXIT does not necessarily appear at the end of the program point name;
// a number may follow it.
public static final String exit_suffix = "EXIT";
public static final String exit_tag = ppt_tag_separator + exit_suffix;
public static final String throws_suffix = "THROWS";
public static final String throws_tag = ppt_tag_separator + throws_suffix;
// public static final String throw_suffix = "THROW";
// public static final String throw_tag = ppt_tag_separator + throw_suffix;
public static final String exception_uncaught_suffix = "EXCEPTIONUNCAUGHT";
public static final String exception_uncaught_tag = ppt_tag_separator + exception_uncaught_suffix;
// EXCEPTION does not necessarily appear at the end of the program point name;
// a number may follow it.
public static final String exception_suffix = "EXCEPTION";
public static final String exception_tag = ppt_tag_separator + exception_suffix;
public static final String object_suffix = "OBJECT";
public static final String object_tag = ppt_tag_separator + object_suffix;
public static final String class_static_suffix = "CLASS";
Expand Down Expand Up @@ -1013,8 +1019,8 @@ private static void warn_if_hierarchy_mismatch(PptMap all_ppts) {
for (PptTopLevel ppt_top_level : all_ppts.ppt_all_iterable()) {
boolean is_program_point =
(ppt_top_level.ppt_name.isExitPoint()
|| ppt_top_level.ppt_name.isExceptionPoint()
|| ppt_top_level.ppt_name.isEnterPoint()
|| ppt_top_level.ppt_name.isThrowsPoint()
|| ppt_top_level.ppt_name.isObjectInstanceSynthetic()
|| ppt_top_level.ppt_name.isClassStaticSynthetic()
|| ppt_top_level.ppt_name.isGlobalPoint());
Expand Down Expand Up @@ -1722,9 +1728,9 @@ public static void process_sample(
// and :::CLASS program points. This scheme ensures that arbitrarly
// named program points such as :::POINT (used by convertcsv.pl)
// will be treated as leaves.
// Throws is a LEAF now, like Exit_nn

if (ppt.ppt_name.isEnterPoint()
|| ppt.ppt_name.isThrowsPoint()
|| ppt.ppt_name.isObjectInstanceSynthetic()
|| ppt.ppt_name.isClassStaticSynthetic()
|| ppt.ppt_name.isGlobalPoint()) {
Expand All @@ -1736,6 +1742,12 @@ public static void process_sample(
throw new RuntimeException(
"Bad program point name " + ppt.name + " is a combined exit point name");
}

if (ppt.ppt_name.isExceptionPoint() && ppt.ppt_name.isCombinedExceptionPoint()) {
// not Daikon.TerminationMessage; caller has more info (e.g., filename)
throw new RuntimeException(
"Bad program point name " + ppt.name + " is a combined exception point name");
}
}

// Add derived variables
Expand Down Expand Up @@ -2161,7 +2173,7 @@ public static boolean compute_orig_variables(
VarInfo[] vis = ppt.var_infos;
/*@Interned*/ String fn_name = ppt.ppt_name.getNameWithoutPoint();
String ppt_name = ppt.name();
if (ppt_name.endsWith(enter_tag)) {
if (ppt_name.endsWith(entry_tag)) {
Invocation invok = new Invocation(ppt, vals, mods);
if (nonce == null) {
call_stack.push(invok);
Expand All @@ -2171,7 +2183,7 @@ public static boolean compute_orig_variables(
return false;
}

if (ppt.ppt_name.isExitPoint() || ppt.ppt_name.isThrowsPoint()) {
if (ppt.ppt_name.isExitPoint() || ppt.ppt_name.isExceptionPoint()) {
Invocation invoc;
// Set invoc
{
Expand Down
Loading