[WHLSL] Make .length work
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Jun 2019 21:44:23 +0000 (21:44 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Jun 2019 21:44:23 +0000 (21:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=198890

Reviewed by Myles Maxfield.

Source/WebCore:

This patch makes accessing .length on buffers work. To make this work as
expected, I've fixed a handful of small bugs:

- The checker was not calling resolveByInstantiation for getters. This patch
  modifies the checker to do that, so we can now resolve a getter to
  "operator.length". I also refactored the checker to have a helper method
  that both does overload resolution and resolveByInstantiation to make it
  difficult to forget to call resolveByInstantiation.
- The property resolver had a bug where it would return a non-null value
  in anderCallArgument for array references even when there was no ander and
  no thread ander function. This patch makes it now return null if there is
  neither an ander nor a thread ander.
- The metal codegen incorrectly unpacked the length of buffers. It swapped the
  bottom four bytes and the top four bytes of the size_t value. This patch
  corrects that. This was also a cause of flakiness in various tests since
  we ended up with a length much larger than expected, leading to bounds
  checks always passing in our tests.
- This patch also fixes our tests to specify the output buffer length
  properly for various programs.

Test: webgpu/whlsl-buffer-length.html

* Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp:
(WebCore::WHLSL::Metal::EntryPointScaffolding::unpackResourcesAndNamedBuiltIns):
* Modules/webgpu/WHLSL/WHLSLChecker.cpp:
(WebCore::WHLSL::resolveFunction):
(WebCore::WHLSL::Checker::finishVisiting):
(WebCore::WHLSL::Checker::visit):
* Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp:
(WebCore::WHLSL::anderCallArgument):

LayoutTests:

* TestExpectations:
* webgpu/whlsl-buffer-length-expected.txt: Added.
* webgpu/whlsl-buffer-length.html: Added.
* webgpu/whlsl-buffer-vertex.html:
* webgpu/whlsl-compute.html:
* webgpu/whlsl-null-dereference.html:
* webgpu/whlsl-oob-access.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@246515 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/webgpu/whlsl-buffer-length-expected.txt [new file with mode: 0644]
LayoutTests/webgpu/whlsl-buffer-length.html [new file with mode: 0644]
LayoutTests/webgpu/whlsl-buffer-vertex.html
LayoutTests/webgpu/whlsl-compute.html
LayoutTests/webgpu/whlsl-null-dereference.html
LayoutTests/webgpu/whlsl-oob-access.html
Source/WebCore/ChangeLog
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp

index 3c55618..c4ec313 100644 (file)
@@ -1,3 +1,18 @@
+2019-06-17  Saam Barati  <sbarati@apple.com>
+
+        [WHLSL] Make .length work
+        https://bugs.webkit.org/show_bug.cgi?id=198890
+
+        Reviewed by Myles Maxfield.
+
+        * TestExpectations:
+        * webgpu/whlsl-buffer-length-expected.txt: Added.
+        * webgpu/whlsl-buffer-length.html: Added.
+        * webgpu/whlsl-buffer-vertex.html:
+        * webgpu/whlsl-compute.html:
+        * webgpu/whlsl-null-dereference.html:
+        * webgpu/whlsl-oob-access.html:
+
 2019-06-17  Shawn Roberts  <sroberts@apple.com>
 
         scrollingcoordinator/ios/sync-layer-positions-after-scroll.html is a flaky failure on iOS Simulator
index be92e1c..0cacad5 100644 (file)
@@ -3413,6 +3413,3 @@ imported/w3c/web-platform-tests/websockets/Secure-Send-unpaired-surrogates.any.w
 
 # iOS only
 fast/dom/linkify-phone-numbers.html [ ImageOnlyFailure ]
-
-# FIXME: Should be fixed by: https://bugs.webkit.org/show_bug.cgi?id=198890
-webgpu/whlsl-oob-access.html [ Pass Failure ]
diff --git a/LayoutTests/webgpu/whlsl-buffer-length-expected.txt b/LayoutTests/webgpu/whlsl-buffer-length-expected.txt
new file mode 100644 (file)
index 0000000..c1b6704
--- /dev/null
@@ -0,0 +1,5 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS resultUint32Array[0] is 1337
+
diff --git a/LayoutTests/webgpu/whlsl-buffer-length.html b/LayoutTests/webgpu/whlsl-buffer-length.html
new file mode 100644 (file)
index 0000000..1b1512d
--- /dev/null
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+const shaderSource = `
+[numthreads(1, 1, 1)]
+compute void computeShader(device uint[] buffer : register(u0), float3 threadID : SV_DispatchThreadID) {
+    buffer[0] = buffer.length;
+}
+`;
+let resultUint32Array;
+async function start() {
+    const adapter = await navigator.gpu.requestAdapter();
+    const device = await adapter.requestDevice();
+
+    const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true});
+    const computeStage = {module: shaderModule, entryPoint: "computeShader"};
+
+    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "storage-buffer"}]};
+    const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
+    const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]};
+    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
+
+    const computePipelineDescriptor = {computeStage, layout: pipelineLayout};
+    const computePipeline = device.createComputePipeline(computePipelineDescriptor);
+
+    const size = Uint32Array.BYTES_PER_ELEMENT * 1337;
+
+    const bufferDescriptor = {size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
+    const buffer = device.createBuffer(bufferDescriptor);
+    const bufferArrayBuffer = await buffer.mapWriteAsync();
+    const bufferUint32Array = new Uint32Array(bufferArrayBuffer);
+    bufferUint32Array[0] = 0;
+    buffer.unmap();
+
+    const resultsBufferDescriptor = {size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ};
+    const resultsBuffer = device.createBuffer(resultsBufferDescriptor);
+
+    const bufferBinding = {buffer: resultsBuffer, size};
+    const bindGroupBinding = {binding: 0, resource: bufferBinding};
+    const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]};
+    const bindGroup = device.createBindGroup(bindGroupDescriptor);
+
+    const commandEncoder = device.createCommandEncoder(); // {}
+    commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, 1 * Uint32Array.BYTES_PER_ELEMENT);
+    const computePassEncoder = commandEncoder.beginComputePass();
+    computePassEncoder.setPipeline(computePipeline);
+    computePassEncoder.setBindGroup(0, bindGroup);
+    computePassEncoder.dispatch(1, 1, 1);
+    computePassEncoder.endPass();
+    const commandBuffer = commandEncoder.finish();
+    device.getQueue().submit([commandBuffer]);
+
+    const resultsArrayBuffer = await resultsBuffer.mapReadAsync();
+    resultUint32Array = new Uint32Array(resultsArrayBuffer);
+    shouldBe("resultUint32Array[0]", "1337");
+    resultsBuffer.unmap();
+}
+if (window.testRunner)
+    testRunner.waitUntilDone();
+window.addEventListener("load", function() {
+    start().then(function() {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }, function() {
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+});
+</script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
index 71d4e35..b192703 100644 (file)
@@ -38,7 +38,9 @@ async function start() {
     const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
     const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
 
-    const resourceBufferDescriptor = {size: 4 * 4 * Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE};
+    const size = 4 * 4 * Float32Array.BYTES_PER_ELEMENT;
+
+    const resourceBufferDescriptor = {size, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE};
     const resourceBuffer = device.createBuffer(resourceBufferDescriptor);
     const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync();
     const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer);
@@ -60,7 +62,7 @@ async function start() {
     resourceBufferFloat32Array[15] = 1;
     resourceBuffer.unmap();
 
-    const bufferBinding = {buffer: resourceBuffer, size: 4};
+    const bufferBinding = {buffer: resourceBuffer, size};
     const bindGroupBinding = {binding: 0, resource: bufferBinding};
     const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]};
     const bindGroup = device.createBindGroup(bindGroupDescriptor);
index 9058407..8a68efd 100644 (file)
@@ -27,7 +27,9 @@ async function start() {
     const computePipelineDescriptor = {computeStage, layout: pipelineLayout};
     const computePipeline = device.createComputePipeline(computePipelineDescriptor);
 
-    const bufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 8, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
+    const size = Float32Array.BYTES_PER_ELEMENT * 8;
+
+    const bufferDescriptor = {size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
     const buffer = device.createBuffer(bufferDescriptor);
     const bufferArrayBuffer = await buffer.mapWriteAsync();
     const bufferFloat32Array = new Float32Array(bufferArrayBuffer);
@@ -41,16 +43,16 @@ async function start() {
     bufferFloat32Array[7] = 8;
     buffer.unmap();
 
-    const resultsBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 8, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ};
+    const resultsBufferDescriptor = {size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ};
     const resultsBuffer = device.createBuffer(resultsBufferDescriptor);
 
-    const bufferBinding = {buffer: resultsBuffer, size: 4};
+    const bufferBinding = {buffer: resultsBuffer, size};
     const bindGroupBinding = {binding: 0, resource: bufferBinding};
     const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]};
     const bindGroup = device.createBindGroup(bindGroupDescriptor);
 
     const commandEncoder = device.createCommandEncoder(); // {}
-    commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, Float32Array.BYTES_PER_ELEMENT * 8);
+    commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, size);
     const computePassEncoder = commandEncoder.beginComputePass();
     computePassEncoder.setPipeline(computePipeline);
     computePassEncoder.setBindGroup(0, bindGroup);
