Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Document non-trivial function Code.constant_equal, and fix related bugs #1659

Merged
merged 13 commits into from
Aug 27, 2024

Conversation

OlivierNicole
Copy link
Contributor

I think this will be useful to future us.

(@vouillon excavated the semantics of the function.)

@OlivierNicole
Copy link
Contributor Author

See

| Int _, (String _ | NativeString _ | Float_array _ | Int64 _ | Tuple (_, _, _)) ->
Some false

Is it definitely the case that in Javascript a == b is false when a is an Int (whatever that means) and b is an Int64?

@vouillon
Copy link
Member

An int64 is implemented as a JavaScript object, which is never equal to a JavaScript number.

compiler/lib/code.mli Outdated Show resolved Hide resolved
@vouillon
Copy link
Member

Also Float.equal 0. (-0.) is false. So (0., 0.) = (-0., 0.) is miscompiled into true.

I think the fix in #1048 is wrong and we should not use Code.constant_equal in Flow.the_const_of.

@hhugo
Copy link
Member

hhugo commented Aug 1, 2024

Also Float.equal 0. (-0.) is false. So (0., 0.) = (-0., 0.) is miscompiled into true.

I'm guessing you mean

Also `Float.equal 0. (-0.)` is false. So `(0., 0.) = (-0., 0.)` is miscompiled into `false`

@hhugo
Copy link
Member

hhugo commented Aug 1, 2024

@vouillon, can you explain what's wrong with using Code.constant_equal in Flow.the_const_of ?

I think the way forward is to come up with regression tests showing how the current implementation is wrong. @OlivierNicole, do you want to look at this ?

@OlivierNicole
Copy link
Contributor Author

I can look at this, but so far i’m confused:

Also Float.equal 0. (-0.) is false.

Testing in ocaml 5.2.0 yields true.

I'm guessing you mean

Also `Float.equal 0. (-0.)` is false. So `(0., 0.) = (-0., 0.)` is miscompiled into `false`

This equality is true in both ocaml 5.2.0 and Node (with (==)).

@vouillon
Copy link
Member

vouillon commented Aug 1, 2024

I can look at this, but so far i’m confused:

Also Float.equal 0. (-0.) is false.

Testing in ocaml 5.2.0 yields true.

We have this definition in stdlib.ml, which is really confusing:

  let equal (a : float) (b : float) =
    Int64.equal (Int64.bits_of_float a) (Int64.bits_of_float b)

@OlivierNicole
Copy link
Contributor Author

Yes, very!

@vouillon
Copy link
Member

vouillon commented Aug 1, 2024

@vouillon, can you explain what's wrong with using Code.constant_equal in Flow.the_const_of ?

In Flow.the_const_of, we want to consider two constants the same if they cannot be distinguished. In particular, 0. and -0. are different.

On the other hand, we want that if Code.constant_equal a b = Some v, then Poly.(=) a b = v.

It is possible to define a function that satisfies both constraints by special-casing 0. and -0., but it seems simpler to use difference functions, especially since in the_const_of we only care about simple constants.

@OlivierNicole
Copy link
Contributor Author

So (0., 0.) = (-0., 0.) is miscompiled into false

Regarding this, I suggest we stop shadowing the IEEE754-complying stdlib Float.equal with bitwise equality and call it bitwise_equal instead. This way we will use IEEE754-complying Float.equal in the rewritings and the problem should disappear.

@vouillon
Copy link
Member

vouillon commented Aug 1, 2024

So (0., 0.) = (-0., 0.) is miscompiled into false

Regarding this, I suggest we stop shadowing the IEEE754-complying stdlib Float.equal with bitwise equality and call it bitwise_equal instead. This way we will use IEEE754-complying Float.equal in the rewritings and the problem should disappear.

I agree that we should rename this function. But Float.equal is not quite IEEE754-complying since Float.equal nan nan is true (but Poly.equal nan nan is false). So we should also review where it is used.

@OlivierNicole
Copy link
Contributor Author

After checking, the only other place it is used is in compiler/lib/javascript.ml, in Num.of_float:

