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

Disable fusion for impure externs #10432

Merged
merged 5 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/optimization/analyzerTexpr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -590,14 +590,24 @@ module Fusion = struct
let can_be_used_as_value = can_be_used_as_value com e in
let is_compiler_generated = match v.v_kind with VUser _ | VInlined -> false | _ -> true in
let has_type_params = match v.v_extra with Some ve when ve.v_params <> [] -> true | _ -> false in
let rec is_impure_extern e = match e.eexpr with
| TField(ef,(FStatic(cl,cf) | FInstance(cl,_,cf))) when has_class_flag cl CExtern ->
not (
Meta.has Meta.CoreApi cl.cl_meta ||
PurityState.is_pure cl cf
)
| _ -> check_expr is_impure_extern e
in
let b = num_uses <= 1 &&
num_writes = 0 &&
can_be_used_as_value &&
not (
ExtType.has_variable_semantics v.v_type &&
(match e.eexpr with TLocal { v_kind = VUser _ } -> false | _ -> true)
) &&
(is_compiler_generated || config.optimize && config.fusion && config.user_var_fusion && not has_type_params)
) && (
is_compiler_generated || config.optimize &&
config.fusion && config.user_var_fusion && not has_type_params && not (is_impure_extern e)
)
in
if config.fusion_debug then begin
print_endline (Printf.sprintf "\nFUSION: %s\n\tvar %s<%i> = %s" (if b then "true" else "false") v.v_name v.v_id (s_expr_pretty e));
Expand Down
55 changes: 55 additions & 0 deletions tests/optimization/src/issues/Issue9943.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package issues;

private extern class Element {
static function get():Element;
var offset(default,null) : Int;
var style(default,null) : CSSStyleDeclaration;
}
@:pure
private extern class PureElement {
static function get():PureElement;
var offset(default,null) : Int;
var style(default,null) : CSSStyleDeclaration;
}
private extern class CSSStyleDeclaration {
var verticalAlign : Int;
}

class Issue9943 {
static final foo = Std.random(0);

@:js('
var el = issues._Issue9943.Element.get();
var a = el.offset + issues_Issue9943.foo;
el.style.verticalAlign = 1;
var b = el.offset + issues_Issue9943.foo;
el.style.verticalAlign = 2;
var c = el.offset + issues_Issue9943.foo;
issues_Issue9943.values(a,b,c);
')
static function test() {
final el = Element.get();
final a = (el.offset + foo);
el.style.verticalAlign = 1;
final b = (el.offset + foo);
el.style.verticalAlign = 2;
final c = (el.offset + foo);
values(a, b, c);
}
@:js('
var el = issues._Issue9943.PureElement.get();
el.style.verticalAlign = 1;
el.style.verticalAlign = 2;
issues_Issue9943.values(el.offset + issues_Issue9943.foo,el.offset + issues_Issue9943.foo,el.offset + issues_Issue9943.foo);
')
static function test2() {
final el = PureElement.get();
final a = (el.offset + foo);
el.style.verticalAlign = 1;
final b = (el.offset + foo);
el.style.verticalAlign = 2;
final c = (el.offset + foo);
values(a, b, c);
}
static function values(a, b, c) trace(a, b, c);
}