Skip to content

Move microtask queue to JS - #6

Closed
Jarred-Sumner wants to merge 69 commits into
mainfrom
jarred/js-microtask-queue
Closed

Jarred-Sumner wants to merge 69 commits into
mainfrom
jarred/js-microtask-queue

Conversation

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

Not working yet:

  • Promise.all
  • Exception handlers in Test262 (why did this break?)

Jarred-Sumner and others added 21 commits March 27, 2022 16:26
This uses `TypedArray.prototype.set` when `TypedArray.from(array)` receives another TypedArray

It does not handle when `set` has been overridden. This will likely have to be changed later, but it is better than the present state
Instead of checking `isJSCall` three times, now it checks once.
Instead of 4 checks, only do one
This makes promises & async take two ticks instead of three ticks.

See tc39/ecma262#1250
See tc39/ecma262#2770
See tc39/ecma262#2772

50% faster when measuring call overhead. Similar improvements for https://github.com/v8/promise-performance-tests and when measuring with the following snippet:

```js
import { run, bench } from "mitata";

bench("sync", () => {});
bench("async", async () => {});

run();
```
@Jarred-Sumner
Jarred-Sumner force-pushed the main branch 2 times, most recently from b2bc126 to f01745a Compare July 31, 2022 23:24
Jarred-Sumner pushed a commit that referenced this pull request Jan 29, 2023
https://bugs.webkit.org/show_bug.cgi?id=251063
rdar://104585575

Reviewed by Mark Lam and Justin Michaud.

This patch enhances CallFrame::dump to support wasm frames in btjs stacktrace.
The example is as follows.

    frame #0: 0x00000001035fca78 JavaScriptCore`JSC::functionBreakpoint(globalObject=0x000000012f410068, callFrame=0x000000016fdfa9d0) at JSDollarVM.cpp:2273:9 [opt]
    frame #1: 0x000000010ec44204 0x10eccc5dc
    frame #2: 0x000000010eccc5dc callback#Dwaxn6 [Baseline bc#50](Undefined)
    frame #3: 0x000000010ec4ca84 wasm-stub [WasmToJS](Wasm::Instance: 0x10d29da40)
    frame #4: 0x000000010ed0c060 <?>.wasm-function[1] [OMG](Wasm::Instance: 0x10d29da40)
    frame #5: 0x000000010ed100d0 jsToWasm#CWTx6k [FTL bc#22](Cell[JSModuleEnvironment]: 0x12f524540, Cell[WebAssemblyFunction]: 0x10d06a3a8, 1, 2, 3)
    frame #6: 0x000000010ec881b0 #D5ymZE [Baseline bc#733](Undefined, Cell[Generator]: 0x12f55c180, 1, Cell[Object]: 0x12f69dfc0, 0, Cell[JSLexicalEnvironment]: 0x12f52cee0)
    frame #7: 0x000000010ec3c008 asyncFunctionResume#A4ayYg [LLInt bc#49](Undefined, Cell[Generator]: 0x12f55c180, Cell[Object]: 0x12f69dfc0, 0)
    frame #8: 0x000000010ec3c008 promiseReactionJobWithoutPromise#D0yDF1 [LLInt bc#25](Undefined, Cell[Function]: 0x12f44f3c0, Cell[Object]: 0x12f69dfc0, Cell[Generator]: 0x12f55c180)
    frame #9: 0x000000010ec80ec0 promiseReactionJob#EdShZz [Baseline bc#74](Undefined, Undefined, Cell[Function]: 0x12f44f3c0, Cell[Object]: 0x12f69dfc0, Cell[Generator]: 0x12f55c180)
    frame #10: 0x000000010ec3c728
    frame #11: 0x0000000103137560 JavaScriptCore`JSC::Interpreter::executeCall(JSC::JSGlobalObject*, JSC::JSObject*, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) [inlined] JSC::JITCode::execute(this=<unavailable>, vm=<unavailable>, protoCallFrame=<unavailable>) at JITCodeInlines.h:42:38 [opt]
    frame #12: 0x0000000103137524 JavaScriptCore`JSC::Interpreter::executeCall(this=<unavailable>, lexicalGlobalObject=<unavailable>, function=<unavailable>, callData=<unavailable>, thisValue=<unavailable>, args=<unavailable>) at Interpreter.cpp:1093:27 [opt]
    frame #13: 0x000000010349d6d0 JavaScriptCore`JSC::runJSMicrotask(globalObject=0x000000012f410068, identifier=(m_identifier = 81), job=JSValue @ x22, argument0=JSValue @ x26, argument1=JSValue @ x25, argument2=<unavailable>, argument3=<unavailable>) at JSMicrotask.cpp:98:9 [opt]
    frame #14: 0x00000001039dfc54 JavaScriptCore`JSC::VM::drainMicrotasks() (.cold.1) at VM.cpp:0:9 [opt]
    frame #15: 0x00000001035e58a4 JavaScriptCore`JSC::VM::drainMicrotasks() [inlined] JSC::MicrotaskQueue::dequeue(this=<unavailable>) at VM.cpp:0:9 [opt]
    frame #16: 0x00000001035e5894 JavaScriptCore`JSC::VM::drainMicrotasks(this=0x000000012f000000) at VM.cpp:1255:46 [opt]
    ...