index 6a81382..a848867 100644 (file)
@@ -63,7 +63,9 @@ async function start() {
     const computePipelineDescriptor = {computeStage, layout: pipelineLayout};
     const computePipeline = device.createComputePipeline(computePipelineDescriptor);
 
-    const bufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 8, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
+    const size = Float32Array.BYTES_PER_ELEMENT * 8;
+
+    const bufferDescriptor = {size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
     const buffer = device.createBuffer(bufferDescriptor);
     const bufferArrayBuffer = await buffer.mapWriteAsync();
     const bufferFloat32Array = new Float32Array(bufferArrayBuffer);
@@ -77,16 +79,16 @@ async function start() {
     bufferFloat32Array[7] = 8;
     buffer.unmap();
 
-    const resultsBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 8, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ};
+    const resultsBufferDescriptor = {size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ};
     const resultsBuffer = device.createBuffer(resultsBufferDescriptor);
 
-    const bufferBinding = {buffer: resultsBuffer, size: 4};
+    const bufferBinding = {buffer: resultsBuffer, size};
     const bindGroupBinding = {binding: 0, resource: bufferBinding};
     const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]};
     const bindGroup = device.createBindGroup(bindGroupDescriptor);
 
     const commandEncoder = device.createCommandEncoder(); // {}
-    commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, Float32Array.BYTES_PER_ELEMENT * 8);
+    commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, size);
     const computePassEncoder = commandEncoder.beginComputePass();
     computePassEncoder.setPipeline(computePipeline);
     computePassEncoder.setBindGroup(0, bindGroup);
