summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/J2CLOpts.cpp21
-rw-r--r--test/lit/passes/j2cl-inline.wast30
-rw-r--r--test/lit/passes/j2cl.wast119
3 files changed, 101 insertions, 69 deletions
diff --git a/src/passes/J2CLOpts.cpp b/src/passes/J2CLOpts.cpp
index b1fb8bb1f..f6821b80f 100644
--- a/src/passes/J2CLOpts.cpp
+++ b/src/passes/J2CLOpts.cpp
@@ -67,7 +67,7 @@ private:
// Avoid optimizing class initialization condition variable itself. If we
// were optimizing it then it would become "true" and would defeat its
// functionality and the clinit would never trigger during runtime.
- if (name.startsWith("f_$initialized__")) {
+ if (name.startsWith("$class-initialized@")) {
return;
}
assignmentCounts[name]++;
@@ -90,13 +90,14 @@ public:
if (!isOnceFunction(curr)) {
return;
}
+ Name enclosingClassName = getEnclosingClass(curr->name);
int optimizedBefore = optimized;
if (auto* block = curr->body->dynCast<Block>()) {
for (auto*& expr : block->list) {
- maybeHoistConstant(expr);
+ maybeHoistConstant(expr, enclosingClassName);
}
} else {
- maybeHoistConstant(curr->body);
+ maybeHoistConstant(curr->body, enclosingClassName);
}
if (optimized != optimizedBefore) {
@@ -111,7 +112,7 @@ public:
}
private:
- void maybeHoistConstant(Expression* expr) {
+ void maybeHoistConstant(Expression* expr, Name enclosingClassName) {
auto set = expr->dynCast<GlobalSet>();
if (!set) {
return;
@@ -123,6 +124,14 @@ private:
return;
}
+ if (getEnclosingClass(set->name) != enclosingClassName) {
+ // Only hoist fields initialized by its own class.
+ // If it is only initialized once but by another class (although it is
+ // very uncommon / edge scenario) then we cannot be sure if the clinit was
+ // triggered before the field access so it is better to leave it alone.
+ return;
+ }
+
if (!GlobalUtils::canInitializeGlobal(*getModule(), set->value)) {
// It is not a valid constant expression so cannot be hoisted to
// global init.
@@ -138,6 +147,10 @@ private:
optimized++;
}
+ Name getEnclosingClass(Name name) {
+ return Name(name.str.substr(name.str.find_last_of('@')));
+ }
+
AssignmentCountMap& assignmentCounts;
};
diff --git a/test/lit/passes/j2cl-inline.wast b/test/lit/passes/j2cl-inline.wast
index 9ccdad00e..dad35b80e 100644
--- a/test/lit/passes/j2cl-inline.wast
+++ b/test/lit/passes/j2cl-inline.wast
@@ -6,41 +6,41 @@
(module
;; A once function that has become empty
- (func $clinit-trivial-1_@once@_ )
+ (func $clinit-trivial-1_@once@_@Foo )
;; A once function that just calls another
- (func $clinit-trivial-2_@once@_
- (call $clinit-trivial-1_@once@_)
+ (func $clinit-trivial-2_@once@_@Bar
+ (call $clinit-trivial-1_@once@_@Foo)
)
;; CHECK: (type $0 (func))
- ;; CHECK: (global $f_$initialized__ (mut i32) (i32.const 0))
- (global $f_$initialized__ (mut i32) (i32.const 0))
+ ;; CHECK: (global $$class-initialized@Zoo (mut i32) (i32.const 0))
+ (global $$class-initialized@Zoo (mut i32) (i32.const 0))
;; Not hoisted but trivial.
- ;; CHECK: (func $clinit-non-trivial_@once@_ (type $0)
+ ;; CHECK: (func $clinit-non-trivial_@once@_@Zoo (type $0)
;; CHECK-NEXT: (if
- ;; CHECK-NEXT: (global.get $f_$initialized__)
+ ;; CHECK-NEXT: (global.get $$class-initialized@Zoo)
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (global.set $f_$initialized__
+ ;; CHECK-NEXT: (global.set $$class-initialized@Zoo
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $clinit-non-trivial_@once@_
- (if (global.get $f_$initialized__)
+ (func $clinit-non-trivial_@once@_@Zoo
+ (if (global.get $$class-initialized@Zoo)
(return)
)
- (global.set $f_$initialized__ (i32.const 1))
+ (global.set $$class-initialized@Zoo (i32.const 1))
)
;; CHECK: (func $main (type $0)
- ;; CHECK-NEXT: (call $clinit-non-trivial_@once@_)
+ ;; CHECK-NEXT: (call $clinit-non-trivial_@once@_@Zoo)
;; CHECK-NEXT: )
(func $main
- (call $clinit-trivial-1_@once@_)
- (call $clinit-trivial-2_@once@_)
- (call $clinit-non-trivial_@once@_)
+ (call $clinit-trivial-1_@once@_@Foo)
+ (call $clinit-trivial-2_@once@_@Bar)
+ (call $clinit-non-trivial_@once@_@Zoo)
)
)
diff --git a/test/lit/passes/j2cl.wast b/test/lit/passes/j2cl.wast
index 75c845ec5..0d37dd829 100644
--- a/test/lit/passes/j2cl.wast
+++ b/test/lit/passes/j2cl.wast
@@ -6,18 +6,18 @@
(module
;; CHECK: (type $0 (func))
- ;; CHECK: (global $field-f64 f64 (f64.const 1))
+ ;; CHECK: (global $field-f64@Foo f64 (f64.const 1))
- ;; CHECK: (global $field-i32 i32 (i32.const 1))
- (global $field-i32 (mut i32) (i32.const 0))
- (global $field-f64 (mut f64) (f64.const 0))
+ ;; CHECK: (global $field-i32@Foo i32 (i32.const 1))
+ (global $field-i32@Foo (mut i32) (i32.const 0))
+ (global $field-f64@Foo (mut f64) (f64.const 0))
- ;; CHECK: (func $clinit_@once@_ (type $0)
+ ;; CHECK: (func $clinit_@once@_@Foo (type $0)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
- (func $clinit_@once@_
- (global.set $field-i32 (i32.const 1))
- (global.set $field-f64 (f64.const 1))
+ (func $clinit_@once@_@Foo
+ (global.set $field-i32@Foo (i32.const 1))
+ (global.set $field-f64@Foo (f64.const 1))
)
)
@@ -29,46 +29,46 @@
;; CHECK: (type $1 (func))
- ;; CHECK: (global $field2 (mut anyref) (ref.null none))
+ ;; CHECK: (global $field2@Foo (mut anyref) (ref.null none))
- ;; CHECK: (global $referredField i32 (i32.const 42))
- (global $referredField (i32) (i32.const 42))
+ ;; CHECK: (global $referredField@Foo i32 (i32.const 42))
+ (global $referredField@Foo (i32) (i32.const 42))
- ;; CHECK: (global $field1 anyref (struct.new $A
- ;; CHECK-NEXT: (global.get $referredField)
+ ;; CHECK: (global $field1@Foo anyref (struct.new $A
+ ;; CHECK-NEXT: (global.get $referredField@Foo)
;; CHECK-NEXT: ))
- ;; CHECK: (global $referredFieldMut (mut i32) (i32.const 42))
- (global $referredFieldMut (mut i32) (i32.const 42))
+ ;; CHECK: (global $referredFieldMut@Foo (mut i32) (i32.const 42))
+ (global $referredFieldMut@Foo (mut i32) (i32.const 42))
- (global $field1 (mut anyref) (ref.null none))
+ (global $field1@Foo (mut anyref) (ref.null none))
- (global $field2 (mut anyref) (ref.null none))
+ (global $field2@Foo (mut anyref) (ref.null none))
- ;; CHECK: (global $field3 anyref (global.get $field1))
- (global $field3 (mut anyref) (ref.null none))
+ ;; CHECK: (global $field3@Foo anyref (global.get $field1@Foo))
+ (global $field3@Foo (mut anyref) (ref.null none))
- ;; CHECK: (func $clinit_@once@_ (type $1)
- ;; CHECK-NEXT: (global.set $field2
+ ;; CHECK: (func $clinit_@once@_@Foo (type $1)
+ ;; CHECK-NEXT: (global.set $field2@Foo
;; CHECK-NEXT: (struct.new $A
- ;; CHECK-NEXT: (global.get $referredFieldMut)
+ ;; CHECK-NEXT: (global.get $referredFieldMut@Foo)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $clinit_@once@_
+ (func $clinit_@once@_@Foo
;; Referred field is immutable, should hoist
- (global.set $field1 (struct.new $A (
- global.get $referredField)
+ (global.set $field1@Foo (struct.new $A (
+ global.get $referredField@Foo)
))
;; Referred field is mutable, should not hoist
- (global.set $field2 (struct.new $A
- (global.get $referredFieldMut)
+ (global.set $field2@Foo (struct.new $A
+ (global.get $referredFieldMut@Foo)
))
;; Referred field is mutable but hoistable hence also this one.
;; (Note that requires multiple iterations in a single run)
- (global.set $field3 (global.get $field1))
+ (global.set $field3@Foo (global.get $field1@Foo))
)
)
@@ -78,24 +78,24 @@
(type $A (struct))
;; CHECK: (type $1 (func))
- ;; CHECK: (global $field-any (mut anyref) (struct.new_default $A))
+ ;; CHECK: (global $field-any@Foo (mut anyref) (struct.new_default $A))
- ;; CHECK: (global $field-i32 (mut i32) (i32.const 2))
- (global $field-i32 (mut i32) (i32.const 2))
+ ;; CHECK: (global $field-i32@Foo (mut i32) (i32.const 2))
+ (global $field-i32@Foo (mut i32) (i32.const 2))
- (global $field-any (mut anyref) (struct.new $A))
+ (global $field-any@Foo (mut anyref) (struct.new $A))
- ;; CHECK: (func $clinit_@once@_ (type $1)
- ;; CHECK-NEXT: (global.set $field-i32
+ ;; CHECK: (func $clinit_@once@_@Foo (type $1)
+ ;; CHECK-NEXT: (global.set $field-i32@Foo
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
- ;; CHECK-NEXT: (global.set $field-any
+ ;; CHECK-NEXT: (global.set $field-any@Foo
;; CHECK-NEXT: (struct.new_default $A)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $clinit_@once@_
- (global.set $field-i32 (i32.const 1))
- (global.set $field-any (struct.new $A))
+ (func $clinit_@once@_@Foo
+ (global.set $field-i32@Foo (i32.const 1))
+ (global.set $field-any@Foo (struct.new $A))
)
)
@@ -104,31 +104,50 @@
;; CHECK: (type $0 (func))
- ;; CHECK: (global $field-i32 i32 (i32.const 1))
- (global $field-i32 (mut i32) (i32.const 0))
+ ;; CHECK: (global $field@Foo i32 (i32.const 1))
+ (global $field@Foo (mut i32) (i32.const 0))
- ;; CHECK: (func $clinit_@once@_ (type $0)
+ ;; CHECK: (func $clinit_@once@_@Foo (type $0)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
- (func $clinit_@once@_
- (global.set $field-i32 (i32.const 1))
+ (func $clinit_@once@_@Foo
+ (global.set $field@Foo (i32.const 1))
)
)
-;; f_$initialized__ are not hoisted
+;; $$class-initialized are not hoisted
(module
;; CHECK: (type $0 (func))
- ;; CHECK: (global $f_$initialized__ (mut i32) (i32.const 0))
- (global $f_$initialized__ (mut i32) (i32.const 0))
+ ;; CHECK: (global $$class-initialized@Foo (mut i32) (i32.const 0))
+ (global $$class-initialized@Foo (mut i32) (i32.const 0))
- ;; CHECK: (func $clinit_@once@_ (type $0)
- ;; CHECK-NEXT: (global.set $f_$initialized__
+ ;; CHECK: (func $clinit_@once@_@Foo (type $0)
+ ;; CHECK-NEXT: (global.set $$class-initialized@Foo
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
- (func $clinit_@once@_
- (global.set $f_$initialized__ (i32.const 1))
+ (func $clinit_@once@_@Foo
+ (global.set $$class-initialized@Foo (i32.const 1))
+ )
+)
+
+;; Fields from different classes are not hoisted.
+(module
+
+ ;; CHECK: (type $0 (func))
+
+ ;; CHECK: (global $field@Foo (mut i32) (i32.const 0))
+ (global $field@Foo (mut i32) (i32.const 0))
+
+ ;; CHECK: (func $clinit_@once@_@Bar (type $0)
+ ;; CHECK-NEXT: (global.set $field@Foo
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $clinit_@once@_@Bar
+ ;; Note that $clinit is @Bar and field is @Foo.
+ (global.set $field@Foo (i32.const 1))
)
)