@@ -191,22 +191,6 @@ function isPointerType(type) {
191191 return type [ type . length - 1 ] == '*' ;
192192}
193193
194- function isIntImplemented ( type ) {
195- return type [ 0 ] == 'i' || type [ 0 ] == 'u' || isPointerType ( type ) ;
196- }
197-
198- // Note: works for iX types and structure types, not pointers (even though they are implemented as ints)
199- function getBits ( type , allowPointers ) {
200- if ( allowPointers && isPointerType ( type ) ) return POINTER_SIZE ;
201- if ( ! type ) return 0 ;
202- if ( type [ 0 ] == 'i' || type [ 0 ] == 'u' ) {
203- const left = type . substr ( 1 ) ;
204- if ( ! isNumber ( left ) ) return 0 ;
205- return parseInt ( left ) ;
206- }
207- return 0 ;
208- }
209-
210194// Given an expression like (VALUE=VALUE*2,VALUE<10?VALUE:t+1) , this will
211195// replace VALUE with value. If value is not a simple identifier of a variable,
212196// value will be replaced with tempVar.
@@ -405,12 +389,13 @@ function makeHEAPView(which, start, end) {
405389 return `HEAP${ which } .subarray((${ start } )${ mod } , (${ end } )${ mod } )` ;
406390}
407391
408- const TWO_TWENTY = Math . pow ( 2 , 20 ) ;
409-
410392// Given two values and an operation, returns the result of that operation.
411393// Tries to do as much as possible at compile time.
412- // Leaves overflows etc. unhandled, *except* for integer multiply, in order to be efficient with Math.imul
413- function getFastValue ( a , op , b , type ) {
394+ function getFastValue ( a , op , b ) {
395+ // In the past we supported many operations, but today we only use addition.
396+ assert ( op == '+' ) ;
397+
398+ // Convert 'true' and 'false' to '1' and '0'.
414399 a = a === 'true' ? '1' : ( a === 'false' ? '0' : a ) ;
415400 b = b === 'true' ? '1' : ( b === 'false' ? '0' : b ) ;
416401
@@ -419,95 +404,47 @@ function getFastValue(a, op, b, type) {
419404 if ( typeof a == 'number' ) {
420405 aNumber = a ;
421406 a = a . toString ( ) ;
422- } else if ( isNumber ( a ) ) aNumber = parseFloat ( a ) ;
407+ } else if ( isNumber ( a ) ) {
408+ aNumber = parseFloat ( a ) ;
409+ }
423410 if ( typeof b == 'number' ) {
424411 bNumber = b ;
425412 b = b . toString ( ) ;
426- } else if ( isNumber ( b ) ) bNumber = parseFloat ( b ) ;
413+ } else if ( isNumber ( b ) ) {
414+ bNumber = parseFloat ( b ) ;
415+ }
427416
417+ // First check if we can do the addition at compile time
428418 if ( aNumber !== null && bNumber !== null ) {
429- switch ( op ) {
430- case '+' : return ( aNumber + bNumber ) . toString ( ) ;
431- case '-' : return ( aNumber - bNumber ) . toString ( ) ;
432- case '*' : return ( aNumber * bNumber ) . toString ( ) ;
433- case '/' : {
434- if ( type [ 0 ] === 'i' ) {
435- return ( ( aNumber / bNumber ) | 0 ) . toString ( ) ;
436- }
437- return ( aNumber / bNumber ) . toString ( ) ;
438- }
439- case '%' : return ( aNumber % bNumber ) . toString ( ) ;
440- case '|' : return ( aNumber | bNumber ) . toString ( ) ;
441- case '>>>' : return ( aNumber >>> bNumber ) . toString ( ) ;
442- case '&' : return ( aNumber & bNumber ) . toString ( ) ;
443- case 'pow' : return Math . pow ( aNumber , bNumber ) . toString ( ) ;
444- default : assert ( false , 'need to implement getFastValue pn ' + op ) ;
445- }
419+ return ( aNumber + bNumber ) . toString ( ) ;
446420 }
447- if ( op === 'pow' ) {
448- if ( a === '2' && isIntImplemented ( type ) ) {
449- return `(1 << (${ b } ))` ;
450- }
451- return `Math.pow(${ a } , ${ b } )` ;
452- }
453- if ( ( op === '+' || op === '*' ) && aNumber !== null ) { // if one of them is a number, keep it last
421+
422+ // If one of them is a number, keep it last
423+ if ( aNumber !== null ) {
454424 const c = b ;
455425 b = a ;
456426 a = c ;
457427 const cNumber = bNumber ;
458428 bNumber = aNumber ;
459429 aNumber = cNumber ;
460430 }
461- if ( op === '*' ) {
462- // We can't eliminate where a or b are 0 as that would break things for creating
463- // a negative 0.
464- if ( ( aNumber === 0 || bNumber === 0 ) && ! FLOAT_TYPES . has ( type ) ) {
465- return '0' ;
466- } else if ( aNumber === 1 ) {
467- return b ;
468- } else if ( bNumber === 1 ) {
469- return a ;
470- } else if ( bNumber !== null && type && isIntImplemented ( type ) && Runtime . getNativeTypeSize ( type ) <= 32 ) {
471- const shifts = Math . log ( bNumber ) / Math . LN2 ;
472- if ( shifts % 1 === 0 ) {
473- return `(${ a } <<${ shifts } )` ;
474- }
475- }
476- if ( ! FLOAT_TYPES . has ( type ) ) {
477- // if guaranteed small enough to not overflow into a double, do a normal multiply
478- // default is 32-bit multiply for things like getelementptr indexes
479- const bits = getBits ( type ) || 32 ;
480- // Note that we can emit simple multiple in non-asm.js mode, but asm.js
481- // will not parse "16-bit" multiple, so must do imul there
482- if ( ( aNumber !== null && Math . abs ( a ) < TWO_TWENTY ) || ( bNumber !== null && Math . abs ( b ) < TWO_TWENTY ) ) {
483- // keep a non-eliminatable coercion directly on this
484- return `(((${ a } )*(${ b } ))&${ ( Math . pow ( 2 , bits ) - 1 ) | 0 } )` ;
485- }
486- return `(Math.imul(${ a } , ${ b } )|0)` ;
487- }
488- } else if ( op === '/' ) {
489- // careful on floats, since 0*NaN is not 0
490- if ( a === '0' && ! FLOAT_TYPES . has ( type ) ) {
491- return '0' ;
492- } else if ( b === 1 ) {
493- return a ;
494- } // Doing shifts for division is problematic, as getting the rounding right on negatives is tricky
495- } else if ( op === '+' || op === '-' ) {
496- if ( b [ 0 ] === '-' ) {
497- op = op === '+' ? '-' : '+' ;
498- b = b . substr ( 1 ) ;
499- }
500- if ( aNumber === 0 ) {
501- return op === '+' ? b : `(-${ b } )` ;
502- } else if ( bNumber === 0 ) {
503- return a ;
504- }
431+
432+ if ( aNumber === 0 ) {
433+ return b ;
434+ } else if ( bNumber === 0 ) {
435+ return a ;
505436 }
437+
438+ if ( b [ 0 ] === '-' ) {
439+ op = '-'
440+ b = b . substr ( 1 ) ;
441+ }
442+
506443 return `(${ a } )${ op } (${ b } )` ;
507444}
508445
509446function calcFastOffset ( ptr , pos ) {
510- return getFastValue ( ptr , '+' , pos , 'i32' ) ;
447+ return getFastValue ( ptr , '+' , pos ) ;
511448}
512449
513450function getHeapForType ( type ) {
0 commit comments