index 4959cb1..8c696f2 100644 (file)
@@ -30,7 +30,9 @@ async function start() {
     const computePipelineDescriptor = {computeStage, layout: pipelineLayout};
     const computePipeline = device.createComputePipeline(computePipelineDescriptor);
 
-    const bufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 8, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
+    const size = Float32Array.BYTES_PER_ELEMENT * 8;
+
+    const bufferDescriptor = {size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
     const buffer = device.createBuffer(bufferDescriptor);
     const bufferArrayBuffer = await buffer.mapWriteAsync();
     const bufferFloat32Array = new Float32Array(bufferArrayBuffer);
@@ -44,16 +46,16 @@ async function start() {
     bufferFloat32Array[7] = 8;
     buffer.unmap();
 
-    const resultsBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 8, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ};
+    const resultsBufferDescriptor = {size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ};
     const resultsBuffer = device.createBuffer(resultsBufferDescriptor);
 
-    const bufferBinding = {buffer: resultsBuffer, size: 4};
+    const bufferBinding = {buffer: resultsBuffer, size};
     const bindGroupBinding = {binding: 0, resource: bufferBinding};
     const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]};
     const bindGroup = device.createBindGroup(bindGroupDescriptor);
 
     const commandEncoder = device.createCommandEncoder(); // {}
-    commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, Float32Array.BYTES_PER_ELEMENT * 8);
+    commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, size);
     const computePassEncoder = commandEncoder.beginComputePass();
     computePassEncoder.setPipeline(computePipeline);
     computePassEncoder.setBindGroup(0, bindGroup);
