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: use type information to simplify type checks (guards and is checks) #9836

Closed
sethladd opened this issue Apr 11, 2013 · 10 comments
Closed

Comments

@sethladd
Copy link
Contributor

Hi, hope this is a useful report.

Consider this code:

main() {
  var map = {};
  map['fruits'] = ['apples', 'oranges'];

  var fruits = map['fruits'];
  if (fruits is! List) return;

  for (var i = 0; i < fruits.length; i++) {
    print(fruits[i]);
  }
}

My expectation is that if fruits is not a list, the for loop is never encountered, and that my manual type guard is sufficient.

However, here's the dart2js compiled code:

$.main = function() {
  var map, fruits, i;
  map = $.makeLiteralMap([]);
  map.$indexSet(map, "fruits", ["apples", "oranges"]);
  fruits = map.$index(map, "fruits");
  if (!(typeof fruits === "object" && fruits !== null && (fruits.constructor === Array || !!$.getInterceptor(fruits).$isList)))
    return;
  else if (typeof fruits !== "object" || fruits === null || fruits.constructor !== Array && !$.getInterceptor(fruits).$isJavaScriptIndexingBehavior)
    return $.main$bailout(1, fruits);
  for (i = 0; i < fruits.length; ++i)
    $.Primitives_printString($.toString$0(fruits[i]));
};

Shouldn't my manual type guard be sufficient? Can we drop the "else if" guard?

Thanks for taking a look!

@kasperl
Copy link

kasperl commented Apr 11, 2013

I think what you're seeing here is that you check for any List, but in order for us to use fruits[i] in the generated code we have to make sure that it is a builtin List (represented as a JS array).

Clearly the code could be much nicer if we realized that we know something about fruits after the 'is List' check passes. We know it's non-null and we know it's an object that implements List (I think we actually know that in the compiler). It seems like all we need to do to generate vastly better code here is to improve the is checks by using information about the type of the checked instruction in visitTypeGuard, handleNumberOrStringSupertypeCheck, handleStringSupertypeCheck, and handleListOrSupertypeCheck in codegen.dart.


Added this to the M5 milestone.
Changed the title to: "dart2js: use type information to simplify type checks (guards and is checks)".

@kasperl
Copy link

kasperl commented Apr 11, 2013

We just chatted a bit more about this at the office and it would also be possible for us to realize when all Lists in a program implement JavaScriptIndexingBehavior and optimize the second check away in that case.

@sethladd
Copy link
Contributor Author

Awesome, thanks for the great update. Playing with dart2js is a lot of fun. Keep up the good work!

@kasperl
Copy link

kasperl commented Apr 22, 2013

Removed this from the M5 milestone.
Added this to the Later milestone.

@kasperl
Copy link

kasperl commented May 23, 2013

Added TriageForM5 label.

@kasperl
Copy link

kasperl commented May 28, 2013

Have this been fixed already?

@kasperl
Copy link

kasperl commented May 28, 2013

Removed TriageForM5 label.

@kasperl
Copy link

kasperl commented Jul 10, 2014

Removed this from the Later milestone.
Added Oldschool-Milestone-Later label.

@kasperl
Copy link

kasperl commented Aug 4, 2014

Removed Oldschool-Milestone-Later label.

@karlklose
Copy link
Contributor

Verified fixed in 79a8654.

@kevmoo kevmoo removed the triaged label Mar 1, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants