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

Documents for BodyInterceptor and some Tools #410

Merged
merged 7 commits into from
Sep 27, 2021
Merged

Documents for BodyInterceptor and some Tools #410

merged 7 commits into from
Sep 27, 2021

Conversation

wangzun66
Copy link
Collaborator

@wangzun66 wangzun66 commented Aug 25, 2021

BodyInterceptor:

  • LocalSplitter
  • LocalPacker
  • SSA
  • TrapTightener
  • EmptySwitchEliminator
  • UnreachableCodeEliminator
  • CopyPropagator
  • LocalNameStandardizer

Tools:

  • LocalLivenessAnalyser
  • DominanceFinder

@@ -0,0 +1,28 @@
#### LocalSplitter

LocalSplitter is a <code>BodyInterceptor</code> that attempts to identify and separate uses of a local variable (as definition) that are independent of each other by renaming local variable.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
LocalSplitter is a <code>BodyInterceptor</code> that attempts to identify and separate uses of a local variable (as definition) that are independent of each other by renaming local variable.
LocalSplitter is a <code>BodyInterceptor</code> that attempts to identify and separate uses of a local variable (as definition) that are independent of each other by renaming local variables.


![LocalSplitter Example_1](./figures/LocalSplitter Example_1.png)

As shown the example above, the local variable <code>l1</code> is defined twice. It can be split up into two new local variables: <code>l1#1</code> and <code>l1#2</code> because of the independency between its two definitions.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
As shown the example above, the local variable <code>l1</code> is defined twice. It can be split up into two new local variables: <code>l1#1</code> and <code>l1#2</code> because of the independency between its two definitions.
As shown in the example above, the local variable <code>l1</code> is defined twice. It can be split up into two new local variables: <code>l1#1</code> and <code>l1#2</code> because the two definitions are independent of each other.


![LocalSplitter Example_2](./figures/LocalSplitter Example_2.png)

In the second example, the local variable <code>l2</code> is defined thrice. But it cannot be split up into three new local variables as in the first example. Because its definitions in the if-branches are not independent of each other. Therefore, it can be only split up into two local variables as shown in the figure.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
In the second example, the local variable <code>l2</code> is defined thrice. But it cannot be split up into three new local variables as in the first example. Because its definitions in the if-branches are not independent of each other. Therefore, it can be only split up into two local variables as shown in the figure.
In the second example, the local variable <code>l2</code> is defined thrice. But it cannot be split up into three new local variables as in the first example, because its definitions in the if-branches are not independent of each other. Therefore, it can only be split up into two local variables as shown in the figure.


![TrapTightener Example](./figures/TrapTightener%20Example.png)

We assume in the example above that only the<code>Stmt</code>:<code>l2 := 2</code>might throw an exception caught by the<code>Trap</code>which is labeled with<code>label3</code>. In the jimple body before running the TrapTightener, the protected area covered by the Trap contains three<code>Stmt</code>:<code>l1 := 1; l2 := 2; l2 := 3</code>. But an exception could only arise at the<code>Stmt</code>:<code>l2 := 2</code>. After the implementation of TrapTightener, we will get a contractible protected area which contains only the<code>Stmt</code>that might throw an exception, namely the<code>Stmt</code>:<code>l2 := 2</code>.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
We assume in the example above that only the<code>Stmt</code>:<code>l2 := 2</code>might throw an exception caught by the<code>Trap</code>which is labeled with<code>label3</code>. In the jimple body before running the TrapTightener, the protected area covered by the Trap contains three<code>Stmt</code>:<code>l1 := 1; l2 := 2; l2 := 3</code>. But an exception could only arise at the<code>Stmt</code>:<code>l2 := 2</code>. After the implementation of TrapTightener, we will get a contractible protected area which contains only the<code>Stmt</code>that might throw an exception, namely the<code>Stmt</code>:<code>l2 := 2</code>.
We assume in the example above that only the<code>Stmt</code>:<code>l2 := 2</code>might throw an exception caught by the<code>Trap</code>which is labeled with<code>label3</code>. In the jimple body before running the TrapTightener, the protected area covered by the Trap contains three<code>Stmts</code>:<code>l1 := 1; l2 := 2; l2 := 3</code>. But an exception could only arise at the<code>Stmt</code>:<code>l2 := 2</code>. After the implementation of TrapTightener, we will get a contractible protected area which contains only the<code>Stmt</code>that might throw an exception, namely the<code>Stmt</code>:<code>l2 := 2</code>.


#### EmptySwitchEliminator

EmptySwitchEliminator is a<code>BodyInterceptor</code>that removes the empty switch statement which contains only the default case.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
EmptySwitchEliminator is a<code>BodyInterceptor</code>that removes the empty switch statement which contains only the default case.
EmptySwitchEliminator is a<code>BodyInterceptor</code>that removes empty switch statements which contains only the default case.


![EmptySwitchEliminator Example](./figures/EmptySwitchEliminator Example.png)

As shown in the example above, the switch statement in the jimple body always takes the default action. After running EmptySwitchEliminator, the switch statement is replaced with the<code>GotoStmt</code>for default case.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
As shown in the example above, the switch statement in the jimple body always takes the default action. After running EmptySwitchEliminator, the switch statement is replaced with the<code>GotoStmt</code>for default case.
As shown in the example above, the switch statement in the jimple body always takes the default action. After running EmptySwitchEliminator, the switch statement is replaced with a <code>GotoStmt</code> to the default case.

