Changeset 271113 in webkit


Ignore:
Timestamp:
Dec 30, 2020 6:49:48 PM (19 months ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Wasm multivalue should iterate iterable result from JS function first before converting values
https://bugs.webkit.org/show_bug.cgi?id=220206

Reviewed by Alexey Shvayka.

LayoutTests/imported/w3c:

  • web-platform-tests/wasm/jsapi/constructor/multi-value.any-expected.txt:
  • web-platform-tests/wasm/jsapi/constructor/multi-value.any.worker-expected.txt:

Source/JavaScriptCore:

When converting JS results to Wasm multivalue (result from JS when executing Wasm->JS calls), we should first iterate all results from iterable.
And then, we should convert each element into Wasm value. Currently, we are converting while iterating, this is not aligned to the spec.

  • wasm/WasmOperations.cpp:

(JSC::Wasm::JSC_DEFINE_JIT_OPERATION):

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r271112 r271113  
     12020-12-30  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Wasm multivalue should iterate iterable result from JS function first before converting values
     4        https://bugs.webkit.org/show_bug.cgi?id=220206
     5
     6        Reviewed by Alexey Shvayka.
     7
     8        * web-platform-tests/wasm/jsapi/constructor/multi-value.any-expected.txt:
     9        * web-platform-tests/wasm/jsapi/constructor/multi-value.any.worker-expected.txt:
     10
    1112020-12-29  Yusuke Suzuki  <ysuzuki@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any-expected.txt

    r267649 r271113  
    22PASS multiple return values from wasm to js
    33PASS multiple return values inside wasm
    4 FAIL multiple return values from js to wasm assert_array_equals: expected property 6 to be "next call 2" but got "valueOf get 1" (expected array ["@@iterator getter", "@@iterator call", "next getter", "next call 1", "done call 1", "value call 1", "next call 2", "done call 2", "value call 2", "next call 3", "done call 3", "valueOf get 1", "valueOf call 1", "valueOf get 2", "valueOf call 2"] got ["@@iterator getter", "@@iterator call", "next getter", "next call 1", "done call 1", "value call 1", "valueOf get 1", "valueOf call 1", "next call 2", "done call 2", "value call 2", "valueOf get 2", "valueOf call 2", "next call 3", "done call 3"])
     4PASS multiple return values from js to wasm
    55
  • trunk/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.worker-expected.txt

    r267649 r271113  
    22PASS multiple return values from wasm to js
    33PASS multiple return values inside wasm
    4 FAIL multiple return values from js to wasm assert_array_equals: expected property 6 to be "next call 2" but got "valueOf get 1" (expected array ["@@iterator getter", "@@iterator call", "next getter", "next call 1", "done call 1", "value call 1", "next call 2", "done call 2", "value call 2", "next call 3", "done call 3", "valueOf get 1", "valueOf call 1", "valueOf get 2", "valueOf call 2"] got ["@@iterator getter", "@@iterator call", "next getter", "next call 1", "done call 1", "value call 1", "valueOf get 1", "valueOf call 1", "next call 2", "done call 2", "value call 2", "valueOf get 2", "valueOf call 2", "next call 3", "done call 3"])
     4PASS multiple return values from js to wasm
    55
  • trunk/Source/JavaScriptCore/ChangeLog

    r271112 r271113  
     12020-12-30  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Wasm multivalue should iterate iterable result from JS function first before converting values
     4        https://bugs.webkit.org/show_bug.cgi?id=220206
     5
     6        Reviewed by Alexey Shvayka.
     7
     8        When converting JS results to Wasm multivalue (result from JS when executing Wasm->JS calls), we should first iterate all results from iterable.
     9        And then, we should convert each element into Wasm value. Currently, we are converting while iterating, this is not aligned to the spec.
     10
     11        * wasm/WasmOperations.cpp:
     12        (JSC::Wasm::JSC_DEFINE_JIT_OPERATION):
     13
    1142020-12-29  Yusuke Suzuki  <ysuzuki@apple.com>
    215
  • trunk/Source/JavaScriptCore/wasm/WasmOperations.cpp

    r271100 r271113  
    509509}
    510510
     511// https://webassembly.github.io/multi-value/js-api/index.html#run-a-host-function
    511512JSC_DEFINE_JIT_OPERATION(operationIterateResults, void, (CallFrame* callFrame, Instance* instance, const Signature* signature, JSValue result, uint64_t* registerResults, uint64_t* calleeFramePointer))
    512513{
     
    522523    RegisterAtOffsetList registerResultOffsets = wasmCallInfo.computeResultsOffsetList();
    523524
    524     unsigned itemsInserted = 0;
    525     forEachInIterable(globalObject, result, [&] (VM& vm, JSGlobalObject* globalObject, JSValue value) -> void {
    526         auto scope = DECLARE_THROW_SCOPE(vm);
    527         if (itemsInserted < signature->returnCount()) {
    528             uint64_t unboxedValue;
    529             switch (signature->returnType(itemsInserted)) {
    530             case I32:
    531                 unboxedValue = value.toInt32(globalObject);
    532                 break;
    533             case F32:
    534                 unboxedValue = bitwise_cast<uint32_t>(value.toFloat(globalObject));
    535                 break;
    536             case F64:
    537                 unboxedValue = bitwise_cast<uint64_t>(value.toNumber(globalObject));
    538                 break;
    539             case Funcref:
    540                 if (!value.isCallable(vm)) {
    541                     throwTypeError(globalObject, scope, "Funcref value is not a function"_s);
    542                     return;
    543                 }
    544                 FALLTHROUGH;
    545             case Externref:
    546                 unboxedValue = bitwise_cast<uint64_t>(value);
    547                 RELEASE_ASSERT(Options::useWebAssemblyReferences());
    548                 break;
    549             default:
    550                 RELEASE_ASSERT_NOT_REACHED();
    551             }
    552 
    553             RETURN_IF_EXCEPTION(scope, void());
    554             auto rep = wasmCallInfo.results[itemsInserted];
    555             if (rep.isReg())
    556                 registerResults[registerResultOffsets.find(rep.reg())->offset() / sizeof(uint64_t)] = unboxedValue;
    557             else
    558                 calleeFramePointer[rep.offsetFromFP() / sizeof(uint64_t)] = unboxedValue;
    559         }
    560         itemsInserted++;
     525    MarkedArgumentBuffer buffer;
     526    forEachInIterable(globalObject, result, [&] (VM&, JSGlobalObject*, JSValue value) -> void {
     527        if (buffer.size() < signature->returnCount())
     528            buffer.append(value);
    561529    });
    562530    RETURN_IF_EXCEPTION(scope, void());
    563     if (itemsInserted != signature->returnCount())
     531
     532    if (buffer.hasOverflowed()) {
     533        throwOutOfMemoryError(globalObject, scope, "JS results to Wasm are too large");
     534        return;
     535    }
     536
     537    if (buffer.size() != signature->returnCount()) {
    564538        throwVMTypeError(globalObject, scope, "Incorrect number of values returned to Wasm from JS");
     539        return;
     540    }
     541
     542    for (unsigned index = 0; index < buffer.size(); ++index) {
     543        JSValue value = buffer.at(index);
     544
     545        uint64_t unboxedValue = 0;
     546        switch (signature->returnType(index)) {
     547        case I32:
     548            unboxedValue = value.toInt32(globalObject);
     549            break;
     550        case F32:
     551            unboxedValue = bitwise_cast<uint32_t>(value.toFloat(globalObject));
     552            break;
     553        case F64:
     554            unboxedValue = bitwise_cast<uint64_t>(value.toNumber(globalObject));
     555            break;
     556        case Funcref:
     557            if (!value.isCallable(vm)) {
     558                throwTypeError(globalObject, scope, "Funcref value is not a function"_s);
     559                return;
     560            }
     561            FALLTHROUGH;
     562        case Externref:
     563            unboxedValue = bitwise_cast<uint64_t>(value);
     564            RELEASE_ASSERT(Options::useWebAssemblyReferences());
     565            break;
     566        default:
     567            RELEASE_ASSERT_NOT_REACHED();
     568        }
     569        RETURN_IF_EXCEPTION(scope, void());
     570
     571        auto rep = wasmCallInfo.results[index];
     572        if (rep.isReg())
     573            registerResults[registerResultOffsets.find(rep.reg())->offset() / sizeof(uint64_t)] = unboxedValue;
     574        else
     575            calleeFramePointer[rep.offsetFromFP() / sizeof(uint64_t)] = unboxedValue;
     576    }
    565577}
    566578
Note: See TracChangeset for help on using the changeset viewer.