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

dart2js appears to be discarding referenced functions #18383

Closed
blois opened this issue Apr 22, 2014 · 11 comments
Closed

dart2js appears to be discarding referenced functions #18383

blois opened this issue Apr 22, 2014 · 11 comments
Labels
P1 A high priority bug; for example, a single project is unusable or has many test failures web-dart2js

Comments

@blois
Copy link
Contributor

blois commented Apr 22, 2014

In the attached Angular application (full app is enclosed), I'm seeing errors because functions which are being used appear to be discarded by dart2js.

Repro is to compile with:
dart2js main.dart -o main.dart.js --show-package-warnings --dump-info --checked

Then load index.html in the browser.

The first error when running is because the _StaticAnnotationUriResolver.resolve method is not found on an instance of _StaticAnnotationUriResolver- dart2js appears to not include this function at all.

I was able to add into main.dart:
print(generated_type_uris.uriResolver.resolve);
Which explicitly referenced this method and fixed that issue. According to sra@ the ShadowDomComponentFactory.call method is appearing as not being called and stuff is going wrong from there. I was also able to fix this issue by renaming that to 'create'.

After this I ran into a second similar issue with DefaultTransformDataHttpInterceptor's request function (in packages/angular/core_dom/http.dart).

I can repro this on stable and dev channels.


Attachment:
web.zip (3.21 MB)

@rakudrama
Copy link
Member

By 'appearing as not being called' I mean the typed selector for the call site for 'resolve' has a type of [empty], which prevents it matching any method, including _StaticAnnotationUriResolver.resolve.
This is because the type of receiver is assigned

It seems like type inference does not see that the closure XXX is called, leading to over-aggressive optimization of subsequent code.

class ShadowDomComponentFactory implements ComponentFactory {
  final Expando _expando;

  ShadowDomComponentFactory(this._expando);

  FactoryFn call(dom.Node node, DirectiveRef ref) {
    return (Injector injector) { <-----------------XXXX
        ...
      };
  }
}

From the --dump-info:
+library angular.core.dom_internal 112866 bytes (7%) package:angular/core_dom/module_internal.dart
  ...
  +class ShadowDomComponentFactory implements [ ComponentFactory, Object ]
    +field /* Expando / final _expando 0 bytes (0%)
    +method /
(Node, DirectiveRef) -> FactoryFn / call 1153 bytes (0%)
      Inferred parameter node [null|subclass=Object]
      Inferred parameter ref [null|subclass=Object]
      Inferred return type [subtype=Function]
      Inferred side effects Depends on nothing, Changes static.
      Generated code 136 bytes (0%)
      function(node, ref) {
        return new Y.ShadowDomComponentFactory_call_closure(this, node, ref);
      }
      +closure /
(Injector) -> dynamic */ <unnamed> 1017 bytes (0%) <-------------------------XXX
        Inferred parameter injector [empty]
        Inferred return type [empty]
        Inferred side effects Depends on [] field store static store, Changes [] field static.

Even though the code is unreachable as evidenced by the [empty] type, quite a lot of code is generated along that path.
It might be a good idea to generate 'throw "Unreachable"' as the entire body of any method which has some parameter inferred as [empty]. This would tree-shake out more code rather than leave it in an incorrectly optimized state and cause the failure to be closer to the type inference bug.


cc @herhut-ggl.

@rakudrama
Copy link
Member

This repro demonstrates the problem:


class F {
  call() => (x) => new G(x.toInt());
}

class G {
  var z;
  G(this.z);
  foo() => '$this.foo';
  toString() => 'G($z)';
}

main() {
  var f = new F();
  var m = {};
  m['a'] = f();

  print(m'a'.foo());
}


out.js:775: TypeError: undefined is not a function
      return new A.G(x.toInt$0(0));
                       ^
TypeError: undefined is not a function
    at F_call_closure.call$1 (out.js:775:24)
    at dart.main (out.js:763:29)


x has inferred type [empty].
The body is optimized under that assumption. 'x' does not match any interceptor types, so the call is generated directly.
The body should have either J.JSNumber_methods.toInt$0(x) or some other interceptor-style call.

@rakudrama
Copy link
Member

Stefan - do you know why the function parameters are [empty]?


cc @floitschG.
Set owner to @herhut-ggl.

@ghost
Copy link

ghost commented Apr 24, 2014

Added Accepted label.

@kasperl
Copy link

kasperl commented Apr 24, 2014

The fix for this is probably worth merging to the 1.3 branch if it's simple enough. Please file a merge request if so (Label: MergeToStable).


cc @ricowind.

@ghost
Copy link

ghost commented Apr 25, 2014

Tracing of closures did not consider the [call] member of instances of [Function] to be closures themselves. The fix in r35417 makes the tracer consider all invocations of [call] methods to be a closure call.


Added Fixed label.

@DartBot
Copy link

DartBot commented May 27, 2014

This comment was originally written by vmend...@gmail.com


This is still happening to me in 1.4.0, particularly in DefaultTransformDataHttpInterceptor and only in checked mode.


Attachment:
CheckedMode.png (168.71 KB)

@ghost
Copy link

ghost commented May 27, 2014

Removed this from the 1.4 milestone.
Added Started label.

@DartBot
Copy link

DartBot commented Jun 3, 2014

This comment was originally written by vmen...@gmail.com


herhut: Are you able to reproduce this? Do you need any help to reproduce it? It seems simple, just a regular angulardart project compiled in checked mode, but just tell me if you don't have clues of what's happening and I'll try to help.

Thanks

@ghost
Copy link

ghost commented Jun 3, 2014

I have a fix for this but due to recent holidays in Denmark it took a little longer than usual to get it in. This will be fixed soon.

@ghost
Copy link

ghost commented Jun 4, 2014

This has been fixed as of r36984.


Added Fixed label.

@blois blois added Type-Defect P1 A high priority bug; for example, a single project is unusable or has many test failures web-dart2js labels Jun 4, 2014
@blois blois assigned ghost Jun 4, 2014
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P1 A high priority bug; for example, a single project is unusable or has many test failures web-dart2js
Projects
None yet
Development

No branches or pull requests

4 participants