According to the copy propagation's definition, the statement<code>c = use(a)</code>can be replaced with<code>c = use(b)</code>iff both conditions are met:

* <code>a</code>is defined only one time on all the paths from<code>a = b</code>to<code>c = use(a)</code>.
* There're no definitions of<code>b</code>on any path from<code>a = b</code>to<code>c = use(a)</code>.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* There're no definitions of<code>b</code>on any path from<code>a = b</code>to<code>c = use(a)</code>.
* There are no definitions of<code>b</code>on any path from<code>a = b</code>to<code>c = use(a)</code>.

* <code>a</code>is defined only one time on all the paths from<code>a = b</code>to<code>c = use(a)</code>.
* There're no definitions of<code>b</code>on any path from<code>a = b</code>to<code>c = use(a)</code>.

In the example for global copy propagation, the first used<code>l1</code>is replaced with<code>l0</code>, but the second used<code>l1</code>cannot be replace with<code>l3</code>, because the second condition is not satisfied.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
In the example for global copy propagation, the first used<code>l1</code>is replaced with<code>l0</code>, but the second used<code>l1</code>cannot be replace with<code>l3</code>, because the second condition is not satisfied.
In the example for global copy propagation, the first used<code>l1</code>is replaced with<code>l0</code>, but the second used<code>l1</code>cannot be replaced with<code>l3</code>, because the second condition is not satisfied.

b = use(a); // a, b are local variables, const is a constant
```

After perfoming the constant propagation, the statement<code>b = use(a)</code>can be replace with<code>b = use(const)</code>iff<code>a</code>is not redefined on all the paths from<code>a = const</code>to<code>b = use(a)</code>.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
After perfoming the constant propagation, the statement<code>b = use(a)</code>can be replace with<code>b = use(const)</code>iff<code>a</code>is not redefined on all the paths from<code>a = const</code>to<code>b = use(a)</code>.
After perfoming the constant propagation, the statement<code>b = use(a)</code>can be replaced with<code>b = use(const)</code>iff<code>a</code>is not redefined on any of the paths from<code>a = const</code>to<code>b = use(a)</code>.


After perfoming the constant propagation, the statement<code>b = use(a)</code>can be replace with<code>b = use(const)</code>iff<code>a</code>is not redefined on all the paths from<code>a = const</code>to<code>b = use(a)</code>.

Therefore, the first used<code>l1</code>in the second example can be replace with the constant<code>1</code>, but the second used<code>l1</code>cannot be replaced with the constant<code>2</code>, because<code>l1</code>is redefined on the path from<code>l1 = 2</code>to<code>l4 = use(l1)</code>. However, it can replaced with local variable<code>l2</code>, because the both conditions of copy propagation are met.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Therefore, the first used<code>l1</code>in the second example can be replace with the constant<code>1</code>, but the second used<code>l1</code>cannot be replaced with the constant<code>2</code>, because<code>l1</code>is redefined on the path from<code>l1 = 2</code>to<code>l4 = use(l1)</code>. However, it can replaced with local variable<code>l2</code>, because the both conditions of copy propagation are met.
Therefore, the first used<code>l1</code>in the second example can be replaced with the constant<code>1</code>, but the second used<code>l1</code>cannot be replaced with the constant<code>2</code>, because<code>l1</code>is redefined on the path from<code>l1 = 2</code>to<code>l4 = use(l1)</code>. However, it can replaced with local variable<code>l2</code>, because the both conditions of copy propagation are met.


![SSA Example_2](./figures/SSA Example_2.png)

In the given example, the StaticSingleAssignmentFormer assigns to a new local variable for each<code>IdentityStmt</code>and<code>AssignStmt</code>. And each use uses the local variable which is most recently defined. Sometimes, it is impossible to determine the most recently defined local variable for a use in a join block. In this case, the StaticSingleAssignmentFormer will insert a<code>PhiStmt</code>in the front of the join block to merge all most recently defined local variables and assign them a new local variable.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
In the given example, the StaticSingleAssignmentFormer assigns to a new local variable for each<code>IdentityStmt</code>and<code>AssignStmt</code>. And each use uses the local variable which is most recently defined. Sometimes, it is impossible to determine the most recently defined local variable for a use in a join block. In this case, the StaticSingleAssignmentFormer will insert a<code>PhiStmt</code>in the front of the join block to merge all most recently defined local variables and assign them a new local variable.
In the given example, the StaticSingleAssignmentFormer assigns each<code>IdentityStmt</code>and<code>AssignStmt</code>to a new local variable. And each use uses the local variable which is most recently defined. Sometimes, it is impossible to determine the most recently defined local variable for a use in a join block. In this case, the StaticSingleAssignmentFormer will insert a<code>PhiStmt</code>in the front of the join block to merge all most recently defined local variables and assign them a new local variable.

@kadirayk kadirayk merged commit 208b414 into develop Sep 27, 2021
@swissiety swissiety deleted the Documents branch January 7, 2022 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants