dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.26k stars 1.58k forks source link

dart2js uses unsigned shift for '>>' operator while VM uses signed #3109

Closed DartBot closed 9 years ago

DartBot commented 12 years ago

This issue was originally filed by rice@google.com


  Consider the following code:

void main() {   int negativeOne = -1;   if (1 + 1 != 2) negativeOne = 999; // defeat constant-folding in the compiler   print("${negativeOne >> 8}"); }

In the VM, it prints -1, while dart2js prints 16777215. dart2js emits this following code:

$.main = function() {   var negativeOne = -1;   $.print('' + $.stringToString($.shr(negativeOne, 8))); };

$.shr = function(a, b) {   if ($.checkNumbers(a, b) === true) {     if ($.ltB(b, 0)) {       throw $.captureStackTrace($.IllegalArgumentException$1(b));     }     if ($.gtB(b, 31)) {       return 0;     }     return a >>> b;   }   return a.operator$shr$1(b); };

The upshot is that dart2js compiles the dart expression '-1 >> 8' to the js expression '-1 >>> 8', which does not match the VM behavior.

This makes it difficult to implement bit operations reliably in dart2js, which is gating other library work.

iposva-google commented 12 years ago

Shift-right (">>") is a signed shift.


Added Triaged label.

iposva-google commented 12 years ago

cc @floitschG.

rakudrama commented 12 years ago

See Issue #2725 JavaScript supports only 32 bit values for bitwise and shift operations. There will always be some discrepancy between the VM and JavaScript so long as JavaScript native numbers are used. Two possible policies: (1) all results are in the range [-2^31, 2^31) (2) all results are in the range [0, 2^32)

I believe dart2js is consciously implementing (2) because that makes crypto libraries work. frog mostly implements (1).

What we need is a clear description of how (and why) dart2js is dealing with these issues so we can quickly triage this endless list of edge cases as examples of the underlying problem.

floitschG commented 12 years ago

Stephen is right that we always return something in the range [0, 2^32], but the behavior described in this issue is a bug. The idea was to transform "x bitOp y" into (in Dart semantics) (x bitOp y) & 0x32bit I wrongly assumed that (x >> y) & 32bit would be equivalent to JS "x >>> y". I'm going to fix this on Monday.


Added Accepted label.

kasperl commented 12 years ago

Was this fixed in r7899?

floitschG commented 12 years ago

Yes. fixed in r7899.


Added Fixed label.