Skip to content

dart2js: bitwise operators truncated to 32 bits #8298

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

Closed
DartBot opened this issue Feb 4, 2013 · 8 comments
Closed

dart2js: bitwise operators truncated to 32 bits #8298

DartBot opened this issue Feb 4, 2013 · 8 comments
Labels
closed-as-intended Closed as the reported issue is expected behavior web-dart2js

Comments

@DartBot
Copy link

DartBot commented Feb 4, 2013

This issue was originally filed by [email protected]


This is related to issue #638.

What steps will reproduce the problem?

main() {
  num val = 0;
  for (int i = 0; i <= 32; i++) {
    val = val > 0 ? val << 1 : 1;
    print("${1 << i}, $val");
  }
}

What is the expected output? What do you see instead?

DartVM outputs the correct result, but the output from dart2js outputs 0 for i == 32.
Probabl not related, but the ternary operator also wasn't converted properly:

  $.main = function() {
    var val, i;
    for (val = 0, i = 0; i <= 64; ++i) {
      val = val === 0 ? 1 : val << 1 >>> 0;
      $.print($.S($.CONSTANT.$shl(1, i)) + ", " + $.S(val));
    }
  };

What version of the product are you using? On what operating system?

0.3.2_r17657 - Arch Linux

Please provide any additional information below.

I checked the generated code, and I found this for the implementation for the shift operator:

  $shl: function(receiver, other) {
    if (other < 0)
      throw $.$$throw($.ArgumentError$(other));
    if (other > 31)
      return 0;
    return (receiver << other) >>> 0;
  },

This seems to have been done because JavaScript is unreliable for bit operations > 30 bits (the >>> 0 hack was pretty clever for 31). As noted in the linked issue, JavaScript is reliable for arithmetic operations up to 53 bits, so a potential solution is to use arithmetic operations for numbers > 31.

In my code, I have modified the $sh1 function like so:

  $shl: function(receiver, other) {
    var i;
    if (other < 0)
      throw $.$$throw($.ArgumentError$(other));
    if (other > 31) {
      for (i = 0; i < other; i++)
        receiver *= 2;
      return receiver;
    }
    return (receiver << other) >>> 0;
  },

This seems to work up to around 53 bits or so. This isn't very elegant, but it makes working with 32-bit numbers possible with dart2js. I have some packages I'd like to port to Dart (written in JS) that need 32-bit number manipulation. In JS, I've written shims to get it to work, but it would be nice for it to work with Dart's native shift operators.

@kasperl
Copy link

kasperl commented Feb 5, 2013

This is actually working as intended for now. The bitwise operations are truncated to 32-bit unsigned values because JavaScript's bitwise operations only work on 32-bit (signed or unsigned) values.

It makes a lot of sense to strive for making Dart compiled to JavaScript deal nicely with 32-bit numbers and bitwise operations. Are you being burnt by the fact that we always produce unsigned results? If you have an example of an algorithm written in JS that use 32-bit numbers and manipulate them with bitwise operations that's hard to port to Dart, I would be very interested in taking a look.


Added Area-Dart2JS, NeedsInfo labels.
Changed the title to: "dart2js: bitwise operators truncated to 31 bits".

@kasperl
Copy link

kasperl commented Feb 6, 2013

Added this to the Later milestone.

@DartBot
Copy link
Author

DartBot commented Feb 7, 2013

This comment was originally written by [email protected]


Here's an example, gzip:

https://github.com/beatgammit/gzip-js

On line 84 of lib/gzip.js, I have to a nasty hack to get a 64-bit long (mtime) from a file. Here's a link to that specific line: https://github.com/beatgammit/gzip-js/blob/master/lib/gzip.js#L84

The problem is, some operations are signed, some are unsigned. The logical | appears to be signed, which makes absolutely no sense to me. The same applies to left shift (<<) and right shift (>>), which are both signed. There's no unsigned left shift that I've found.

For example, in JS:

0xffffffff | 0 == -1

And in Dart:

0xffffffff | 0 == 4294967295

I couldn't find any documentation in the Dart spec about signed vs unsigned numbers. I also couldn't find anything specific about whether the | is supposed to be signed in EcmaScript, but it appears to be implemented that way in every implementation I've tried.

@kasperl
Copy link

kasperl commented Feb 12, 2013

FWIW, the only bitwise operation in JS that gives an unsigned 32-bit result is >>>. All the others give you a signed 32-bit result.

In Dart, we've decided to keep the result of all bitwise operations unsigned 32-bit values when compiling to JavaScript. The intent was to make it easier to make your code work on both the Dart VM and using dart2js.

@DartBot
Copy link
Author

DartBot commented Feb 16, 2013

This comment was originally written by [email protected]


After further investigation, my contrived example that lead me to complain was shifting by more than 32 bits and back again. The Dart2js implementation only allows shifts of up to 31 bits, which makes sense for a 32-bit limit.

I haven't been able to break it again since, so it seems that the implementation is correct for 32 bits.

It would be nice to have support for larger integers but I personally don't have a need yet. I'm removing my star because my intent for this issue was actually a misunderstanding.

@kasperl
Copy link

kasperl commented Feb 18, 2013

Thanks for the extra information!

Updating bug summary to "truncated to 32 bits" and marking this "as designed" for now.


Added AsDesigned label.
Changed the title to: "dart2js: bitwise operators truncated to 32 bits".

@peter-ahe-google
Copy link
Contributor

This may be how dart2js is currently designed, but I'm not sure this is how Dart is designed. Shouldn't we keep this bug open until we have fixed the implementation in dart2js?

@kasperl
Copy link

kasperl commented Feb 18, 2013

We already have issue #638 to track the differences between Dart and dart2js.

@DartBot DartBot added Type-Defect web-dart2js closed-as-intended Closed as the reported issue is expected behavior labels Feb 18, 2013
@DartBot DartBot added this to the Later milestone Feb 18, 2013
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-as-intended Closed as the reported issue is expected behavior web-dart2js
Projects
None yet
Development

No branches or pull requests

3 participants