* Source/JavaScriptCore/interpreter/CallFrame.cpp:
(JSC::CallFrame::dump const):

Canonical link: https://commits.webkit.org/259262@main
Jarred-Sumner pushed a commit that referenced this pull request Dec 30, 2024
https://bugs.webkit.org/show_bug.cgi?id=281902
rdar://136486349

Reviewed by Mike Wyrzykowski.

Metal: Ensure potentially infinite loops have defined behavior

The MSL compiler would omit infinite loops and assume number domains
based on the omission logic. This would induce incorrect number domains
in case the infinite loops would be invokable. Infinite loops are
undefined in C++ and thus in MSL. It is the job of the programmer
to ensure undefined behavior cannot happen.

Consider GLSL loop like:
uniform float i;
...
    if (i != 0.5) for(;;) { }
    gl_FragColor = vec4(i);

Historically this would emit MSL loop in spirit of:
    if (i != 0.5) {
      bool c = true;
      while (c) { }
    }
    ANGLE_fragmentOut.gl_FragColor = metal::float4(i, i, i, i);

Since This could cause the MSL compiler to optimize the function to
equivalent of:
    ANGLE_fragmentOut.gl_FragColor = metal::float4(0.5, 0.5, 0.5, 0.5);

Presumably this loop omission would happen at the clang frontend part.

Before, was worked around by emitting asm statements to the MSL:
    bool c = true;
    while (c) {
        __asm__("");
    }

The asm injection would would work for this particular source pattern,
presumably because injecting the asm would avoid the loop omission at
the clang frontend part.

The MSL/C++ code is still UB, though. The asm statement does not cause
anything that C++ would consider as "forward progress" of the loop. The
success was just due to how the backend worked. The bitcode produced
would be similar to:

4:
    tail call void asm sideeffect "", ""() #6, !srcloc !28
    br label %4, !llvm.loop !29

Here, the compiler can be seen to simply fail to detect a loop that
does not make forward progress.

Considering GLSL of form:
uniform int f;
...
    for (;;) { if (f <= 1) break; }

With asm injection to the loop, this would produce:

5:
    tail call void asm sideeffect "", ""() #8, !srcloc !29
    %6 = load i32, i32 addrspace(2)* %4, align 4, !tbaa !30
    %7 = icmp slt i32 %6, 2
    br i1 %7, label %8, label %5
8:

This code is still assumed to make progress. The backend optimizer is
free to assume that the condition holds, since the load to break the
loop is from constant address space. I.e. uniform f does not change its
value during the loop.

Instead of injecting asm, inject a read of unused volatile variable.
The volatile variable access is defined in C++ as forward progress.
This means infinite loop containing such read is considered defined.
To simplify the implementation and to avoid volatile writes, the read
is to a dummy variable instead of the loop condition bool.

The tests here do not pass completely for MSL backend. In case the
compiler would omit the infinite loop (unpatched code), they would fail
with demonstration of how the values behave. After fixing, the loops
cause timeout but Metal backend does not have implementation to report
context loss. Also, the ReadPixels is just for demostration purposes of the
unpatched code.

* Source/ThirdParty/ANGLE/src/compiler/translator/msl/EmitMetal.cpp:
(GenMetalTraverser::GenMetalTraverser):
(GenMetalTraverser::emitLoopBody):
(GenMetalTraverser::emitForwardProgressStore):
(GenMetalTraverser::emitForwardProgressSignal):
(GenMetalTraverser::visitForLoop):
(GenMetalTraverser::visitWhileLoop):
(GenMetalTraverser::visitDoWhileLoop):
* Source/ThirdParty/ANGLE/src/tests/angle_end2end_tests.gni:
* Source/ThirdParty/ANGLE/src/tests/gl_tests/TimeoutDrawTest.cpp: Added.
(angle::TimeoutDrawTest::TimeoutDrawTest):
(angle::TEST_P):

Originally-landed-as: 283286.350@safari-7620-branch (b82d94e). rdar://141318430
Canonical link: https://commits.webkit.org/288020@main
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.

2 participants