Bug 211540

Summary: GetArrayLength should be "blessed" during Fixup phase in the DFG
Product: WebKit Reporter: Keith Miller <keith_miller>
Component: New BugsAssignee: Keith Miller <keith_miller>
Status: RESOLVED FIXED    
Severity: Normal CC: ews-watchlist, mark.lam, msaboff, saam, tzagallo, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch for landing
none
Patch for landing
none
Patch for landing none

Description Keith Miller 2020-05-06 17:37:10 PDT
GetArrayLength should be "blessed" during Fixup phase in the DFG
Comment 1 Keith Miller 2020-05-06 17:39:34 PDT
Created attachment 398688 [details]
Patch
Comment 2 Keith Miller 2020-05-06 17:39:55 PDT
rdar://problem/62839448
Comment 3 Mark Lam 2020-05-06 17:47:07 PDT
Comment on attachment 398688 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398688&action=review

r=me

> Source/JavaScriptCore/ChangeLog:8
> +        If we got an ArrayMode that expects to be configured during Fixup

Please add a comma after "Fixup".
Comment 4 Keith Miller 2020-05-07 18:13:24 PDT
Created attachment 398822 [details]
Patch
Comment 5 Saam Barati 2020-05-07 18:31:42 PDT
Comment on attachment 398822 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398822&action=review

> Source/JavaScriptCore/ChangeLog:3
> +        GetArrayLength should be "blessed" during Fixup phase in the DFG

in your changelog, can you say what this fixes? You say some mechanical things, but not the original bug.

> Source/JavaScriptCore/ChangeLog:9
> +        If we got an ArrayMode that expects to be configured during Fixup,
> +        then right now we will fail. This fixes GetArrayLength to properly

Can you be a bit more specific on this first sentence. What you wrote is clearly not true.

> Source/JavaScriptCore/ChangeLog:22
> +        previously pass it's own speculation for the speculation of the index, which logically

it's => its

> Source/JavaScriptCore/dfg/DFGArrayMode.cpp:430
> +    if (isSomeTypedArrayView())
> +        return value.isType(SpecTypedArrayView);

how is this enough? e.g, how does this handle Float32Array vs Float64Array?

> Source/JavaScriptCore/dfg/DFGArrayMode.h:240
> +    static constexpr SpeculatedType unusedIndexSpeculatedType = SpecInt32Only;

alternatively:  just use Optional for the argument param
Comment 6 Saam Barati 2020-05-07 18:34:07 PDT
Comment on attachment 398822 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398822&action=review

>> Source/JavaScriptCore/dfg/DFGArrayMode.cpp:430
>> +        return value.isType(SpecTypedArrayView);
> 
> how is this enough? e.g, how does this handle Float32Array vs Float64Array?

I think this is correct if we're AnyTypedArray

But for specific typed arrays, we need a lot more than this.
Comment 7 Saam Barati 2020-05-07 18:36:45 PDT
Comment on attachment 398822 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398822&action=review

> Source/JavaScriptCore/dfg/DFGArrayMode.cpp:247
> +        // As long as we have a JSArray getting its length shouldn't require any sane chainness.
> +        if (canBecomeGetArrayLength(graph, node) && isJSArray())
> +            return *this;

"Undecided" feels like the wrong name for this.
Comment 8 Saam Barati 2020-05-07 18:42:15 PDT
Comment on attachment 398822 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398822&action=review

> Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:901
> +            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), 0, m_jit.branchIfNotType(baseReg, JSType(FirstTypedArrayType), JSType(LastTypedArrayTypeExcludingDataView)));

nullptr, not zero. But why not provide the node?
Comment 9 Saam Barati 2020-05-07 18:48:58 PDT
Comment on attachment 398822 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398822&action=review

> Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:2031
> +                arrayMode = arrayMode.withType(Array::ForceExit);

can you also add an assert we can exit here?
Comment 10 Saam Barati 2020-05-07 18:49:37 PDT
Comment on attachment 398822 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398822&action=review

> Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:2033
> +            blessArrayOperation(node->child1(), Edge(), node->child2());

Maybe we need to assert we're always ok to exit
Comment 11 Keith Miller 2020-05-08 10:21:45 PDT
Created attachment 398872 [details]
Patch
Comment 12 Saam Barati 2020-05-08 11:44:21 PDT
Comment on attachment 398872 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398872&action=review

> Source/JavaScriptCore/ChangeLog:9
> +        to be configured during Fixup, then right now we will fail for

still not obvious here what you mean by "fail"

> Source/JavaScriptCore/ChangeLog:26
> +        previously pass it's own speculation for the speculation of the index, which logically

it's => its

> Source/JavaScriptCore/dfg/DFGArrayMode.cpp:433
> +    if (isSomeTypedArrayView()) {
> +        if (type() == Array::AnyTypedArray)
> +            return value.isType(SpecTypedArrayView);
> +        return value.isType(speculationFromTypedArrayType(typedArrayType()));
> +    }

