Skip to content

Commit b68f550

Browse files
committed
Add documentation on remove-instanceof
1 parent dbd6988 commit b68f550

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

jbmc/src/java_bytecode/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ To be documented.
4343

4444
To be documented.
4545

46+
\section java-bytecode-remove-instanceof Remove instanceof
47+
48+
\ref remove_instanceof.h removes the bytecode instruction `instanceof ` and replaces it with two instructions:
49+
- check whether the pointer is null
50+
- if not null, does the class identifier match the type of any of its subtypes
51+
4652
\section java-bytecode-method-stubbing Method stubbing
4753

4854
To be documented.

jbmc/src/java_bytecode/remove_instanceof.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,73 @@ Author: Chris Smowton, [email protected]
88

99
/// \file
1010
/// Remove Instance-of Operators
11+
///
12+
/// Java has an operator called `instanceof`, which is used to check if an
13+
/// instance of a class is of a particular type. For example given that `A` and
14+
/// `B` are the identifiers of classes, which directly extend Object. If the
15+
/// following example java code is executed -
16+
/// ```java
17+
/// Object a = new A();
18+
/// boolean x = a instanceof A; // true
19+
/// boolean y = a instanceof B; // false
20+
/// ```
21+
/// Then, `x` will be set to `true` and `y` will be set to `false`.
22+
///
23+
/// `instanceof` also works with inheritance. Given classes `C` and `D`, where
24+
/// `C` extends from `Object` and `D` extends `C`. If the following example java
25+
/// code is executed -
26+
/// ```java
27+
/// Object c = new C();
28+
/// Object d = new D();
29+
/// boolean b1 = c instanceof C; // true
30+
/// boolean b2 = c instanceof D; // false
31+
/// boolean b3 = d instanceof C; // true
32+
/// boolean b4 = d instanceof D; // true
33+
/// ```
34+
/// Then, `b1` will be `true`, `b2` will be `false`, `b3` will be `true` and
35+
/// `b4` will be `true`.
36+
///
37+
/// `instanceof` has its own instruction type in the java bytecode. We need to
38+
/// rewrite it in terms of other, more fundamental operations in order to
39+
/// analyse it. This operation is referred to as "lowering" or in this
40+
/// specific case - `remove_instanceof`.
41+
///
42+
/// For a simple example where class `A` extends `Object` and no classes extend
43+
/// `A`, the expression `e instanceof A` needs to be lowered to an expression
44+
/// equivalent to `e == null ? false : e->@class_identifier == "A"`. The null
45+
/// case needs to be taken into account first, as we can't lookup the value of
46+
/// a `@class_identifier` field in a null pointer. Note that according to the
47+
/// Java specification, `null` is not an instance of any type.
48+
///
49+
/// For an example with inheritance where class `D` extends `C` and `C` extends
50+
/// `Object`, then `e instanceof C` needs to be lowered to an expression
51+
/// equivalent to `e == null ? false : (e->@class_identifier == "C" ||
52+
/// e->@class_identifier == "D")`. To lower `e instanceof C` correctly, we need
53+
/// to take into account each of the classes extends from `C`. Working out what
54+
/// classes extend a given class type is performed using an instance of the
55+
/// `class_hierarchyt` class.
56+
///
57+
/// In terms of the goto program, the `instanceof` operator is identified in the
58+
/// expression tree, based on the `exprt.id()` being `ID_java_instance_of`. The
59+
/// left hand side of the operator must be a pointer and the right hand side
60+
/// must be a type.
61+
///
62+
/// The lowered form has a refinement to help with null pointer analysis later
63+
/// on. Instead of dereferencing the pointer to get @class_identifier in each
64+
/// comparision, it is dereferenced a single time and the result is reused. This
65+
/// is easier to analyse for null pointers, because there is only a single
66+
/// dereference to consider. So the constructed program takes the form -
67+
/// ```cpp
68+
/// if(expr == null)
69+
/// instanceof_result = false;
70+
/// else
71+
/// string class_identifier_tmpX = expr->@class_identifier;
72+
/// instanceof_result =
73+
/// class_identifier_tmpX == "C" ||
74+
/// class_identifier_tmpX == "D";
75+
/// ```
76+
/// Where the `X` in `class_identifier_tmp` is a number which makes the
77+
/// identifier unique.
1178

1279
#ifndef CPROVER_JAVA_BYTECODE_REMOVE_INSTANCEOF_H
1380
#define CPROVER_JAVA_BYTECODE_REMOVE_INSTANCEOF_H

0 commit comments

Comments
 (0)