index 94711c2..9002855 100644 (file)
@@ -1,3 +1,41 @@
+2019-06-17  Saam Barati  <sbarati@apple.com>
+
+        [WHLSL] Make .length work
+        https://bugs.webkit.org/show_bug.cgi?id=198890
+
+        Reviewed by Myles Maxfield.
+
+        This patch makes accessing .length on buffers work. To make this work as
+        expected, I've fixed a handful of small bugs:
+        
+        - The checker was not calling resolveByInstantiation for getters. This patch
+          modifies the checker to do that, so we can now resolve a getter to
+          "operator.length". I also refactored the checker to have a helper method
+          that both does overload resolution and resolveByInstantiation to make it
+          difficult to forget to call resolveByInstantiation.
+        - The property resolver had a bug where it would return a non-null value
+          in anderCallArgument for array references even when there was no ander and
+          no thread ander function. This patch makes it now return null if there is
+          neither an ander nor a thread ander.
+        - The metal codegen incorrectly unpacked the length of buffers. It swapped the
+          bottom four bytes and the top four bytes of the size_t value. This patch
+          corrects that. This was also a cause of flakiness in various tests since
+          we ended up with a length much larger than expected, leading to bounds
+          checks always passing in our tests.
+        - This patch also fixes our tests to specify the output buffer length
+          properly for various programs.
+
+        Test: webgpu/whlsl-buffer-length.html
+
+        * Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp:
+        (WebCore::WHLSL::Metal::EntryPointScaffolding::unpackResourcesAndNamedBuiltIns):
+        * Modules/webgpu/WHLSL/WHLSLChecker.cpp:
+        (WebCore::WHLSL::resolveFunction):
+        (WebCore::WHLSL::Checker::finishVisiting):
+        (WebCore::WHLSL::Checker::visit):
+        * Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp:
+        (WebCore::WHLSL::anderCallArgument):
+
 2019-06-17  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r246501.
index 01fb71e..ec45da1 100644 (file)
@@ -315,9 +315,9 @@ String EntryPointScaffolding::unpackResourcesAndNamedBuiltIns()
                 auto& unnamedType = *m_entryPointItems.inputs[iterator->value].unnamedType;
                 auto mangledTypeName = m_typeNamer.mangledNameForType(downcast<AST::ReferenceType>(unnamedType).elementType());
 
-                stringBuilder.append(makeString("size_t ", lengthTemporaryName, " = ", variableName, '.', lengthElementName, ".x;\n"));
+                stringBuilder.append(makeString("size_t ", lengthTemporaryName, " = ", variableName, '.', lengthElementName, ".y;\n"));
                 stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " << 32;\n"));
-                stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " | ", variableName, '.', lengthElementName, ".y;\n"));
+                stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " | ", variableName, '.', lengthElementName, ".x;\n"));
                 stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " / sizeof(", mangledTypeName, ");\n"));
                 stringBuilder.append(makeString("if (", lengthTemporaryName, " > 0xFFFFFFFF) ", lengthTemporaryName, " = 0xFFFFFFFF;\n"));
                 stringBuilder.append(makeString(mangledInputPath(path), " = { ", variableName, '.', elementName, ", static_cast<uint32_t>(", lengthTemporaryName, ") };\n"));
index 35c70c9..2847295 100644 (file)
@@ -215,6 +215,19 @@ static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(const Str
     return WTF::nullopt;
 }
 
