8000 Drop support for non-strict floats. · scala-js/scala-js@b38201c · GitHub
[go: up one dir, main page]

Skip to content

Commit b38201c

Browse files
committed
Drop support for non-strict floats.
Non-strict floats were deprecated 3 years ago in Scala.js 1.9.0. I don't recall seeing any comment about them ever since.
1 parent 76f7be7 commit b38201c

File tree

24 files changed

+196
-381
lines changed

24 files changed

+196
-381
lines changed

Jenkinsfile

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -232,17 +232,6 @@ def Tasks = [
232232
'set scalaJSLinkerConfig in $testSuite.v$v ~= makeCompliant' \
233233
'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withOptimizer(false))' \
234234
$testSuite$v/test &&
235-
sbtretry ++$scala 'set Global/enableMinifyEverywhere := $testMinify' \
236-
'set scalaJSLinkerConfig in $testSuite.v$v ~= { _.withSemantics(_.withStrictFloats(false)) }' \
237-
$testSuite$v/test &&
238-
sbtretry ++$scala 'set Global/enableMinifyEverywhere := $testMinify' \
239-
'set scalaJSLinkerConfig in $testSuite.v$v ~= { _.withSemantics(_.withStrictFloats(false)) }' \
240-
'set scalaJSStage in Global := FullOptStage' \
241-
$testSuite$v/test &&
242-
sbtretry ++$scala 'set Global/enableMinifyEverywhere := $testMinify' \
243-
'set scalaJSLinkerConfig in $testSuite.v$v ~= { _.withSemantics(_.withStrictFloats(false)) }' \
244-
'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withOptimizer(false))' \
245-
$testSuite$v/test &&
246235
sbtretry ++$scala 'set Global/enableMinifyEverywhere := $testMinify' \
247236
'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withESFeatures(_.withAllowBigIntsForLongs(true)))' \
248237
$testSuite$v/test &&
@@ -312,20 +301,6 @@ def Tasks = [
312301
'set Seq(jsEnv in $testSuite.v$v := new NodeJSEnvForcePolyfills(ESVersion.$esVersion), MyScalaJSPlugin.wantSourceMaps in $testSuite.v$v := ("$esVersion" != "ES5_1"))' \
313302
'set scalaJSLinkerConfig in $testSuite.v$v ~= makeCompliant' \
314303
'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withOptimizer(false))' \
315-
++$scala $testSuite$v/test &&
316-
sbtretry 'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withESFeatures(_.withESVersion(ESVersion.$esVersion)))' \
317-
'set Seq(jsEnv in $testSuite.v$v := new NodeJSEnvForcePolyfills(ESVersion.$esVersion), MyScalaJSPlugin.wantSourceMaps in $testSuite.v$v := ("$esVersion" != "ES5_1"))' \
318-
'set scalaJSLinkerConfig in $testSuite.v$v ~= { _.withSemantics(_.withStrictFloats(false)) }' \
319-
++$scala $testSuite$v/test &&
320-
sbtretry 'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withESFeatures(_.withESVersion(ESVersion.$esVersion)))' \
321-
'set Seq(jsEnv in $testSuite.v$v := new NodeJSEnvForcePolyfills(ESVersion.$esVersion), MyScalaJSPlugin.wantSourceMaps in $testSuite.v$v := ("$esVersion" != "ES5_1"))' \
322-
'set scalaJSLinkerConfig in $testSuite.v$v ~= { _.withSemantics(_.withStrictFloats(false)) }' \
323-
'set scalaJSStage in Global := FullOptStage' \
324-
++$scala $testSuite$v/test &&
325-
sbtretry 'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withESFeatures(_.withESVersion(ESVersion.$esVersion)))' \
326-
'set Seq(jsEnv in $testSuite.v$v := new NodeJSEnvForcePolyfills(ESVersion.$esVersion), MyScalaJSPlugin.wantSourceMaps in $testSuite.v$v := ("$esVersion" != "ES5_1"))' \
327-
'set scalaJSLinkerConfig in $testSuite.v$v ~= { _.withSemantics(_.withStrictFloats(false)) }' \
328-
'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withOptimizer(false))' \
329304
++$scala $testSuite$v/test
330305
''',
331306

@@ -355,17 +330,6 @@ def Tasks = [
355330
'set scalaJSLinkerConfig in $testSuite.v$v ~= makeCompliant' \
356331
'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withOptimizer(false))' \
357332
++$scala $testSuite$v/test &&
358-
sbtretry 'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withESFeatures(_.withESVersion(ESVersion.$esVersion)))' \
359-
'set scalaJSLinkerConfig in $testSuite.v$v ~= { _.withSemantics(_.withStrictFloats(false)) }' \
360-
++$scala $testSuite$v/test &&
361-
sbtretry 'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withESFeatures(_.withESVersion(ESVersion.$esVersion)))' \
362-
'set scalaJSLinkerConfig in $testSuite.v$v ~= { _.withSemantics(_.withStrictFloats(false)) }' \
363-
'set scalaJSStage in Global := FullOptStage' \
364-
++$scala $testSuite$v/test &&
365-
sbtretry 'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withESFeatures(_.withESVersion(ESVersion.$esVersion)))' \
366-
'set scalaJSLinkerConfig in $testSuite.v$v ~= { _.withSemantics(_.withStrictFloats(false)) }' \
367-
'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withOptimizer(false))' \
368-
++$scala $testSuite$v/test &&
369333
sbtretry 'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withESFeatures(_.withESVersion(ESVersion.$esVersion).withAllowBigIntsForLongs(true)))' \
370334
++$scala $testSuite$v/test &&
371335
sbtretry 'set scalaJSLinkerConfig in $testSuite.v$v ~= (_.withESFeatures(_.withESVersion(ESVersion.$esVersion).withAllowBigIntsForLongs(true)).withOptimizer(false))' \

javalib/src/main/scala/java/lang/Float.scala

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,7 @@ object Float {
150150
val zDouble = z.toDouble
151151

152152
if (zDouble == z0) {
153-
/* This branch is always taken when strictFloats are disabled, and there
154-
* is no Math.fround support. In that case, Floats are basically
155-
* equivalent to Doubles, and we make no specific guarantee about the
156-
* result, so we can quickly return `z`.
157-
* More importantly, the computations in the `else` branch assume that
158-
* Float operations are exact, so we must return early.
159-
*
160-
* This branch is also always taken when z0 is 0.0 or Infinity, which the
153+
/* This branch is always taken when z0 is 0.0 or Infinity, which the
161154
* `else` branch assumes does not happen.
162155
*/
163156
z

javalib/src/main/scala/java/lang/FloatingPointBits.scala

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ private[lang] object FloatingPointBits {
149149
float32Array(0) = value
150150
int32Array(0)
151151
} else {
152-
floatToIntBitsPolyfill(value.toDouble)
152+
floatToIntBitsPolyfill(value)
153153
}
154154
}
155155

@@ -181,8 +181,7 @@ private[lang] object FloatingPointBits {
181181
* Note that if typed arrays are not supported, it is almost certain that
182182
* fround is not supported natively, so Float operations are extremely slow.
183183
*
184-
* We therefore do all computations in Doubles here, which is also more
185-
* predictable, since the results do not depend on strict floats semantics.
184+
* We therefore do all computations in Doubles here.
186185
*/
187186

188187
private def intBitsToFloatPolyfill(bits: Int): scala.Double = {
@@ -194,21 +193,23 @@ private[lang] object FloatingPointBits {
194193
decodeIEEE754(ebits, fbits, floatPowsOf2, scala.Float.MinPositiveValue, sign, e, f)
195194
}
196195

197-
private def floatToIntBitsPolyfill(value: scala.Double): Int = {
196+
private def floatToIntBitsPolyfill(floatValue: scala.Float): Int = {
198197
// Some constants
199198
val ebits = 8
200199
val fbits = 23
201200

201+
// Force computations to be on Doubles
202+
val value = floatValue.toDouble
203+
202204
// Determine sign bit and compute the absolute value av
203205
val sign = if (value < 0.0 || (value == 0.0 && 1.0 / value < 0.0)) -1 else 1
204206
val s = sign & scala.Int.MinValue
205207
val av = sign * value
206208

207209
// Compute e and f
208-
val avr = forceFround(av)
209210
val powsOf2 = this.floatPowsOf2 // local cache
210-
val e = encodeIEEE754Exponent(ebits, powsOf2, avr)
211-
val f = encodeIEEE754MantissaBits(ebits, fbits, powsOf2, scala.Float.MinPositiveValue.toDouble, avr, e)
211+
val e = encodeIEEE754Exponent(ebits, powsOf2, av)
212+
val f = encodeIEEE754MantissaBits(ebits, fbits, powsOf2, scala.Float.MinPositiveValue.toDouble, av, e)
212213

213214
// Encode
214215
s | (e << fbits) | rawToInt(f)
@@ -277,37 +278,6 @@ private[lang] object FloatingPointBits {
277278
}
278279
}
279280

280-
/** Force rounding of `av` to fit in 32 bits (this is a manual `fround`).
281-
*
282-
* `av` must not be negative, i.e., `av < 0.0` must be false (it can be
283-
* `NaN` or `Infinity`).
284-
*
285-
* When we use strict-float semantics, this is redundant, because the input
286-
* came from a `Float` and is therefore guaranteed to be rounded already.
287-
* However, here we don't know whether we use strict floats semantics or
288-
* not, so we must always do it. This is not a big deal because, if this
289-
* code is called, then any operation on `Float`s is calling the same code
290-
* from the `CoreJSLib`, so doing one more such operation for
291-
* `floatToIntBits` is negligible.
292-
*
293-
* TODO Remove this when we get rid of non-strict float semantics altogether.
294-
*/
295-
@inline
296-
private def forceFround(av: scala.Double): scala.Double = {
297-
// See the `fround` polyfill in CoreJSLib
298-
val overflowThreshold = 3.4028235677973366e38
299-
val normalThreshold = 1.1754943508222875e-38
300-
if (av >= overflowThreshold) {
301-
scala.Double.PositiveInfinity
302-
} else if (av >= normalThreshold) {
303-
val p = av * 536870913.0 // pow(2, 29) + 1
304-
p + (av - p)
305-
} else {
306-
val roundingFactor = scala.Double.MinPositiveValue / scala.Float.MinPositiveValue.toDouble
307-
(av * roundingFactor) / roundingFactor
308-
}
309-
}
310-
311281
private def encodeIEEE754Exponent(ebits: Int,
312282
powsOf2: js.Array[scala.Double], av: scala.Double): Int = {
313283

linker-interface/shared/src/main/scala/org/scalajs/linker/interface/Semantics.scala

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
package org.scalajs.linker.interface
1414

15+
import scala.annotation.compileTimeOnly
16+
1517
import CheckedBehavior._
1618
import Fingerprint.FingerprintBuilder
1719

@@ -23,12 +25,16 @@ final class Semantics private (
2325
val nullPointers: CheckedBehavior,
2426
val stringIndexOutOfBounds: CheckedBehavior,
2527
val moduleInit: CheckedBehavior,
26-
val strictFloats: Boolean,
2728
val productionMode: Boolean,
2829
val runtimeClassNameMapper: Semantics.RuntimeClassNameMapper) {
2930

3031
import Semantics._
3132

33+
@deprecated(
34+
"non-strict floats are not supported anymore; strictFloats is always true",
35+
since = "1.19.0")
36+
val strictFloats: Boolean = true
37+
3238
def withAsInstanceOfs(behavior: CheckedBehavior): Semantics =
3339
copy(asInstanceOfs = behavior)
3440

@@ -50,13 +56,11 @@ final class Semantics private (
5056
def withModuleInit(moduleInit: CheckedBehavior): Semantics =
5157
copy(moduleInit = moduleInit)
5258

53-
@deprecated(
54-
"Scala.js now uses strict floats by default. " +
55-
"Non-strict float semantics are deprecated and will eventually be " +
56-
"removed.",
57-
"1.9.0")
59+
@compileTimeOnly(
60+
"Non-strict floats are not supported anymore. " +
61+
"The default is `true` and cannot be turned to `false`.")
5862
def withStrictFloats(strictFloats: Boolean): Semantics =
59-
copy(strictFloats = strictFloats)
63+
this
6064

6165
def withProductionMode(productionMode: Boolean): Semantics =
6266
copy(productionMode = productionMode)
@@ -86,7 +90,6 @@ final class Semantics private (
8690
this.nullPointers == that.nullPointers &&
8791
this.stringIndexOutOfBounds == that.stringIndexOutOfBounds &&
8892
this.moduleInit == that.moduleInit &&
89-
this.strictFloats == that.strictFloats &&
9093
this.productionMode == that.productionMode &&
9194
this.runtimeClassNameMapper == that.runtimeClassNameMapper
9295
case _ =>
@@ -103,7 +106,6 @@ final class Semantics private (
103106
acc = mix(acc, nullPointers.##)
104107
acc = mix(acc, stringIndexOutOfBounds.##)
105108
acc = mix(acc, moduleInit.##)
106-
acc = mix(acc, strictFloats.##)
107109
acc = mix(acc, productionMode.##)
108110
acc = mixLast(acc, runtimeClassNameMapper.##)
109111
finalizeHash(acc, 10)
@@ -118,7 +120,6 @@ final class Semantics private (
118120
| nullPointers = $nullPointers,
119121
| stringIndexOutOfBounds = $stringIndexOutOfBounds,
120122
| moduleInit = $moduleInit,
121-
| strictFloats = $strictFloats,
122123
| productionMode = $productionMode
123124
|)""".stripMargin
124125
}
@@ -131,7 +132,6 @@ final class Semantics private (
131132
nullPointers: CheckedBehavior = this.nullPointers,
132133
stringIndexOutOfBounds: CheckedBehavior = this.stringIndexOutOfBounds,
133134
moduleInit: CheckedBehavior = this.moduleInit,
134-
strictFloats: Boolean = this.strictFloats,
135135
productionMode: Boolean = this.productionMode,
136136
runtimeClassNameMapper: RuntimeClassNameMapper =
137137
this.runtimeClassNameMapper): Semantics = {
@@ -143,7 +143,6 @@ final class Semantics private (
143143
nullPointers = nullPointers,
144144
stringIndexOutOfBounds = stringIndexOutOfBounds,
145145
moduleInit = moduleInit,
146-
strictFloats = strictFloats,
147146
productionMode = productionMode,
148147
runtimeClassNameMapper = runtimeClassNameMapper)
149148
}
@@ -262,7 +261,6 @@ object Semantics {
262261
.addField("nullPointers", semantics.nullPointers)
263262
.addField("stringIndexOutOfBounds", semantics.stringIndexOutOfBounds)
264263
.addField("moduleInit", semantics.moduleInit)
265-
.addField("strictFloats", semantics.strictFloats)
266264
.addField("productionMode", semantics.productionMode)
267265
.addField("runtimeClassNameMapper", semantics.runtimeClassNameMapper)
268266
.build()
@@ -277,7 +275,6 @@ object Semantics {
277275
nullPointers = Fatal,
278276
stringIndexOutOfBounds = Fatal,
279277
moduleInit = Unchecked,
280-
strictFloats = true,
281278
productionMode = false,
282279
runtimeClassNameMapper = RuntimeClassNameMapper.keepAll())
283280
}

linker-interface/shared/src/main/scala/org/scalajs/linker/interface/StandardConfig.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ final class StandardConfig private (
192192
*
193193
* - `moduleKind == ModuleKind.ESModule`
194194
* - `esFeatures.useECMAScript2015Semantics == true` (true by default)
195-
* - `semantics.strictFloats == true` (true by default; non-strict floats are deprecated)
196195
*
197196
* We may lift these restrictions in the future, although we do not expect
198197
* to do so.

linker/shared/src/main/scala/org/scalajs/linker/backend/WebAssemblyLinkerBackend.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,6 @@ final class WebAssemblyLinkerBackend(config: LinkerBackendImpl.Config)
4040
coreSpec.esFeatures.useECMAScript2015Semantics,
4141
s"The WebAssembly backend only supports the ECMAScript 2015 semantics."
4242
)
43-
require(
44-
coreSpec.semantics.strictFloats,
45-
"The WebAssembly backend only supports strict float semantics."
46-
)
4743

4844
require(coreSpec.targetIsWebAssembly,
4945
s"A WebAssembly backend cannot be used with CoreSpec targeting JavaScript")

0 commit comments

Comments
 (0)
0