can you construct a test where your old code would've been broken?

> Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:2031
> +                arrayMode = arrayMode.withType(Array::ForceExit);

assert we can exit here.

> Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:2032
> +            node->setArrayMode(arrayMode);

assert "isSpecific() here?

> Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:901
> +            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), 0, m_jit.branchIfNotType(baseReg, JSType(FirstTypedArrayType), JSType(LastTypedArrayTypeExcludingDataView)));

nullptr, not zero

> Source/JavaScriptCore/jit/AssemblyHelpers.h:991
> +        if (last && *last != first) {
> +            ASSERT(*last > first);
> +            GPRReg scratch = scratchRegister();
> +            load8(Address(cellGPR, JSCell::typeInfoTypeOffset()), scratch);
> +            sub32(TrustedImm32(first), scratch);
> +            return branch32(Below, scratch, TrustedImm32(*last - first));
> +        }

this is unused. I'd revert your change here

> Source/JavaScriptCore/jit/AssemblyHelpers.h:996
> +    Jump branchIfNotType(GPRReg cellGPR, JSType first, Optional<JSType> last = WTF::nullopt)

You should comment that first/last is inclusive

> Source/JavaScriptCore/jit/AssemblyHelpers.h:1003
> +            return branch32(AboveOrEqual, scratch, TrustedImm32(*last - first));

this is wrong, since "last" here is inclusive, you're going to say you're not the 'last' value AFAICT
Comment 13 Saam Barati 2020-05-08 11:45:59 PDT
Comment on attachment 398872 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398872&action=review

> Source/JavaScriptCore/runtime/JSType.h:134
>  static constexpr uint32_t LastTypedArrayType = DataViewType;

not your patch, but I feel like maybe we could name this better, and your new variable can subsume this name. "last" here reads to me like it should be inclusive, especially since "first" is
Comment 14 Keith Miller 2020-05-11 12:02:41 PDT
Comment on attachment 398872 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=398872&action=review

>> Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:2031
>> +                arrayMode = arrayMode.withType(Array::ForceExit);
> 
> assert we can exit here.

That must be true because GetArrayLength clobbers exit state before Fixup as it's a ArrayMode node.

>> Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:2032
>> +            node->setArrayMode(arrayMode);
> 
> assert "isSpecific() here?

That's not true because it can be ForceExit. :P But I can add ASSERT(isSpecific() || ForceExit).

>> Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:901
>> +            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), 0, m_jit.branchIfNotType(baseReg, JSType(FirstTypedArrayType), JSType(LastTypedArrayTypeExcludingDataView)));
> 
> nullptr, not zero

Done.

>> Source/JavaScriptCore/jit/AssemblyHelpers.h:991
>> +        }
> 
> this is unused. I'd revert your change here

I added it for symmetry.

>> Source/JavaScriptCore/jit/AssemblyHelpers.h:996
>> +    Jump branchIfNotType(GPRReg cellGPR, JSType first, Optional<JSType> last = WTF::nullopt)
> 
> You should comment that first/last is inclusive

Done.

>> Source/JavaScriptCore/jit/AssemblyHelpers.h:1003
>> +            return branch32(AboveOrEqual, scratch, TrustedImm32(*last - first));
> 
> this is wrong, since "last" here is inclusive, you're going to say you're not the 'last' value AFAICT

Yeah, you're right. I'll add at testmasm test for this.

>> Source/JavaScriptCore/runtime/JSType.h:134
>>  static constexpr uint32_t LastTypedArrayType = DataViewType;
> 
> not your patch, but I feel like maybe we could name this better, and your new variable can subsume this name. "last" here reads to me like it should be inclusive, especially since "first" is

Last is inclusive here. DataViews are JSArrayBufferViews so we include them in the list. We should probably make this more consistent throughout though.
Comment 15 Keith Miller 2020-05-11 12:05:34 PDT
Created attachment 399041 [details]
Patch
Comment 16 Keith Miller 2020-05-11 12:15:11 PDT
Created attachment 399043 [details]
Patch
Comment 17 Saam Barati 2020-05-11 16:46:33 PDT
Comment on attachment 399043 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=399043&action=review

r=me. Seems like you need to rebase

> Source/JavaScriptCore/ChangeLog:9
> +        to be configured during Fixup, then right now we will fail for

Fail how?

> Source/JavaScriptCore/assembler/testmasm.cpp:2198
> +static void testBranchIfNotType()

You could also have a microbenchmark too

> Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:2032
> +            node->setArrayMode(arrayMode);

It’s nice to have that assert you proposed. Maybe even in the DFG spec JIT / FTL lower. But here works too
Comment 18 Keith Miller 2020-05-12 12:19:45 PDT
Created attachment 399152 [details]
Patch for landing
Comment 19 Keith Miller 2020-05-12 12:19:49 PDT
Comment on attachment 399043 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=399043&action=review

