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

Put extra guardrails for J2CLOpts. #6171

Merged
merged 4 commits into from
Dec 12, 2023
Merged

Put extra guardrails for J2CLOpts. #6171

merged 4 commits into from
Dec 12, 2023

Conversation

gkdn
Copy link
Contributor

@gkdn gkdn commented Dec 12, 2023

The patch puts a new guardrail that will only hoist the field if it is initialized with the owner class.

The constant hoisting optimization in J2CL pass relies on the assumption that clinit that will initialize the field will be executed before the read of the field. That means the field that is optiized is within the same class:

class Foo {
public static final Object field = new Object();
}

Although it is possible to observe the initial value, that is not intention of the developer (which the point of the optimization).

However can also see a similar pattern in following:

class Foo {
public static Object field;
}

class Zoo {
static {
Foo.field = new Object();
}
}

Currently the pass also optimizes it as well since the field is only initialized once and by a clinit. However Zoo clinit is not guaranteed to be run before Foo.field access so it is less safe to speculate on the intention of the developer here hence it is not worth the risk.

FWIW, we haven't seen this issue. But this is something we are also guarding in Closure Compiler so I decided it is worthwhile to do here as well.

The patch puts a new guardrail that will only hoist the field
if it is initialized with the owner class.

The constant hoisting optimization in J2CL pass relies on the
assumption that clinit that will initialize the field will be
executed before the read of the field. That means the field
that is optiized is within the same class:

class Foo {
  public static final Object field = new Object();
}

Although it is possible to observe the initial value, that is
not intention of the developer (which the point of the
optimization).

However can also see a similar pattern in following:

class Foo {
  public static Object field;
}

class Zoo {
  static {
    Foo.field = new Object();
  }
}

Currently the pass also optimizes it as well since the field
is only initialized once and by a clinit. However Zoo clinit
is not guaranteed to be run before Foo.field access so it is
less safe to speculate on the intention of the developer here
hence it is not worth the risk.

FWIW, we haven't seen this issue. But this is something we
are also guarding in Closure Compiler so I decided it is
worthwhile to do here as well.
src/passes/J2CLOpts.cpp Outdated Show resolved Hide resolved
test/lit/passes/j2cl.wast Outdated Show resolved Hide resolved
test/lit/passes/j2cl.wast Outdated Show resolved Hide resolved
gkdn and others added 3 commits December 12, 2023 13:31
Co-authored-by: Alon Zakai <alonzakai@gmail.com>
Co-authored-by: Alon Zakai <alonzakai@gmail.com>
Co-authored-by: Alon Zakai <alonzakai@gmail.com>
@kripken kripken enabled auto-merge (squash) December 12, 2023 21:57
@kripken kripken merged commit da18e25 into WebAssembly:main Dec 12, 2023
14 checks passed
radekdoulik pushed a commit to dotnet/binaryen that referenced this pull request Jul 12, 2024
The patch puts a new guardrail that will only hoist the field
if it is initialized with the owner class.

The constant hoisting optimization in J2CL pass relies on the
assumption that clinit that will initialize the field will be
executed before the read of the field. That means the field
that is optimized is within the same class:

class Foo {
  public static final Object field = new Object();
}

Although it is possible to observe the initial value, that is
not intention of the developer (which the point of the
optimization).

However can also see a similar pattern in following:

class Foo {
  public static Object field;
}

class Zoo {
  static {
    Foo.field = new Object();
  }
}

Currently the pass also optimizes it as well since the field
is only initialized once and by a clinit. However Zoo clinit
is not guaranteed to be run before Foo.field access so it is
less safe to speculate on the intention of the developer here
hence it is not worth the risk.

FWIW, we haven't seen this issue. But this is something we
are also guarding in Closure Compiler so I decided it is
worthwhile to do here as well.
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.

2 participants