let of_float v =
match Float.classify_float v with
| FP_nan -> "NaN"
| FP_zero ->
(* [1/-0] < 0. seems to be the only way to detect -0 in JavaScript *)
if Float.(1. /. v < 0.) then "-0." else "0."
| FP_infinite -> if Float.(v < 0.) then "-Infinity" else "Infinity"
| FP_normal | FP_subnormal -> (
let vint = int_of_float v in
if Float.equal (float_of_int vint) v
then Printf.sprintf "%d." vint
else
match
find_smaller
~f:(fun prec ->
let s = float_to_string prec v in
if Float.equal v (float_of_string s) then Some s else None)
~bad:0
~good:18
~good_s:"max"
with
| "max" -> float_to_string 18 v |> fix_exponent
| s -> fix_exponent s)

I’m not entirely sure what it does, but I expect we can adapt it if needed.

@vouillon
Copy link
Member

vouillon commented Aug 1, 2024

After checking, the only other place it is used is in compiler/lib/javascript.ml, in Num.of_float:

[...]

I’m not entirely sure what it does, but I expect we can adapt it if needed.

NaN and zeroes have been excluded, so this is fine.

OlivierNicole added a commit to OlivierNicole/js_of_ocaml that referenced this pull request Aug 2, 2024
@OlivierNicole OlivierNicole changed the title Document non-trivial function Code.constant_equal Document non-trivial function Code.constant_equal, and fix related bugs Aug 2, 2024
@OlivierNicole
Copy link
Contributor Author

OlivierNicole commented Aug 2, 2024

I have updated the comment, and attempted to fix the two compilation bugs that you have mentioned here.

Edit: I renamed a file from constant.ml to global_constant.ml because otherwise it clashed with the new module Code.Constant that I wanted to introduce.

@OlivierNicole
Copy link
Contributor Author

I will also add regression tests

OlivierNicole added a commit to OlivierNicole/js_of_ocaml that referenced this pull request Aug 2, 2024
@OlivierNicole
Copy link
Contributor Author

I have added a regression test.

OlivierNicole added a commit to OlivierNicole/js_of_ocaml that referenced this pull request Aug 2, 2024
OlivierNicole added a commit to OlivierNicole/js_of_ocaml that referenced this pull request Aug 2, 2024
@hhugo
Copy link
Member

hhugo commented Aug 2, 2024

We have this definition in stdlib.ml, which is really confusing:

  let equal (a : float) (b : float) =
    Int64.equal (Int64.bits_of_float a) (Int64.bits_of_float b)

Maybe we should rename it Float.bits_equal and have Float.equal the one from the stdlib. I'd prefer to limit the use of Poly.equal as much as possible.