>> Source/JavaScriptCore/ChangeLog:9
>> +        to be configured during Fixup, then right now we will fail for
> 
> Fail how?

Crash. Edited.

>> Source/JavaScriptCore/assembler/testmasm.cpp:2198
>> +static void testBranchIfNotType()
> 
> You could also have a microbenchmark too

This seems more consistent because if you "break" a microbenchmark we may or may not notice.

>> Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:2032
>> +            node->setArrayMode(arrayMode);
> 
> It’s nice to have that assert you proposed. Maybe even in the DFG spec JIT / FTL lower. But here works too

Ok, I'll add it.
Comment 20 Saam Barati 2020-05-12 12:39:27 PDT
Comment on attachment 399043 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=399043&action=review

>>> Source/JavaScriptCore/assembler/testmasm.cpp:2198
>>> +static void testBranchIfNotType()
>> 
>> You could also have a microbenchmark too
> 
> This seems more consistent because if you "break" a microbenchmark we may or may not notice.

"also", not "instead of"
Comment 21 EWS 2020-05-12 14:28:00 PDT
Found 17 new test failures: imported/w3c/web-platform-tests/IndexedDB/idlharness.any.html, imported/w3c/web-platform-tests/html/dom/idlharness.https.html, imported/w3c/web-platform-tests/notifications/interfaces.html, imported/w3c/web-platform-tests/resize-observer/idlharness.window.html, imported/w3c/web-platform-tests/media-source/interfaces.html, imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.html, imported/w3c/web-platform-tests/dom/idlharness.any.worker.html, imported/w3c/web-platform-tests/dom/idlharness.window.html, imported/w3c/web-platform-tests/css/cssom-view/idlharness.html, imported/w3c/web-platform-tests/xhr/idlharness.any.html, imported/w3c/web-platform-tests/xhr/idlharness.any.worker.html, imported/w3c/web-platform-tests/css/geometry/interfaces.worker.html, imported/w3c/web-platform-tests/fetch/api/idl.any.html, imported/w3c/web-platform-tests/resource-timing/idlharness.any.worker.html, js/dom/typed-array-set-different-types.html, fast/canvas/webgl/typed-arrays-in-workers.html, imported/w3c/web-platform-tests/fetch/api/idl.any.worker.html
Comment 22 Keith Miller 2020-05-12 15:06:28 PDT
Created attachment 399184 [details]
Patch for landing
Comment 23 Keith Miller 2020-05-12 15:07:03 PDT
(In reply to EWS from comment #21)
> Found 17 new test failures:
> imported/w3c/web-platform-tests/IndexedDB/idlharness.any.html,
> imported/w3c/web-platform-tests/html/dom/idlharness.https.html,
> imported/w3c/web-platform-tests/notifications/interfaces.html,
> imported/w3c/web-platform-tests/resize-observer/idlharness.window.html,
> imported/w3c/web-platform-tests/media-source/interfaces.html,
> imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.html,
> imported/w3c/web-platform-tests/dom/idlharness.any.worker.html,
> imported/w3c/web-platform-tests/dom/idlharness.window.html,
> imported/w3c/web-platform-tests/css/cssom-view/idlharness.html,
> imported/w3c/web-platform-tests/xhr/idlharness.any.html,
> imported/w3c/web-platform-tests/xhr/idlharness.any.worker.html,
> imported/w3c/web-platform-tests/css/geometry/interfaces.worker.html,
> imported/w3c/web-platform-tests/fetch/api/idl.any.html,
> imported/w3c/web-platform-tests/resource-timing/idlharness.any.worker.html,
> js/dom/typed-array-set-different-types.html,
> fast/canvas/webgl/typed-arrays-in-workers.html,
> imported/w3c/web-platform-tests/fetch/api/idl.any.worker.html

Whoops, forgot to add the callback that says we don't want storage for TypedArray lengths.
Comment 24 EWS 2020-05-12 17:16:19 PDT
Found 10 new test failures: imported/w3c/web-platform-tests/media-source/interfaces.html, imported/w3c/web-platform-tests/requestidlecallback/idlharness.window.html, imported/w3c/web-platform-tests/dom/idlharness.any.worker.html, imported/w3c/web-platform-tests/remote-playback/idlharness.window.html, imported/w3c/web-platform-tests/css/cssom-view/idlharness.html, imported/w3c/web-platform-tests/xhr/idlharness.any.html, imported/w3c/web-platform-tests/xhr/idlharness.any.worker.html, imported/w3c/web-platform-tests/WebCryptoAPI/idlharness.https.html, imported/w3c/web-platform-tests/fetch/api/idl.any.html, imported/w3c/web-platform-tests/css/geometry/interfaces.html
Comment 25 Keith Miller 2020-05-14 13:07:35 PDT
Created attachment 399395 [details]
Patch for landing
Comment 26 EWS 2020-05-14 15:01:55 PDT
Committed r261712: <https://trac.webkit.org/changeset/261712>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 399395 [details].