Atomics.isLockFree does not convert its argument properly (interpreter and jit are wrong in different ways)

RESOLVED WORKSFORME

Status

()

Core
JavaScript Engine
P2
normal
RESOLVED WORKSFORME
2 years ago
a year ago

People

(Reporter: lth, Assigned: lth)

Tracking

(Blocks: 1 bug)

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Assignee)

Description

2 years ago
The spec says that the argument is converted by ToInteger().  Our current (interpreter) implementation does not do that; if the argument is not int32 it is assumed to be invalid.

The JIT implementation probably gets this *mostly* right, it uses a ConvertToInt32Policy on the argument, with appropriate bailout handling.  This will give the wrong result in some corner cases (values outside the Int32 range).

Spec here:
https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.isLockFree

Test case here:
https://github.com/tc39/ecmascript_sharedmem/blob/master/test262/is-lock-free-corner-cases.js
(Assignee)

Updated

2 years ago
Blocks: 1054841, 1225039
(Assignee)

Comment 1

2 years ago
Created attachment 8717986 [details] [diff] [review]
part 1: argument conversion for Atomics.isLockFree in runtime
Attachment #8717986 - Flags: review?(bbouvier)
Comment on attachment 8717986 [details] [diff] [review]
part 1: argument conversion for Atomics.isLockFree in runtime

Review of attachment 8717986 [details] [diff] [review]:
-----------------------------------------------------------------

Looks good!

::: js/src/builtin/AtomicsObject.cpp
@@ +513,5 @@
> +        size = v.toInt32();
> +    } else {
> +        double dsize;
> +        if (!ToInteger(cx, v, &dsize))
> +            return false;

I don't know how hot this is expected to be, but you could as well get rid of the v.isInt32() check and just have the content of the else, which would simplify the control flow.

::: js/src/jit-test/tests/atomics/basic-tests.js
@@ +426,5 @@
> +    assertEq(Atomics.isLockFree(false), false);
> +    assertEq(Atomics.isLockFree(undefined), false);
> +    assertEq(Atomics.isLockFree(null), false);
> +    assertEq(Atomics.isLockFree({toString: () => '4'}), true);
> +    assertEq(Atomics.isLockFree({password: "qumquat"}), false);

Can you add tests with a Symbol, with NaN, with -0, with Infinity, with an object that implements valueOf()?
Attachment #8717986 - Flags: review?(bbouvier) → review+
(Assignee)

Updated

2 years ago
Keywords: leave-open

Comment 3

2 years ago
Part 1 landed with the wrong bug number (Bug 1246768):
https://hg.mozilla.org/integration/mozilla-inbound/rev/d8781a4c7092db380f52de8467515fd317e24201
https://hg.mozilla.org/mozilla-central/rev/d8781a4c7092
(Assignee)

Updated

a year ago
Priority: -- → P2
(Assignee)

Comment 4

a year ago
Passes all tests with the current code (after the first patch landed).  Indeed ConvertToInt32Policy seems exactly right; we should fall back to the C++ code if the input can't be converted to Int32 without loss of data, and the C++ code gets it right.

I wish I had noted earlier precisely which test case failed... live and learn.
Status: ASSIGNED → RESOLVED
Last Resolved: a year ago
Keywords: leave-open
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.