compiler/lib/code.mli Outdated Show resolved Hide resolved
@hhugo hhugo merged commit 9602504 into ocsigen:master Aug 27, 2024
17 checks passed
OlivierNicole added a commit to ocaml-wasm/wasm_of_ocaml that referenced this pull request Sep 3, 2024
@OlivierNicole OlivierNicole deleted the doc-comment branch September 3, 2024 14:17
OlivierNicole added a commit to ocaml-wasm/wasm_of_ocaml that referenced this pull request Sep 3, 2024
OlivierNicole added a commit to ocaml-wasm/wasm_of_ocaml that referenced this pull request Sep 9, 2024
OlivierNicole added a commit to OlivierNicole/wasm_of_ocaml that referenced this pull request Sep 9, 2024
OlivierNicole added a commit to ocaml-wasm/wasm_of_ocaml that referenced this pull request Sep 12, 2024
OlivierNicole added a commit to OlivierNicole/wasm_of_ocaml that referenced this pull request Sep 12, 2024
OlivierNicole added a commit to ocaml-wasm/wasm_of_ocaml that referenced this pull request Sep 13, 2024
vouillon pushed a commit to OlivierNicole/wasm_of_ocaml that referenced this pull request Sep 20, 2024
vouillon added a commit that referenced this pull request Oct 29, 2024
…related bugs (#1659)

* Document non-trivial function Code.constant_equal

Co-authored-by: Jérome Vouillon <jerome.vouillon@gmail.com>

* Fix bugs related to constant equality

See #1659.

* More static evaluation of equalities in eval

* Statically evaluate caml_js_strict_equals too

* Compiler: small refactoring in eval

---------

Co-authored-by: Jérome Vouillon <jerome.vouillon@gmail.com>
Co-authored-by: Hugo Heuzard <hugo.heuzard@gmail.com>
hhugo added a commit to hhugo/opam-repository that referenced this pull request Nov 22, 2024
CHANGES:

## Features/Changes
* Misc: update testsuite to OCaml 5.2
* Misc: CI uses opam.2.2 and no longer use sunset repo
* Misc: yojson is no longer optional
* Misc: reduce the diff with the wasm_of_ocaml fork
* Misc: finalize support for OCaml 5.3
* Compiler: speedup global_flow/global_deadcode pass on large bytecode
* Compiler: improved global dead code elimination (ocsigen/js_of_ocaml#2206)
* Compiler: speedup json parsing, relying on Yojson.Raw (ocsigen/js_of_ocaml#1640)
* Compiler: Decode sourcemap mappings only when necessary (ocsigen/js_of_ocaml#1664)
* Compiler: mark [TextEncoder] as reserved
* Compiler: add support for the Wasm backend in parts of the pipeline, in
  prevision for the merge of wasm_of_ocaml
* Compiler: introduce a Targetint module
  that follows the semantic of the backend (js or wasm)
* Compiler: warn on joo_global_object
* Compiler: revisit static env handling (ocsigen/js_of_ocaml#1708)
* Compiler: Emit index source_map to avoid changing mappings (ocsigen/js_of_ocaml#1714, ocsigen/js_of_ocaml#1715)
* Compiler: improved source map generation (ocsigen/js_of_ocaml#1716)
* Runtime: change Sys.os_type on windows (Cygwin -> Win32)
* Runtime: backtraces are really expensive, they need to be explicitly
  requested at compile time (--enable with-js-error) or at startup (OCAMLRUNPARAM=b=1)
* Runtime: allow dynlink of precompiled js with separate compilation (ocsigen/js_of_ocaml#1676)
* Runtime: reimplement the runtime of weak and ephemeron (ocsigen/js_of_ocaml#1707)
* Lib: Modify Typed_array API for compatibility with WebAssembly
* Lib: add details element and toggle event (ocsigen/js_of_ocaml#1728)
* Toplevel: no longer set globals for toplevel initialization
* Runtime: precompute constants used in `caml_lxm_next` (ocsigen/js_of_ocaml#1730)
* Runtime: cleanup runtime

## Bug fixes
* Runtime: fix parsing of unsigned integers (0u2147483648) (ocsigen/js_of_ocaml#1633, ocsigen/js_of_ocaml#1666)
* Runtime: fix incorrect pos_in after unmarshalling
* Runtime: make float_of_string stricter (ocsigen/js_of_ocaml#1609)
* Toplevel: fix missing primitives with separate compilation
* Compiler: fix link of packed modules with separate compilation
* Compiler: Fixed the static evaluation of some equalities (ocsigen/js_of_ocaml#1659)
* Compiler: fix global analysis bug (subsumes ocsigen/js_of_ocaml#1556)
hhugo added a commit to hhugo/opam-repository that referenced this pull request Nov 23, 2024
CHANGES:

## Features/Changes
* Misc: update testsuite to OCaml 5.2
* Misc: CI uses opam.2.2 and no longer use sunset repo
* Misc: yojson is no longer optional
* Misc: reduce the diff with the wasm_of_ocaml fork
* Misc: finalize support for OCaml 5.3
* Compiler: speedup global_flow/global_deadcode pass on large bytecode
* Compiler: improved global dead code elimination (ocsigen/js_of_ocaml#2206)
* Compiler: speedup json parsing, relying on Yojson.Raw (ocsigen/js_of_ocaml#1640)
* Compiler: Decode sourcemap mappings only when necessary (ocsigen/js_of_ocaml#1664)
* Compiler: mark [TextEncoder] as reserved
* Compiler: add support for the Wasm backend in parts of the pipeline, in
  prevision for the merge of wasm_of_ocaml
* Compiler: introduce a Targetint module
  that follows the semantic of the backend (js or wasm)
* Compiler: warn on joo_global_object
* Compiler: revisit static env handling (ocsigen/js_of_ocaml#1708)
* Compiler: Emit index source_map to avoid changing mappings (ocsigen/js_of_ocaml#1714, ocsigen/js_of_ocaml#1715)
* Compiler: improved source map generation (ocsigen/js_of_ocaml#1716)
* Runtime: change Sys.os_type on windows (Cygwin -> Win32)
* Runtime: backtraces are really expensive, they need to be explicitly
  requested at compile time (--enable with-js-error) or at startup (OCAMLRUNPARAM=b=1)
* Runtime: allow dynlink of precompiled js with separate compilation (ocsigen/js_of_ocaml#1676)
* Runtime: reimplement the runtime of weak and ephemeron (ocsigen/js_of_ocaml#1707)
* Lib: Modify Typed_array API for compatibility with WebAssembly
* Lib: add details element and toggle event (ocsigen/js_of_ocaml#1728)
* Toplevel: no longer set globals for toplevel initialization
* Runtime: precompute constants used in `caml_lxm_next` (ocsigen/js_of_ocaml#1730)
* Runtime: cleanup runtime

## Bug fixes
* Runtime: fix parsing of unsigned integers (0u2147483648) (ocsigen/js_of_ocaml#1633, ocsigen/js_of_ocaml#1666)
* Runtime: fix incorrect pos_in after unmarshalling
* Runtime: make float_of_string stricter (ocsigen/js_of_ocaml#1609)
* Toplevel: fix missing primitives with separate compilation
* Compiler: fix link of packed modules with separate compilation
* Compiler: Fixed the static evaluation of some equalities (ocsigen/js_of_ocaml#1659)
* Compiler: fix global analysis bug (subsumes ocsigen/js_of_ocaml#1556)
hhugo added a commit to hhugo/opam-repository that referenced this pull request Nov 26, 2024
CHANGES:

## Features/Changes
* Misc: update testsuite to OCaml 5.2
* Misc: CI uses opam.2.2 and no longer use sunset repo
* Misc: yojson is no longer optional
* Misc: reduce the diff with the wasm_of_ocaml fork
* Misc: finalize support for OCaml 5.3
* Compiler: speedup global_flow/global_deadcode pass on large bytecode
* Compiler: improved global dead code elimination (ocsigen/js_of_ocaml#2206)
* Compiler: speedup json parsing, relying on Yojson.Raw (ocsigen/js_of_ocaml#1640)
* Compiler: Decode sourcemap mappings only when necessary (ocsigen/js_of_ocaml#1664)
* Compiler: mark [TextEncoder] as reserved
* Compiler: add support for the Wasm backend in parts of the pipeline, in
  prevision for the merge of wasm_of_ocaml
* Compiler: introduce a Targetint module
  that follows the semantic of the backend (js or wasm)
* Compiler: warn on joo_global_object
* Compiler: revisit static env handling (ocsigen/js_of_ocaml#1708)
* Compiler: Emit index source_map to avoid changing mappings (ocsigen/js_of_ocaml#1714, ocsigen/js_of_ocaml#1715)
* Compiler: improved source map generation (ocsigen/js_of_ocaml#1716)
* Runtime: change Sys.os_type on windows (Cygwin -> Win32)
* Runtime: backtraces are really expensive, they need to be explicitly
  requested at compile time (--enable with-js-error) or at startup (OCAMLRUNPARAM=b=1)
* Runtime: allow dynlink of precompiled js with separate compilation (ocsigen/js_of_ocaml#1676)
* Runtime: reimplement the runtime of weak and ephemeron (ocsigen/js_of_ocaml#1707)
* Lib: Modify Typed_array API for compatibility with WebAssembly
* Lib: add details element and toggle event (ocsigen/js_of_ocaml#1728)
* Toplevel: no longer set globals for toplevel initialization
* Runtime: precompute constants used in `caml_lxm_next` (ocsigen/js_of_ocaml#1730)
* Runtime: cleanup runtime

## Bug fixes
* Runtime: fix parsing of unsigned integers (0u2147483648) (ocsigen/js_of_ocaml#1633, ocsigen/js_of_ocaml#1666)
* Runtime: fix incorrect pos_in after unmarshalling
* Runtime: make float_of_string stricter (ocsigen/js_of_ocaml#1609)
* Toplevel: fix missing primitives with separate compilation
* Compiler: fix link of packed modules with separate compilation
* Compiler: Fixed the static evaluation of some equalities (ocsigen/js_of_ocaml#1659)
* Compiler: fix global analysis bug (subsumes ocsigen/js_of_ocaml#1556)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants