Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc0b6ce2

Browse files
authored
Merge pull request#5194 from sjrd/no-touint-in-lib
Remove all user-space asUint/toUint in the libraries.
2 parentsab9ba4a +5fb3aab commitc0b6ce2

File tree

9 files changed

+112
-35
lines changed

9 files changed

+112
-35
lines changed

‎javalib/src/main/scala/java/lang/Integer.scala

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,9 @@ object Integer {
298298
@inlinedeftoUnsignedLong(x:Int): scala.Long=
299299
thrownewError("stub")// body replaced by the compiler back-end
300300

301+
@inlineprivate[lang]deftoUnsignedDouble(x:Int): scala.Double=
302+
toUnsignedLong(x).toDouble
303+
301304
// Wasm intrinsic
302305
defbitCount(i: scala.Int): scala.Int= {
303306
/* See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
@@ -405,11 +408,6 @@ object Integer {
405408

406409
@inlineprivate[this]deftoStringBase(i: scala.Int,base: scala.Int):String= {
407410
importjs.JSNumberOps.enableJSNumberOps
408-
asUint(i).toString(base)
409-
}
410-
411-
@inlineprivatedefasUint(n: scala.Int): scala.Double= {
412-
importjs.DynamicImplicits.number2dynamic
413-
(n.toDouble>>>0).asInstanceOf[scala.Double]
411+
toUnsignedDouble(i).toString(base)
414412
}
415413
}

‎javalib/src/main/scala/java/lang/Long.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ package java.lang
1515
importscala.annotation.{switch,tailrec}
1616

1717
importjava.lang.constant.{Constable,ConstantDesc}
18-
importjava.lang.Utils.toUint
1918
importjava.util.ScalaOps._
2019

2120
importscala.scalajs.js
@@ -169,7 +168,7 @@ object Long {
169168
if (hi==0) {
170169
// It's an unsigned int32
171170
importjs.JSNumberOps.enableJSNumberOps
172-
Utils.toUint(lo).toString(radix)
171+
Integer.toUnsignedDouble(lo).toString(radix)
173172
}else {
174173
toUnsignedStringInternalLarge(lo, hi, radix)
175174
}
@@ -186,7 +185,8 @@ object Long {
186185
}
187186

188187
valTwoPow32= (1L<<32).toDouble
189-
valapproxNum= toUint(hi)*TwoPow32+ toUint(lo)
188+
valapproxNum=
189+
Integer.toUnsignedDouble(hi)*TwoPow32+Integer.toUnsignedDouble(lo)
190190

191191
if ((hi&0xffe00000)==0) {// see RuntimeLong.isUnsignedSafeDouble
192192
// (lo, hi) is small enough to be a Double, so approxNum is exact

‎javalib/src/main/scala/java/lang/Utils.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,4 @@ private[java] object Utils {
187187
false
188188
// scalastyle:on return
189189
}
190-
191-
@inlinedeftoUint(x: scala.Double): scala.Double= {
192-
importjs.DynamicImplicits.number2dynamic
193-
(x>>>0).asInstanceOf[scala.Double]
194-
}
195190
}

‎library/src/main/scala/scala/scalajs/js/JSNumberOps.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,19 @@ object JSNumberOps {
7979
implicitdefenableJSNumberOps(x:Double): js.JSNumberOps=
8080
x.asInstanceOf[js.JSNumberOps]
8181

82+
@deprecated("Use Integer.toUnsignedLong(x).toDouble instead of toUint.", since="1.20.0")
8283
implicitdefenableJSNumberExtOps(x:Int):ExtOps=
8384
newExtOps(x.asInstanceOf[js.Dynamic])
8485

86+
@deprecated("Use Integer.toUnsignedLong(x).toDouble instead of toUint.", since="1.20.0")
8587
implicitdefenableJSNumberExtOps(x:Double):ExtOps=
8688
newExtOps(x.asInstanceOf[js.Dynamic])
8789

90+
@deprecated("Use Integer.toUnsignedLong(x).toDouble instead of toUint.", since="1.20.0")
8891
finalclassExtOpsprivate[JSNumberOps] (privatevalself: js.Dynamic)
8992
extendsAnyVal {
9093

94+
@deprecated("Use Integer.toUnsignedLong(x).toDouble instead.", since="1.20.0")
9195
@inlinedeftoUint:Double=
9296
(self>>>0.asInstanceOf[js.Dynamic]).asInstanceOf[Double]
9397
}

‎linker-private-library/src/main/scala/org/scalajs/linker/runtime/FloatingPointBitsPolyfills.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ object FloatingPointBitsPolyfills {
8686
valfbits=52
8787
valhifbits= fbits-32
8888
valhi= (bits>>>32).toInt
89-
vallo=toUint(bits.toInt)
89+
vallo= (bits& 0xffffffffL).toDouble
9090
valsign= (hi>>31)|1// -1 or 1
9191
vale= (hi>> hifbits)& ((1<< ebits)-1)
9292
valf= (hi& ((1<< hifbits)-1)).toDouble* 0x100000000L.toDouble+ lo
@@ -181,9 +181,6 @@ object FloatingPointBitsPolyfills {
181181
}
182182
}
183183

184-
@inlineprivatedeftoUint(x:Int):Double=
185-
(x.asInstanceOf[js.Dynamic]>>>0.asInstanceOf[js.Dynamic]).asInstanceOf[Double]
186-
187184
@inlineprivatedefrawToInt(x:Double):Int=
188185
(x.asInstanceOf[js.Dynamic]|0.asInstanceOf[js.Dynamic]).asInstanceOf[Int]
189186

‎linker-private-library/src/main/scala/org/scalajs/linker/runtime/RuntimeLong.scala

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ object RuntimeLong {
671671
valdivisorInv=1.0/ divisor.toDouble
672672

673673
// initial approximation of the quotient and remainder
674-
valapproxNum=asUint(hi)*TwoPow32+ asUint(lo)
674+
valapproxNum=unsignedToDoubleApprox(lo, hi)
675675
varapproxQuot= scala.scalajs.js.Math.floor(approxNum* divisorInv)
676676
varapproxRem= lo- divisor* unsignedSafeDoubleLo(approxQuot)
677677

@@ -695,16 +695,15 @@ object RuntimeLong {
695695
a.lo
696696

697697
@inline
698-
deftoDouble(a:RuntimeLong):Double=
699-
toDouble(a.lo, a.hi)
700-
701-
privatedeftoDouble(lo:Int,hi:Int):Double= {
698+
deftoDouble(a:RuntimeLong):Double= {
699+
vallo= a.lo
700+
valhi= a.hi
702701
if (hi<0) {
703-
// Wedo asUint() on the hi part specifically for MinValue
702+
// Weneed unsignedToDoubleApprox specifically for MinValue
704703
valneg= inline_negate(lo, hi)
705-
-(asUint(neg.hi)*TwoPow32+ asUint(neg.lo))
704+
-unsignedToDoubleApprox(neg.lo,neg.hi)
706705
}else {
707-
hi*TwoPow32+ asUint(lo)
706+
nonNegativeToDoubleApprox(lo, hi)
708707
}
709708
}
710709

@@ -761,8 +760,7 @@ object RuntimeLong {
761760
if (isUnsignedSafeDouble(abs.hi)|| (abs.lo&0xffff)==0) abs.lo
762761
else (abs.lo&~0xffff)|0x8000
763762

764-
// We do asUint() on the hi part specifically for MinValue
765-
valabsRes= (asUint(abs.hi)*TwoPow32+ asUint(compressedAbsLo))
763+
valabsRes= unsignedToDoubleApprox(compressedAbsLo, abs.hi)
766764

767765
(if (hi<0)-absReselse absRes).toFloat
768766
}
@@ -1205,7 +1203,7 @@ object RuntimeLong {
12051203

12061204
/** Converts an unsigned safe double into its Double representation.*/
12071205
@inlinedefasUnsignedSafeDouble(lo:Int,hi:Int):Double=
1208-
hi*TwoPow32+ asUint(lo)
1206+
nonNegativeToDoubleApprox(lo, hi)
12091207

12101208
/** Converts an unsigned safe double into its RuntimeLong representation.*/
12111209
@inlinedeffromUnsignedSafeDouble(x:Double):RuntimeLong=
@@ -1219,10 +1217,27 @@ object RuntimeLong {
12191217
@inlinedefunsignedSafeDoubleHi(x:Double):Int=
12201218
rawToInt(x/TwoPow32)
12211219

1220+
/** Approximates an unsigned (lo, hi) with a Double.*/
1221+
@inlinedefunsignedToDoubleApprox(lo:Int,hi:Int):Double=
1222+
uintToDouble(hi)*TwoPow32+ uintToDouble(lo)
1223+
1224+
/** Approximates a non-negative (lo, hi) with a Double.
1225+
*
1226+
* If `hi` is known to be non-negative, this method is equivalent to
1227+
* `unsignedToDoubleApprox`, but it can fold away part of the computation if
1228+
* `hi` is in fact constant.
1229+
*/
1230+
@inlinedefnonNegativeToDoubleApprox(lo:Int,hi:Int):Double=
1231+
hi.toDouble*TwoPow32+ uintToDouble(lo)
1232+
12221233
/** Interprets an `Int` as an unsigned integer and returns its value as a
12231234
* `Double`.
1235+
*
1236+
* In user space, this would be `Integer.toUnsignedLong(x).toDouble`.
1237+
* However, we cannot use that, since it would circle back here into an
1238+
* infinite recursion.
12241239
*/
1225-
@inlinedefasUint(x:Int):Double= {
1240+
@inlinedefuintToDouble(x:Int):Double= {
12261241
importscala.scalajs.js.DynamicImplicits.number2dynamic
12271242
(x.toDouble>>>0).asInstanceOf[Double]
12281243
}

‎linker/shared/src/main/scala/org/scalajs/linker/backend/wasmemitter/WasmTransients.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ object WasmTransients {
6060
caseF64Floor=> wa.F64Floor
6161
caseF64Nearest=> wa.F64Nearest
6262
caseF64Sqrt=> wa.F64Sqrt
63+
64+
caseF64ConvertI32U=> wa.F64ConvertI32U
6365
}
6466

6567
defprintIR(out:IRTreePrinter):Unit= {
@@ -87,6 +89,8 @@ object WasmTransients {
8789
finalvalF64Nearest=9
8890
finalvalF64Sqrt=10
8991

92+
finalvalF64ConvertI32U=11
93+
9094
defresultTypeOf(op:Code):Type= (op:@switch)match {
9195
caseI32Ctz|I32Popcnt=>
9296
IntType
@@ -97,7 +101,7 @@ object WasmTransients {
97101
caseF32Abs=>
98102
FloatType
99103

100-
caseF64Abs|F64Ceil|F64Floor|F64Nearest|F64Sqrt=>
104+
caseF64Abs|F64Ceil|F64Floor|F64Nearest|F64Sqrt|F64ConvertI32U=>
101105
DoubleType
102106
}
103107
}

‎linker/shared/src/main/scala/org/scalajs/linker/frontend/optimizer/OptimizerCore.scala

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,40 @@ private[optimizer] abstract class OptimizerCore(
646646
JSUnaryOp(op, transformExpr(lhs))
647647

648648
caseJSBinaryOp(op, lhs, rhs)=>
649-
JSBinaryOp(op, transformExpr(lhs), transformExpr(rhs))
649+
valnewTree=JSBinaryOp(op, transformExpr(lhs), transformExpr(rhs))
650+
651+
// Introduce casts for some idioms that are guaranteed to return certain types
652+
653+
// Is `arg` guaranteed to evaluate to a JS `number` (and hence, not a `bigint`)?
654+
defisJSNumber(arg:Tree):Boolean= arg.tpematch {
655+
caseIntType|DoubleType|ByteType|ShortType|FloatType=>true
656+
case _=>false
657+
}
658+
659+
newTreematch {
660+
/* Unless it throws, `x | y` returns either a signed 32-bit integer
661+
* (an `Int`) or a bigint.
662+
*
663+
* The only case in which it returns a bigint is when both arguments
664+
* are (convertible to) bigint's. Custom objects can be converted to
665+
* bigint's if their `valueOf()` method returns a bigint.
666+
*
667+
* Primitive numbers cannot be implicitly converted to bigint's.
668+
* `x | y` throws if one side is a number and the other is (converted
669+
* to) a bigint. Therefore, if at least one of the arguments is known
670+
* to be a primitive number, we know that `x | y` will return a
671+
* signed 32-bit integer (or throw).
672+
*/
673+
caseJSBinaryOp(JSBinaryOp.|, x, y)if isJSNumber(x)|| isJSNumber(y)=>
674+
makeCast(newTree,IntType)
675+
676+
// >>> always returns a positive number in the unsigned 32-bit range (it rejects bigints)
677+
caseJSBinaryOp(JSBinaryOp.>>>, _, _)=>
678+
makeCast(newTree,DoubleType)
679+
680+
case _=>
681+
newTree
682+
}
650683

651684
caseJSArrayConstr(items)=>
652685
JSArrayConstr(transformExprsOrSpreads(items))
@@ -3790,6 +3823,23 @@ private[optimizer] abstract class OptimizerCore(
37903823
PreTransLit(DoubleLiteral(v.toDouble))
37913824
casePreTransUnaryOp(IntToLong, x)=>
37923825
foldUnaryOp(IntToDouble, x)
3826+
3827+
/* (double) <toLongUnsigned>(x) --> <unsignedIntToDouble>(x)
3828+
*
3829+
* On Wasm, there is a dedicated transient. On JS, that is (x >>> 0).
3830+
*
3831+
* The latter only kicks in when using bigints for longs. When using
3832+
* RuntimeLong, we have eagerly expanded the `UnsignedIntToLong`
3833+
* operation, but further inlining and folding will yield the same
3834+
* result.
3835+
*/
3836+
casePreTransUnaryOp(UnsignedIntToLong, x)=>
3837+
valnewX= finishTransformExpr(x)
3838+
valresultTree=
3839+
if (isWasm)Transient(WasmUnaryOp(WasmUnaryOp.F64ConvertI32U, newX))
3840+
else makeCast(JSBinaryOp(JSBinaryOp.>>>, newX,IntLiteral(0)),DoubleType)
3841+
resultTree.toPreTransform
3842+
37933843
case _=>
37943844
default
37953845
}
@@ -5021,6 +5071,20 @@ private[optimizer] abstract class OptimizerCore(
50215071
case (PreTransLit(DoubleLiteral(l)),PreTransLit(DoubleLiteral(r)))=>
50225072
doubleLit(l+ r)
50235073

5074+
/* ±0.0 + cast(a >>> b, DoubleType) --> cast(a >>> b, DoubleType)
5075+
*
5076+
* In general, `+0.0 + y -> y` is not a valid rewrite, because it does
5077+
* not give the same result when y is -0.0. (Paradoxically, with -0.0
5078+
* on the left it *is* a valid rewrite, though not a very useful one.)
5079+
*
5080+
* However, if y is the result of a JS `>>>` operator, we know it
5081+
* cannot be -0.0, hence the rewrite is valid. That particular shape
5082+
* appears in the inlining of `Integer.toUnsignedLong(x).toDouble`.
5083+
*/
5084+
case (PreTransLit(DoubleLiteral(0.0)),// also matches -0.0
5085+
PreTransTree(Transient(Cast(JSBinaryOp(JSBinaryOp.>>>, _, _),DoubleType)), _))=>
5086+
rhs
5087+
50245088
case _=> default
50255089
}
50265090

‎project/Build.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,8 +2060,8 @@ object Build {
20602060
))
20612061
}else {
20622062
Some(ExpectedSizes(
2063-
fastLink=425000 to426000,
2064-
fullLink=282000 to283000,
2063+
fastLink=426000 to427000,
2064+
fullLink=283000 to284000,
20652065
fastLinkGz=61000 to62000,
20662066
fullLinkGz=43000 to44000,
20672067
))
@@ -2070,7 +2070,7 @@ object Build {
20702070
case `default213Version`=>
20712071
if (!useMinifySizes) {
20722072
Some(ExpectedSizes(
2073-
fastLink=442000 to443000,
2073+
fastLink=443000 to444000,
20742074
fullLink=90000 to91000,
20752075
fastLinkGz=57000 to58000,
20762076
fullLinkGz=24000 to25000,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp