|
|
|
/*
|
|
|
|
* Copyright (c) 2018-present, Facebook, Inc.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class HoistIndirect {
|
|
|
|
|
|
|
|
public static int svar = 0;
|
|
|
|
int[] array;
|
|
|
|
|
|
|
|
class Test {
|
|
|
|
|
|
|
|
int a = 0;
|
|
|
|
|
|
|
|
int foo(int x) {
|
|
|
|
return x + 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_test(Test test) {
|
|
|
|
test.a = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
int get_test(Test test) {
|
|
|
|
return test.a;
|
|
|
|
}
|
|
|
|
|
|
|
|
int get_sum_test(Test test, int x) {
|
|
|
|
return test.a + x;
|
|
|
|
}
|
|
|
|
|
|
|
|
Test return_only(Test t) {
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
int indirect_modification_dont_hoist(int size, Test t) {
|
|
|
|
int d = 0;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
set_test(t);
|
|
|
|
d = get_test(t); // don't hoist since t changes
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void variant_arg_dont_hoist(int size, Test t) {
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
set_test(t); // t is invalidated
|
|
|
|
get_sum_test(
|
|
|
|
return_only(t),
|
|
|
|
size); // foo' and return_only's arguments are variant, hence don't hoist
|
|
|
|
}
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
// t changes deep in the call stack
|
|
|
|
int deep_modification_dont_hoist(int size) {
|
|
|
|
int d = 0;
|
|
|
|
Test t = new Test();
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
indirect_modification_dont_hoist(size, t);
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
// foo(3) is ok to hoist, but can't detect this right now
|
|
|
|
int indirect_modification_hoist_FN(int size) {
|
|
|
|
int d = 0;
|
|
|
|
Test t = new Test();
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
set_test(t); // this (and t) is invalidated here
|
|
|
|
d = foo(3); // foo becomes variant due to implicit arg. this being invalidated above
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void set() {
|
|
|
|
svar = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
int get() {
|
|
|
|
return svar;
|
|
|
|
}
|
|
|
|
|
|
|
|
int indirect_this_modification_dont_hoist(int size) {
|
|
|
|
int d = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
d = get(); // don't hoist since this.svar changes in the loop
|
|
|
|
set();
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
int direct_this_modification_dont_hoist_FP(int size) {
|
|
|
|
int d = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
d += get(); // don't hoist since this.svar changes in the loop
|
|
|
|
svar = i;
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
int this_modification_outside_hoist(int size) {
|
|
|
|
int d = 0;
|
|
|
|
set();
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
d += get(); // ok to hoist since set is outside
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
int arg_modification_hoist(int size, Test t) {
|
|
|
|
int d = 0;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
d += get(); // ok to hoist since set_test doesn't modify this
|
|
|
|
t.set_test(t);
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_ith(int i, int[] array) {
|
|
|
|
array[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int get_ith(int i, int[] array) {
|
|
|
|
return array[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
int modified_array_dont_hoist(int size, Test t) {
|
|
|
|
int d = 0;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
set_ith(i, array);
|
|
|
|
d += get_ith(size, array); // don't hoist since array changes
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int regionFirst(int[] region) {
|
|
|
|
return region[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void incrDest(int[] source, int[] dest) {
|
|
|
|
dest[0] = source[0] + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nested_change_dont_hoist_FP(int[][] nextRegionM, int p, int[] tempRegion) {
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
if (i < regionFirst(nextRegionM[p])) {
|
|
|
|
incrDest(tempRegion, nextRegionM[p]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|