+static AST::FunctionDeclaration* resolveFunction(Program& program, Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1>& possibleOverloads, Vector<std::reference_wrapper<ResolvingType>>& types, const String& name, Lexer::Token origin, const Intrinsics& intrinsics, AST::NamedType* castReturnType = nullptr)
+{
+    if (AST::FunctionDeclaration* function = resolveFunctionOverload(possibleOverloads, types, castReturnType))
+        return function;
+
+    if (auto newFunction = resolveByInstantiation(name, origin, types, intrinsics)) {
+        program.append(WTFMove(*newFunction));
+        return &program.nativeFunctionDeclarations().last();
+    }
+
+    return nullptr;
+}
+
 static bool checkSemantics(Vector<EntryPointItem>& inputItems, Vector<EntryPointItem>& outputItems, const Optional<AST::EntryPointType>& entryPointType, const Intrinsics& intrinsics)
 {
     {
@@ -1004,7 +1017,7 @@ void Checker::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpres
         Vector<std::reference_wrapper<ResolvingType>> getterArgumentTypes { baseInfo->resolvingType };
         if (additionalArgumentType)
             getterArgumentTypes.append(*additionalArgumentType);
-        if ((getterFunction = resolveFunctionOverload(propertyAccessExpression.possibleGetterOverloads(), getterArgumentTypes)))
+        if ((getterFunction = resolveFunction(m_program, propertyAccessExpression.possibleGetterOverloads(), getterArgumentTypes, propertyAccessExpression.getterFunctionName(), propertyAccessExpression.origin(), m_intrinsics)))
             getterReturnType = &getterFunction->type();
     }
 
@@ -1017,13 +1030,8 @@ void Checker::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpres
             Vector<std::reference_wrapper<ResolvingType>> anderArgumentTypes { argumentType };
             if (additionalArgumentType)
                 anderArgumentTypes.append(*additionalArgumentType);
-            if ((anderFunction = resolveFunctionOverload(propertyAccessExpression.possibleAnderOverloads(), anderArgumentTypes)))
-                anderReturnType = &downcast<AST::PointerType>(anderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer
-            else if (auto newFunction = resolveByInstantiation(propertyAccessExpression.anderFunctionName(), propertyAccessExpression.origin(), anderArgumentTypes, m_intrinsics)) {
-                m_program.append(WTFMove(*newFunction));
-                anderFunction = &m_program.nativeFunctionDeclarations().last();
+            if ((anderFunction = resolveFunction(m_program, propertyAccessExpression.possibleAnderOverloads(), anderArgumentTypes, propertyAccessExpression.anderFunctionName(), propertyAccessExpression.origin(), m_intrinsics)))
                 anderReturnType = &downcast<AST::PointerType>(anderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer
-            }
         }
     }
 
@@ -1034,13 +1042,8 @@ void Checker::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpres
         Vector<std::reference_wrapper<ResolvingType>> threadAnderArgumentTypes { argumentType };
         if (additionalArgumentType)
             threadAnderArgumentTypes.append(*additionalArgumentType);
-        if ((threadAnderFunction = resolveFunctionOverload(propertyAccessExpression.possibleAnderOverloads(), threadAnderArgumentTypes)))
+        if ((threadAnderFunction = resolveFunction(m_program, propertyAccessExpression.possibleAnderOverloads(), threadAnderArgumentTypes, propertyAccessExpression.anderFunctionName(), propertyAccessExpression.origin(), m_intrinsics)))
             threadAnderReturnType = &downcast<AST::PointerType>(threadAnderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer
-        else if (auto newFunction = resolveByInstantiation(propertyAccessExpression.anderFunctionName(), propertyAccessExpression.origin(), threadAnderArgumentTypes, m_intrinsics)) {
-            m_program.append(WTFMove(*newFunction));
-            threadAnderFunction = &m_program.nativeFunctionDeclarations().last();
-            threadAnderReturnType = &downcast<AST::PointerType>(anderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer
-        }
     }
 
     if (leftAddressSpace && !anderFunction && !getterFunction) {
@@ -1083,7 +1086,7 @@ void Checker::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpres
         if (additionalArgumentType)
             setterArgumentTypes.append(*additionalArgumentType);
         setterArgumentTypes.append(fieldResolvingType);
-        setterFunction = resolveFunctionOverload(propertyAccessExpression.possibleSetterOverloads(), setterArgumentTypes);
+        setterFunction = resolveFunction(m_program, propertyAccessExpression.possibleSetterOverloads(), setterArgumentTypes, propertyAccessExpression.setterFunctionName(), propertyAccessExpression.origin(), m_intrinsics);
         if (setterFunction)
             setterReturnType = &setterFunction->type();
     }
@@ -1468,14 +1471,7 @@ void Checker::visit(AST::CallExpression& callExpression)
     // We don't want to recurse to the same node twice.
 
     ASSERT(callExpression.hasOverloads());
-    auto* function = resolveFunctionOverload(*callExpression.overloads(), types, callExpression.castReturnType());
-    if (!function) {
-        if (auto newFunction = resolveByInstantiation(callExpression.name(), callExpression.origin(), types, m_intrinsics)) {
-            m_program.append(WTFMove(*newFunction));
-            function = &m_program.nativeFunctionDeclarations().last();
-        }
-    }
-
+    auto* function = resolveFunction(m_program, *callExpression.overloads(), types, callExpression.name(), callExpression.origin(), m_intrinsics, callExpression.castReturnType());
     if (!function) {
         setError();
         return;
index 2a3b9b8..cd258b7 100644 (file)
@@ -142,6 +142,8 @@ static Optional<AnderCallArgumentResult> wrapAnderCallArgument(UniqueRef<AST::Ex
 
 static Optional<AnderCallArgumentResult> anderCallArgument(UniqueRef<AST::Expression>& expression, bool anderFunction, bool threadAnderFunction)
 {
+    if (!anderFunction && !threadAnderFunction)
+        return WTF::nullopt;
     auto& unifyNode = expression->resolvedType().unifyNode();
     if (is<AST::UnnamedType>(unifyNode)) {
         auto& unnamedType = downcast<AST::UnnamedType>(unifyNode);