Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # 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 matthias.benkm...@gmail.com


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 matthias.ben...@gmail.com


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 matthias.ben...@gmail.com


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 matthias.benk...@gmail.com


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.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
closed-duplicate Closed in favor of an existing report
Projects
None yet
Development

No branches or pull requests

4 participants