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 miscompiles -1>>1 #21626

Closed
DartBot opened this issue Nov 16, 2014 · 5 comments
Closed

Dart2js miscompiles -1>>1 #21626

DartBot opened this issue Nov 16, 2014 · 5 comments
Labels
closed-duplicate Closed in favor of an existing report

Comments

@DartBot
Copy link

DartBot commented Nov 16, 2014

This issue was originally filed by [email protected]


What steps will reproduce the problem?

  1. echo "void main(){ print(-1>>1); }" >bug.dart
  2. dart2js bug.dart
  3. js24 out.js # or use whatever your favorite js interp is

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

Expected output: -1
Actual printout: 4294967295

What version of the product are you using?

Dart-to-JavaScript compiler (dart2js) version: 1.7.2

On what operating system?

Ubuntu 12.04

Please provide any additional information below.

dart2js computes -1>>1 at compile and puts the string 4294967295 directly into out.js but the problem is not limited to this case. The same bug happens when the computation is actual performed at runtime.

@DartBot
Copy link
Author

DartBot commented Nov 16, 2014

This comment was originally written by [email protected]


In the non-compile time constant case I get the following in out.js:

_shrOtherPositive$1: function(receiver, other) {
      var t1;
      if (receiver > 0)
        t1 = other > 31 ? 0 : receiver >>> other;
      else {
        t1 = other > 31 ? 31 : other;
        t1 = receiver >> t1 >>> 0;
      }
      return t1;

 The problem seems to be that this functions uses >>>. I have no idea why it's written that way. In fact I'm mystified that dart2js wants to insert such a wrapper function anyway. Why not compile ">>" straight to Javascript's ">>". After all you do not support >32bit integers with shifts in dart2js and silently produce incorrect results in that case.

@DartBot
Copy link
Author

DartBot commented Nov 16, 2014

This comment was originally written by [email protected]


Here is a little program that shows the shrOtherPositive case where the expression is miscomputed at runtime.


Attachment:
bug.dart (128 Bytes)

@sgjesse
Copy link
Contributor

sgjesse commented Nov 17, 2014

Added Duplicate label.
Marked as being merged into #1533.

@DartBot
Copy link
Author

DartBot commented Nov 24, 2014

This comment was originally written by [email protected]


I don't think issue #21626 should be merged into issue #1533. Fixing issue #1533 requires a complex solution, such as big integers, new types,... Issue #21626 is a straight-forward bug where dart2js could easily produce correct code by simply compiling Dart's >> into JavaScript's >>. There is absolutely no reason not to fix issue #21626 with the next Dart update, whereas issue #1533 will probably remain unfixed for a long time.

@rakudrama
Copy link
Member

The use of >>> is deliberate.

The bit level operators |, &, ^ , << and >> only work in JavaScript for a limited range of numbers, basically 32-bit numbers.
There are two kinds of 32-bit numbers, signed with range [-2^31,2^31) and unsigned [0, 2^32).
We can't support both at the same time since that would require more than 32 bits.

We studied a number of programs to see which should be supported.
The winner was unsigned arithmetic since that works best for bitmaps, indexes (JavaScript strings and arrays can have indexes up to 2^32-1) and cryptographic functions.
Relaxing any of the operations to have a signed result caused some classic bitmap or crypto algorithms to fail. The problem is not just >> by itself, but >> in combination with other operations. The unsigned scheme maintained the most algebraic identities, e.g. shifting followed by masking being the same as masking by a shifted constant followed by shifting.

All the bit-level operations in dart2js have the following property:
If both inputs are unsigned 32 bit numbers and the 'correct' (VM with no size limit on integers) result is also a unsigned 32 bit value, then the dart2js result will be the same.
This allows you to write some code portably, but not with negative inputs.

I hope this explanation de-mystifies the behaviour.

@DartBot DartBot added Type-Defect closed-duplicate Closed in favor of an existing report labels Nov 24, 2014
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-duplicate Closed in favor of an existing report
Projects
None yet
Development

No branches or pull requests

4 participants