Changeset 279265 in webkit


Ignore:
Timestamp:
Jun 24, 2021 7:23:28 PM (13 months ago)
Author:
commit-queue@webkit.org
Message:

[WASM-Function-References] Add support for (ref null? $t) type constructor
https://bugs.webkit.org/show_bug.cgi?id=226296

JSTests:

Adds additional tests for uses of (ref $t) and (ref null $t)
types, including with non-null extern/funcrefs.

Patch by Asumu Takikawa <asumu@igalia.com> on 2021-06-24
Reviewed by Yusuke Suzuki.

  • wasm/function-references/ref_types.js: Added.

(module):
(async testRefTypeLocal):
(async testNonNullRefTypeLocal):
(async testRefTypeInSignature):
(async testRefTypeParamCheck):
(async testRefGlobalCheck):
(async testExternFuncrefNonNullCheck):
(async testExternrefCompatibility):
(async testNonNullExternrefIncompatible):
(async testFuncrefCompatibility):
(async testNonNullFuncrefIncompatible):

  • wasm/wasm.json:

Source/JavaScriptCore:

Patch by Asumu Takikawa <asumu@igalia.com> on 2021-06-24
Reviewed by Yusuke Suzuki.

Adds the ref type constructor from the typed function references proposal:

https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md

It's also required for the type imports and GC proposals as well. Ref types represent
references to any heap type (including existing funcref and externref) with a specified
nullability.

This requires a new isNullable flag in the type representation. This flag also enables
non-null externref and funcrefs, and hence this commit also adds the necessary checks
at Wasm/JS boundaries.

Non-null reference types also generally cannot be used as function locals.

  • wasm/WasmAirIRGenerator.cpp:

(JSC::Wasm::AirIRGenerator::gTypeIdx):
(JSC::Wasm::AirIRGenerator::tmpForType):
(JSC::Wasm::AirIRGenerator::emitCCall):
(JSC::Wasm::AirIRGenerator::moveOpForValueType):
(JSC::Wasm::AirIRGenerator::AirIRGenerator):
(JSC::Wasm::AirIRGenerator::addLocal):
(JSC::Wasm::AirIRGenerator::addConstant):
(JSC::Wasm::AirIRGenerator::addRefFunc):

  • wasm/WasmCallingConvention.h:

(JSC::Wasm::WasmCallingConvention::marshallLocation const):
(JSC::Wasm::JSCallingConvention::marshallLocation const):

  • wasm/WasmFormat.h:

(JSC::Wasm::isSubtype):
(JSC::Wasm::isValidHeapTypeKind):
(JSC::Wasm::isDefaultableType):

  • wasm/WasmFunctionParser.h:

(JSC::Wasm::FunctionParser<Context>::parse):
(JSC::Wasm::FunctionParser<Context>::parseAnnotatedSelectImmediates):
(JSC::Wasm::FunctionParser<Context>::checkBranchTarget):
(JSC::Wasm::FunctionParser<Context>::parseExpression):

  • wasm/WasmGlobal.cpp:

(JSC::Wasm::Global::get const):
(JSC::Wasm::Global::set):

  • wasm/WasmLLIntGenerator.cpp:

(JSC::Wasm::LLIntGenerator::callInformationForCaller):
(JSC::Wasm::LLIntGenerator::callInformationForCallee):
(JSC::Wasm::LLIntGenerator::addArguments):

  • wasm/WasmParser.h:

(JSC::Wasm::Parser<SuccessType>::parseBlockSignature):
(JSC::Wasm::Parser<SuccessType>::parseValueType):
(JSC::Wasm::Parser<SuccessType>::parseRefType):

  • wasm/WasmSectionParser.cpp:

(JSC::Wasm::SectionParser::parseType):
(JSC::Wasm::SectionParser::parseElement):
(JSC::Wasm::SectionParser::parseInitExpr):
(JSC::Wasm::SectionParser::parseElementSegmentVectorOfExpressions):
(JSC::Wasm::SectionParser::parseGlobalType):

  • wasm/WasmSignature.cpp:

(JSC::Wasm::computeHash):

  • wasm/generateWasmOpsHeader.py:
  • wasm/js/WasmToJS.cpp:

(JSC::Wasm::wasmToJS):

  • wasm/js/WebAssemblyFunction.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::WebAssemblyFunction::jsCallEntrypointSlow):

  • wasm/js/WebAssemblyFunctionBase.h:

(JSC::WebAssemblyFunctionBase::offsetOfSignatureIndex):

  • wasm/js/WebAssemblyModuleRecord.cpp:

(JSC::WebAssemblyModuleRecord::linkImpl):

  • wasm/wasm.json:
Location:
trunk
Files:
1 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r279243 r279265  
     12021-06-24  Asumu Takikawa  <asumu@igalia.com>
     2
     3        [WASM-Function-References] Add support for (ref null? $t) type constructor
     4        https://bugs.webkit.org/show_bug.cgi?id=226296
     5
     6        Adds additional tests for uses of `(ref $t)` and `(ref null $t)`
     7        types, including with non-null extern/funcrefs.
     8
     9        Reviewed by Yusuke Suzuki.
     10
     11        * wasm/function-references/ref_types.js: Added.
     12        (module):
     13        (async testRefTypeLocal):
     14        (async testNonNullRefTypeLocal):
     15        (async testRefTypeInSignature):
     16        (async testRefTypeParamCheck):
     17        (async testRefGlobalCheck):
     18        (async testExternFuncrefNonNullCheck):
     19        (async testExternrefCompatibility):
     20        (async testNonNullExternrefIncompatible):
     21        (async testFuncrefCompatibility):
     22        (async testNonNullFuncrefIncompatible):
     23        * wasm/wasm.json:
     24
    1252021-06-24  Guillaume Emont  <guijemont@igalia.com>
    226
  • trunk/JSTests/wasm/wasm.json

    r276896 r279265  
    1414        "funcref":   { "type": "varint7", "value":  -16, "b3type": "B3::Int64" },
    1515        "externref": { "type": "varint7", "value":  -17, "b3type": "B3::Int64" },
     16        "ref_null":  { "type": "varint7", "value":  -20, "b3type": "B3::Int64" },
     17        "ref":       { "type": "varint7", "value":  -21, "b3type": "B3::Int64" },
    1618        "func":      { "type": "varint7", "value":  -32, "b3type": "B3::Void" },
    1719        "void":      { "type": "varint7", "value":  -64, "b3type": "B3::Void" },
  • trunk/Source/JavaScriptCore/ChangeLog

    r279256 r279265  
     12021-06-24  Asumu Takikawa  <asumu@igalia.com>
     2
     3        [WASM-Function-References] Add support for (ref null? $t) type constructor
     4        https://bugs.webkit.org/show_bug.cgi?id=226296
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        Adds the `ref` type constructor from the typed function references proposal:
     9
     10          https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md
     11
     12        It's also required for the type imports and GC proposals as well. Ref types represent
     13        references to any heap type (including existing funcref and externref) with a specified
     14        nullability.
     15
     16        This requires a new isNullable flag in the type representation. This flag also enables
     17        non-null externref and funcrefs, and hence this commit also adds the necessary checks
     18        at Wasm/JS boundaries.
     19
     20        Non-null reference types also generally cannot be used as function locals.
     21
     22        * wasm/WasmAirIRGenerator.cpp:
     23        (JSC::Wasm::AirIRGenerator::gTypeIdx):
     24        (JSC::Wasm::AirIRGenerator::tmpForType):
     25        (JSC::Wasm::AirIRGenerator::emitCCall):
     26        (JSC::Wasm::AirIRGenerator::moveOpForValueType):
     27        (JSC::Wasm::AirIRGenerator::AirIRGenerator):
     28        (JSC::Wasm::AirIRGenerator::addLocal):
     29        (JSC::Wasm::AirIRGenerator::addConstant):
     30        (JSC::Wasm::AirIRGenerator::addRefFunc):
     31        * wasm/WasmCallingConvention.h:
     32        (JSC::Wasm::WasmCallingConvention::marshallLocation const):
     33        (JSC::Wasm::JSCallingConvention::marshallLocation const):
     34        * wasm/WasmFormat.h:
     35        (JSC::Wasm::isSubtype):
     36        (JSC::Wasm::isValidHeapTypeKind):
     37        (JSC::Wasm::isDefaultableType):
     38        * wasm/WasmFunctionParser.h:
     39        (JSC::Wasm::FunctionParser<Context>::parse):
     40        (JSC::Wasm::FunctionParser<Context>::parseAnnotatedSelectImmediates):
     41        (JSC::Wasm::FunctionParser<Context>::checkBranchTarget):
     42        (JSC::Wasm::FunctionParser<Context>::parseExpression):
     43        * wasm/WasmGlobal.cpp:
     44        (JSC::Wasm::Global::get const):
     45        (JSC::Wasm::Global::set):
     46        * wasm/WasmLLIntGenerator.cpp:
     47        (JSC::Wasm::LLIntGenerator::callInformationForCaller):
     48        (JSC::Wasm::LLIntGenerator::callInformationForCallee):
     49        (JSC::Wasm::LLIntGenerator::addArguments):
     50        * wasm/WasmParser.h:
     51        (JSC::Wasm::Parser<SuccessType>::parseBlockSignature):
     52        (JSC::Wasm::Parser<SuccessType>::parseValueType):
     53        (JSC::Wasm::Parser<SuccessType>::parseRefType):
     54        * wasm/WasmSectionParser.cpp:
     55        (JSC::Wasm::SectionParser::parseType):
     56        (JSC::Wasm::SectionParser::parseElement):
     57        (JSC::Wasm::SectionParser::parseInitExpr):
     58        (JSC::Wasm::SectionParser::parseElementSegmentVectorOfExpressions):
     59        (JSC::Wasm::SectionParser::parseGlobalType):
     60        * wasm/WasmSignature.cpp:
     61        (JSC::Wasm::computeHash):
     62        * wasm/generateWasmOpsHeader.py:
     63        * wasm/js/WasmToJS.cpp:
     64        (JSC::Wasm::wasmToJS):
     65        * wasm/js/WebAssemblyFunction.cpp:
     66        (JSC::JSC_DEFINE_HOST_FUNCTION):
     67        (JSC::WebAssemblyFunction::jsCallEntrypointSlow):
     68        * wasm/js/WebAssemblyFunctionBase.h:
     69        (JSC::WebAssemblyFunctionBase::offsetOfSignatureIndex):
     70        * wasm/js/WebAssemblyModuleRecord.cpp:
     71        (JSC::WebAssemblyModuleRecord::linkImpl):
     72        * wasm/wasm.json:
     73
    1742021-06-24  Mark Lam  <mark.lam@apple.com>
    275
  • trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp

    r279256 r279265  
    414414    TypedTmp gExternref() { return { newTmp(B3::GP), Types::Externref }; }
    415415    TypedTmp gFuncref() { return { newTmp(B3::GP), Types::Funcref }; }
     416    TypedTmp gTypeIdx(Type type) { return { newTmp(B3::GP), type }; }
    416417    TypedTmp f32() { return { newTmp(B3::FP), Types::F32 }; }
    417418    TypedTmp f64() { return { newTmp(B3::FP), Types::F64 }; }
     
    426427        case TypeKind::Funcref:
    427428            return gFuncref();
     429        case TypeKind::TypeIdx:
     430            return gTypeIdx(type);
    428431        case TypeKind::Externref:
    429432            return gExternref();
     
    602605            case TypeKind::Externref:
    603606            case TypeKind::Funcref:
     607            case TypeKind::TypeIdx:
    604608                resultType = B3::Int64;
    605609                break;
     
    651655        case TypeKind::Externref:
    652656        case TypeKind::Funcref:
     657        case TypeKind::TypeIdx:
    653658            return Move;
    654659        case TypeKind::F32:
     
    908913        case TypeKind::Externref:
    909914        case TypeKind::Funcref:
     915        case TypeKind::TypeIdx:
    910916            append(Move, arg, m_locals[i]);
    911917            break;
     
    10101016        case TypeKind::Externref:
    10111017        case TypeKind::Funcref:
     1018        case TypeKind::TypeIdx:
    10121019            append(Move, Arg::imm(JSValue::encode(jsNull())), local);
    10131020            break;
     
    10451052    case TypeKind::Externref:
    10461053    case TypeKind::Funcref:
     1054    case TypeKind::TypeIdx:
    10471055        append(block, Move, Arg::bigImm(value), result);
    10481056        break;
     
    10891097{
    10901098    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
    1091     result = tmpForType(Types::Funcref);
     1099    if (Options::useWebAssemblyTypedFunctionReferences()) {
     1100        SignatureIndex signatureIndex = m_info.signatureIndexFromFunctionIndexSpace(index);
     1101        result = tmpForType(Type { TypeKind::TypeIdx, Nullable::No, signatureIndex });
     1102    } else
     1103        result = tmpForType(Types::Funcref);
    10921104    emitCCall(&operationWasmRefFunc, result, instanceValue(), addConstant(Types::I32, index));
    10931105
  • trunk/Source/JavaScriptCore/wasm/WasmCallingConvention.h

    r273813 r279265  
    108108        case TypeKind::Funcref:
    109109        case TypeKind::Externref:
     110        case TypeKind::TypeIdx:
    110111            return marshallLocationImpl(role, gprArgs, gpArgumentCount, stackOffset);
    111112        case TypeKind::F32:
     
    196197        case TypeKind::Funcref:
    197198        case TypeKind::Externref:
     199        case TypeKind::TypeIdx:
    198200            return marshallLocationImpl(role, gprArgs, gpArgumentCount, stackOffset);
    199201        case TypeKind::F32:
  • trunk/Source/JavaScriptCore/wasm/WasmFormat.h

    r278340 r279265  
    8080inline bool isSubtype(Type sub, Type parent)
    8181{
     82    if (sub.isNullable() && !parent.isNullable())
     83        return false;
     84
    8285    if (sub.isTypeIdx() && parent.isFuncref())
    8386        return true;
     
    8992{
    9093    return type.isFuncref() || type.isExternref() || type.isTypeIdx();
     94}
     95
     96inline bool isValidHeapTypeKind(TypeKind kind)
     97{
     98    switch (kind) {
     99    case TypeKind::Funcref:
     100    case TypeKind::Externref:
     101        return true;
     102    default:
     103        break;
     104    }
     105    return false;
     106}
     107
     108inline bool isDefaultableType(Type type)
     109{
     110    return !isRefType(type) || type.isNullable();
    91111}
    92112
  • trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h

    r276896 r279265  
    244244        totalNumberOfLocals += numberOfLocals;
    245245        WASM_PARSER_FAIL_IF(totalNumberOfLocals > maxFunctionLocals, "Function's number of locals is too big ", totalNumberOfLocals, " maximum ", maxFunctionLocals);
    246         WASM_PARSER_FAIL_IF(!parseValueType(typeOfLocal), "can't get Function local's type in group ", i);
     246        WASM_PARSER_FAIL_IF(!parseValueType(m_info, typeOfLocal), "can't get Function local's type in group ", i);
     247        WASM_PARSER_FAIL_IF(!isDefaultableType(typeOfLocal), "Function locals must have a defaultable type");
    247248
    248249        WASM_PARSER_FAIL_IF(!m_locals.tryReserveCapacity(totalNumberOfLocals), "can't allocate enough memory for function's ", totalNumberOfLocals, " locals");
     
    645646
    646647    Type targetType;
    647     WASM_PARSER_FAIL_IF(!parseValueType(targetType), "select can't parse annotations");
     648    WASM_PARSER_FAIL_IF(!parseValueType(m_info, targetType), "select can't parse annotations");
    648649
    649650    result.sizeOfAnnotationVector = sizeOfAnnotationVector;
     
    700701    unsigned offset = m_expressionStack.size() - target.branchTargetArity();
    701702    for (unsigned i = 0; i < target.branchTargetArity(); ++i)
    702         WASM_VALIDATOR_FAIL_IF(!isSubtype(target.branchTargetType(i), m_expressionStack[offset + i].type()), "branch's stack type is not a block's type branch target type. Stack value has type", m_expressionStack[offset + i].type().kind, " but branch target expects a value of ", target.branchTargetType(i).kind, " at index ", i);
     703        WASM_VALIDATOR_FAIL_IF(!isSubtype(m_expressionStack[offset + i].type(), target.branchTargetType(i)), "branch's stack type is not a block's type branch target type. Stack value has type ", m_expressionStack[offset + i].type().kind, " but branch target expects a value of ", target.branchTargetType(i).kind, " at index ", i);
    703704
    704705    return { };
     
    10801081        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
    10811082        Type typeOfNull;
    1082         WASM_PARSER_FAIL_IF(!parseRefType(typeOfNull), "ref.null type must be a reference type");
     1083        WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a reference type");
    10831084        m_expressionStack.constructAndAppend(typeOfNull, m_context.addConstant(typeOfNull, JSValue::encode(jsNull())));
    10841085        return { };
     
    11101111        if (Options::useWebAssemblyTypedFunctionReferences()) {
    11111112            SignatureIndex signatureIndex = m_info.signatureIndexFromFunctionIndexSpace(index);
    1112             m_expressionStack.constructAndAppend(Type {TypeKind::TypeIdx, signatureIndex}, result);
     1113            m_expressionStack.constructAndAppend(Type {TypeKind::TypeIdx, Nullable::No, signatureIndex}, result);
    11131114            return { };
    11141115        }
  • trunk/Source/JavaScriptCore/wasm/WasmGlobal.cpp

    r273813 r279265  
    4949    case TypeKind::Externref:
    5050    case TypeKind::Funcref:
     51    case TypeKind::TypeIdx:
    5152        return m_value.m_externref.get();
    5253    default:
     
    8788    case TypeKind::Externref: {
    8889        RELEASE_ASSERT(m_owner);
     90        if (!m_type.isNullable() && argument.isNull()) {
     91            throwException(globalObject, throwScope, createJSWebAssemblyRuntimeError(globalObject, vm, "Non-null Externref cannot be null"));
     92            return;
     93        }
    8994        m_value.m_externref.set(m_owner->vm(), m_owner, argument);
    9095        break;
    9196    }
     97    case TypeKind::TypeIdx:
    9298    case TypeKind::Funcref: {
    9399        RELEASE_ASSERT(m_owner);
    94         if (!isWebAssemblyHostFunction(vm, argument) && !argument.isNull()) {
     100        bool isNullable = m_type.isNullable();
     101        WebAssemblyFunction* wasmFunction = nullptr;
     102        WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
     103        if (!isWebAssemblyHostFunction(vm, argument, wasmFunction, wasmWrapperFunction) && (!isNullable || !argument.isNull())) {
    95104            throwException(globalObject, throwScope, createJSWebAssemblyRuntimeError(globalObject, vm, "Funcref must be an exported wasm function"));
    96105            return;
     106        }
     107        if (m_type.kind == TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
     108            Wasm::SignatureIndex paramIndex = m_type.index;
     109            Wasm::SignatureIndex argIndex;
     110            if (wasmFunction)
     111                argIndex = wasmFunction->signatureIndex();
     112            else
     113                argIndex = wasmWrapperFunction->signatureIndex();
     114            if (paramIndex != argIndex) {
     115                throwException(globalObject, throwScope, createJSWebAssemblyRuntimeError(globalObject, vm, "Argument function did not match the reference type"));
     116                return;
     117            }
    97118        }
    98119        m_value.m_externref.set(m_owner->vm(), m_owner, argument);
  • trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp

    r279082 r279265  
    563563        case TypeKind::Void:
    564564        case TypeKind::Func:
     565        case TypeKind::RefNull:
     566        case TypeKind::Ref:
    565567            RELEASE_ASSERT_NOT_REACHED();
    566568        }
     
    619621        case TypeKind::Void:
    620622        case TypeKind::Func:
     623        case TypeKind::RefNull:
     624        case TypeKind::Ref:
    621625            RELEASE_ASSERT_NOT_REACHED();
    622626        }
     
    647651        case TypeKind::Void:
    648652        case TypeKind::Func:
     653        case TypeKind::RefNull:
     654        case TypeKind::Ref:
    649655            RELEASE_ASSERT_NOT_REACHED();
    650656        }
     
    703709        case TypeKind::Void:
    704710        case TypeKind::Func:
     711        case TypeKind::RefNull:
     712        case TypeKind::Ref:
    705713            RELEASE_ASSERT_NOT_REACHED();
    706714        }
     
    752760        case TypeKind::Void:
    753761        case TypeKind::Func:
     762        case TypeKind::RefNull:
     763        case TypeKind::Ref:
    754764            RELEASE_ASSERT_NOT_REACHED();
    755765        }
  • trunk/Source/JavaScriptCore/wasm/WasmParser.h

    r273813 r279265  
    8585
    8686    PartialResult WARN_UNUSED_RETURN parseBlockSignature(const ModuleInformation&, BlockSignature&);
    87     bool WARN_UNUSED_RETURN parseValueType(Type&);
    88     bool WARN_UNUSED_RETURN parseRefType(Type&);
     87    bool WARN_UNUSED_RETURN parseValueType(const ModuleInformation&, Type&);
     88    bool WARN_UNUSED_RETURN parseRefType(const ModuleInformation&, Type&);
    8989    bool WARN_UNUSED_RETURN parseExternalKind(ExternalKind&);
    9090
     
    278278    int8_t typeKind;
    279279    if (peekInt7(typeKind) && isValidTypeKind(typeKind)) {
    280         Type type = {static_cast<TypeKind>(typeKind), 0};
     280        Type type = {static_cast<TypeKind>(typeKind), Nullable::Yes, 0};
    281281        WASM_PARSER_FAIL_IF(!(isValueType(type) || type.isVoid()), "result type of block: ", makeString(type.kind), " is not a value type or Void");
    282282        result = m_signatureInformation.thunkFor(type);
     
    297297
    298298template<typename SuccessType>
    299 ALWAYS_INLINE bool Parser<SuccessType>::parseValueType(Type& result)
     299ALWAYS_INLINE bool Parser<SuccessType>::parseValueType(const ModuleInformation& info, Type& result)
    300300{
    301301    int8_t kind;
    302302    if (!parseInt7(kind))
    303303        return false;
    304     Type type = {static_cast<TypeKind>(kind), 0};
    305     if (!isValidTypeKind(kind) || !isValueType(type))
     304    if (!isValidTypeKind(kind))
     305        return false;
     306
     307    TypeKind typeKind = static_cast<TypeKind>(kind);
     308    bool isNullable = true;
     309    SignatureIndex sigIndex = 0;
     310    if (typeKind == TypeKind::Ref || typeKind == TypeKind::RefNull) {
     311        if (!Options::useWebAssemblyTypedFunctionReferences())
     312            return false;
     313
     314        int32_t heapType;
     315        isNullable = typeKind == TypeKind::RefNull;
     316
     317        if (!parseVarInt32(heapType))
     318            return false;
     319        if (heapType < 0) {
     320            TypeKind heapKind = static_cast<TypeKind>(heapType);
     321            if (!isValidHeapTypeKind(heapKind))
     322                return false;
     323            typeKind = heapKind;
     324        } else {
     325            typeKind = TypeKind::TypeIdx;
     326            if (static_cast<size_t>(heapType) >= info.usedSignatures.size())
     327                return false;
     328            sigIndex = SignatureInformation::get(info.usedSignatures[heapType].get());
     329        }
     330    }
     331
     332    Type type = { typeKind, static_cast<Nullable>(isNullable), sigIndex };
     333    if (!isValueType(type))
    306334        return false;
    307335    result = type;
     
    310338
    311339template<typename SuccessType>
    312 ALWAYS_INLINE bool Parser<SuccessType>::parseRefType(Type& result)
    313 {
    314     const bool parsed = parseValueType(result);
     340ALWAYS_INLINE bool Parser<SuccessType>::parseRefType(const ModuleInformation& info, Type& result)
     341{
     342    const bool parsed = parseValueType(info, result);
    315343    return parsed && isRefType(result);
    316344}
  • trunk/Source/JavaScriptCore/wasm/WasmSectionParser.cpp

    r278340 r279265  
    6161        for (unsigned i = 0; i < argumentCount; ++i) {
    6262            Type argumentType;
    63             WASM_PARSER_FAIL_IF(!parseValueType(argumentType), "can't get ", i, "th argument Type");
     63            WASM_PARSER_FAIL_IF(!parseValueType(m_info, argumentType), "can't get ", i, "th argument Type");
    6464            arguments.append(argumentType);
    6565        }
     
    7373        for (unsigned i = 0; i < returnCount; ++i) {
    7474            Type value;
    75             WASM_PARSER_FAIL_IF(!parseValueType(value), "can't get ", i, "th Type's return value");
     75            WASM_PARSER_FAIL_IF(!parseValueType(m_info, value), "can't get ", i, "th Type's return value");
    7676            returnTypes.append(value);
    7777        }
     
    484484            WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
    485485            Type refType;
    486             WASM_PARSER_FAIL_IF(!parseRefType(refType), "can't parse reftype in elem section");
     486            WASM_PARSER_FAIL_IF(!parseRefType(m_info, refType), "can't parse reftype in elem section");
    487487            WASM_PARSER_FAIL_IF(!refType.isFuncref(), "reftype in element section should be funcref");
    488488
     
    508508
    509509            Type refType;
    510             WASM_PARSER_FAIL_IF(!parseRefType(refType), "can't parse reftype in elem section");
     510            WASM_PARSER_FAIL_IF(!parseRefType(m_info, refType), "can't parse reftype in elem section");
    511511            WASM_PARSER_FAIL_IF(!refType.isFuncref(), "reftype in element section should be funcref");
    512512
     
    526526
    527527            Type refType;
    528             WASM_PARSER_FAIL_IF(!parseRefType(refType), "can't parse reftype in elem section");
     528            WASM_PARSER_FAIL_IF(!parseRefType(m_info, refType), "can't parse reftype in elem section");
    529529            WASM_PARSER_FAIL_IF(!refType.isFuncref(), "reftype in element section should be funcref");
    530530
     
    606606    case RefNull: {
    607607        Type typeOfNull;
    608         WASM_PARSER_FAIL_IF(!parseRefType(typeOfNull), "ref.null type must be a reference type");
     608        WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a reference type");
    609609        resultType = typeOfNull;
    610610        bitsOrImportNumber = JSValue::encode(jsNull());
     
    617617        WASM_PARSER_FAIL_IF(index >= m_info->functions.size(), "ref.func index", index, " exceeds the number of functions ", m_info->functions.size());
    618618
    619         resultType = Types::Funcref;
     619        if (Options::useWebAssemblyTypedFunctionReferences()) {
     620            SignatureIndex signatureIndex = m_info->signatureIndexFromFunctionIndexSpace(index);
     621            resultType = { TypeKind::TypeIdx, Nullable::No, signatureIndex };
     622        } else
     623            resultType = Types::Funcref;
     624
    620625        bitsOrImportNumber = index;
    621626        break;
     
    692697        } else {
    693698            Type typeOfNull;
    694             WASM_PARSER_FAIL_IF(!parseRefType(typeOfNull), "ref.null type must be a func type in elem section");
     699            WASM_PARSER_FAIL_IF(!parseRefType(m_info, typeOfNull), "ref.null type must be a func type in elem section");
    695700            WASM_PARSER_FAIL_IF(!typeOfNull.isFuncref(), "ref.null extern is forbidden in element section's, ", elementNum, "th element's ", index, "th index");
    696701            functionIndex = Element::nullFuncIndex;
     
    728733{
    729734    uint8_t mutability;
    730     WASM_PARSER_FAIL_IF(!parseValueType(global.type), "can't get Global's value type");
     735    WASM_PARSER_FAIL_IF(!parseValueType(m_info, global.type), "can't get Global's value type");
    731736    WASM_PARSER_FAIL_IF(!parseUInt8(mutability), "can't get Global type's mutability");
    732737    WASM_PARSER_FAIL_IF(mutability != 0x0 && mutability != 0x1, "invalid Global's mutability: 0x", hex(mutability, 2, Lowercase));
  • trunk/Source/JavaScriptCore/wasm/WasmSignature.cpp

    r277920 r279265  
    7171    for (uint32_t i = 0; i < argumentCount; ++i) {
    7272        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(argumentTypes[i].kind)));
     73        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(argumentTypes[i].nullable)));
    7374        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<unsigned>::hash(argumentTypes[i].index));
    7475    }
    7576    for (uint32_t i = 0; i < returnCount; ++i) {
    7677        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(returnTypes[i].kind)));
     78        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<uint8_t>::hash(static_cast<uint8_t>(returnTypes[i].nullable)));
    7779        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<unsigned>::hash(returnTypes[i].index));
    7880    }
  • trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py

    r273962 r279265  
    213213#undef CREATE_ENUM_VALUE
    214214
     215enum class Nullable : bool {
     216  No = false,
     217  Yes = true,
     218};
     219
    215220using SignatureIndex = uintptr_t;
    216221
    217222struct Type {
    218223    TypeKind kind;
     224    Nullable nullable;
    219225    SignatureIndex index;
    220226
    221227    bool operator==(const Type& other) const
    222228    {
    223         return other.kind == kind && other.index == index;
     229        return other.kind == kind && other.nullable == nullable && other.index == index;
    224230    }
    225231
     
    229235    }
    230236
     237    bool isNullable() const
     238    {
     239        return static_cast<bool>(nullable);
     240    }
     241
    231242    #define CREATE_PREDICATE(name, ...) bool is ## name() const { return kind == TypeKind::name; }
    232243    FOR_EACH_WASM_TYPE(CREATE_PREDICATE)
     
    236247namespace Types
    237248{
    238 #define CREATE_CONSTANT(name, id, ...) constexpr Type name = Type{TypeKind::name, 0u};
     249#define CREATE_CONSTANT(name, id, ...) constexpr Type name = Type{TypeKind::name, Nullable::Yes, 0u};
    239250FOR_EACH_WASM_TYPE(CREATE_CONSTANT)
    240251#undef CREATE_CONSTANT
  • trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp

    r277928 r279265  
    105105            case TypeKind::Void:
    106106            case TypeKind::Func:
     107            case TypeKind::RefNull:
     108            case TypeKind::Ref:
    107109                RELEASE_ASSERT_NOT_REACHED(); // Handled above.
    108110            case TypeKind::TypeIdx:
     
    178180            case TypeKind::Void:
    179181            case TypeKind::Func:
     182            case TypeKind::RefNull:
     183            case TypeKind::Ref:
    180184                RELEASE_ASSERT_NOT_REACHED(); // Handled above.
    181185            case TypeKind::TypeIdx:
     
    279283        case TypeKind::Void:
    280284        case TypeKind::Func:
     285        case TypeKind::RefNull:
     286        case TypeKind::Ref:
    281287            // For the JavaScript embedding, imports with these types in their signature return are a WebAssembly.Module validation error.
    282288            RELEASE_ASSERT_NOT_REACHED();
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

    r278253 r279265  
    8686        case Wasm::TypeKind::TypeIdx:
    8787        case Wasm::TypeKind::Funcref: {
    88             if (!isWebAssemblyHostFunction(vm, arg) && !arg.isNull())
     88            bool isNullable = signature.argument(argIndex).isNullable();
     89            WebAssemblyFunction* wasmFunction = nullptr;
     90            WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
     91            if (!isWebAssemblyHostFunction(vm, arg, wasmFunction, wasmWrapperFunction) && (!isNullable || !arg.isNull()))
    8992                return JSValue::encode(throwException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Funcref must be an exported wasm function")));
     93            if (signature.argument(argIndex).kind == Wasm::TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
     94                Wasm::SignatureIndex paramIndex = signature.argument(argIndex).index;
     95                Wasm::SignatureIndex argIndex;
     96                if (wasmFunction)
     97                    argIndex = wasmFunction->signatureIndex();
     98                else
     99                    argIndex = wasmWrapperFunction->signatureIndex();
     100                if (paramIndex != argIndex)
     101                    return JSValue::encode(throwException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Argument function did not match the reference type")));
     102            }
    90103            break;
    91104        }
    92105        case Wasm::TypeKind::Externref:
     106            if (!signature.argument(argIndex).isNullable() && arg.isNull())
     107                return JSValue::encode(throwException(globalObject, scope, createJSWebAssemblyRuntimeError(globalObject, vm, "Non-null Externref cannot be null")));
    93108            break;
    94109        case Wasm::TypeKind::I64:
     
    103118        case Wasm::TypeKind::Void:
    104119        case Wasm::TypeKind::Func:
     120        case Wasm::TypeKind::RefNull:
     121        case Wasm::TypeKind::Ref:
    105122            RELEASE_ASSERT_NOT_REACHED();
    106123        }
     
    278295            break;
    279296        }
     297        case Wasm::TypeKind::TypeIdx:
    280298        case Wasm::TypeKind::Funcref: {
    281299            // Ensure we have a WASM exported function.
    282300            jit.load64(jsParam, scratchGPR);
    283301            auto isNull = jit.branchIfNull(scratchGPR);
     302            if (!type.isNullable())
     303                slowPath.append(isNull);
    284304            slowPath.append(jit.branchIfNotCell(scratchGPR));
    285305
     
    295315
    296316            isWasmFunction.link(&jit);
    297             isNull.link(&jit);
     317            if (type.kind == Wasm::TypeKind::TypeIdx) {
     318                jit.load64(jsParam, scratchGPR);
     319                jit.loadPtr(CCallHelpers::Address(scratchGPR, WebAssemblyFunctionBase::offsetOfSignatureIndex()), scratchGPR);
     320                slowPath.append(jit.branchPtr(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImmPtr(type.index)));
     321            }
     322
     323            if (type.isNullable())
     324                isNull.link(&jit);
    298325            FALLTHROUGH;
    299326        }
     
    301328            if (isStack) {
    302329                jit.load64(jsParam, scratchGPR);
     330                if (!type.isNullable())
     331                    slowPath.append(jit.branchIfNull(scratchGPR));
    303332                jit.store64(scratchGPR, calleeFrame.withOffset(wasmCallInfo.params[i].offsetFromSP()));
    304             } else
    305                 jit.load64(jsParam, wasmCallInfo.params[i].gpr());
     333            } else {
     334                auto externGPR = wasmCallInfo.params[i].gpr();
     335                jit.load64(jsParam, externGPR);
     336                if (!type.isNullable())
     337                    slowPath.append(jit.branchIfNull(externGPR));
     338            }
    306339            break;
    307340        }
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionBase.h

    r277648 r279265  
    5353    static ptrdiff_t offsetOfInstance() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_instance); }
    5454
     55    static ptrdiff_t offsetOfSignatureIndex() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_importableFunction) + WasmToWasmImportableFunction::offsetOfSignatureIndex(); }
     56
    5557    static ptrdiff_t offsetOfEntrypointLoadLocation() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_importableFunction) + WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation(); }
    5658
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp

    r278253 r279265  
    248248                        return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "must be a same mutability")));
    249249                    switch (moduleInformation.globals[import.kindIndex].type.kind) {
    250                     case Wasm::TypeKind::Funcref:
     250                    case Wasm::TypeKind::TypeIdx:
     251                    case Wasm::TypeKind::Funcref: {
     252                        bool isNullable = global.type.isNullable();
     253                        WebAssemblyFunction* wasmFunction = nullptr;
     254                        WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
    251255                        value = globalValue->global()->get(globalObject);
    252256                        RETURN_IF_EXCEPTION(scope, void());
    253                         if (!isWebAssemblyHostFunction(vm, value) && !value.isNull())
    254                             return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "must be a wasm exported function or null")));
     257                        if (!isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction) && (!isNullable || !value.isNull())) {
     258                            const char* msg = isNullable ? "must be a wasm exported function or null" : "must be a wasm exported function";
     259                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", msg)));
     260                        }
     261                        if (global.type.kind == Wasm::TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
     262                            Wasm::SignatureIndex paramIndex = global.type.index;
     263                            Wasm::SignatureIndex argIndex;
     264                            if (wasmFunction)
     265                                argIndex = wasmFunction->signatureIndex();
     266                            else
     267                                argIndex = wasmWrapperFunction->signatureIndex();
     268                            if (paramIndex != argIndex)
     269                                return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "Argument function did not match the reference type")));
     270                        }
    255271                        m_instance->instance().setGlobal(import.kindIndex, value);
    256272                        break;
     273                    }
    257274                    case Wasm::TypeKind::Externref:
    258275                        value = globalValue->global()->get(globalObject);
    259276                        RETURN_IF_EXCEPTION(scope, void());
     277                        if (!global.type.isNullable() && value.isNull())
     278                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "non-null externref cannot be null")));
    260279                        m_instance->instance().setGlobal(import.kindIndex, value);
    261280                        break;
     
    284303                    // iii. Append ToWebAssemblyValue(v) to imports.
    285304                    switch (globalType.kind) {
    286                     case Wasm::TypeKind::Funcref:
    287                         if (!isWebAssemblyHostFunction(vm, value) && !value.isNull())
    288                             return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "must be a wasm exported function or null")));
     305                    case Wasm::TypeKind::TypeIdx:
     306                    case Wasm::TypeKind::Funcref: {
     307                        bool isNullable = globalType.isNullable();
     308                        WebAssemblyFunction* wasmFunction = nullptr;
     309                        WebAssemblyWrapperFunction* wasmWrapperFunction = nullptr;
     310                        if (!isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction) && (!isNullable || !value.isNull())) {
     311                            const char* msg = isNullable ? "must be a wasm exported function or null" : "must be a wasm exported function";
     312                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", msg)));
     313                        }
     314                        if (globalType.kind == Wasm::TypeKind::TypeIdx && (wasmFunction || wasmWrapperFunction)) {
     315                            Wasm::SignatureIndex paramIndex = global.type.index;
     316                            Wasm::SignatureIndex argIndex;
     317                            if (wasmFunction)
     318                                argIndex = wasmFunction->signatureIndex();
     319                            else
     320                                argIndex = wasmWrapperFunction->signatureIndex();
     321                            if (paramIndex != argIndex)
     322                                return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "Argument function did not match the reference type")));
     323                        }
    289324                        m_instance->instance().setGlobal(import.kindIndex, value);
    290325                        break;
     326                    }
    291327                    case Wasm::TypeKind::Externref:
     328                        if (!globalType.isNullable() && value.isNull())
     329                            return exception(createJSWebAssemblyLinkError(globalObject, vm, importFailMessage(import, "imported global", "must be a non-null value")));
    292330                        m_instance->instance().setGlobal(import.kindIndex, value);
    293331                        break;
     
    491529            case Wasm::TypeKind::Externref:
    492530            case Wasm::TypeKind::Funcref:
     531            case Wasm::TypeKind::TypeIdx:
    493532            case Wasm::TypeKind::I32:
    494533            case Wasm::TypeKind::I64:
  • trunk/Source/JavaScriptCore/wasm/wasm.json

    r276896 r279265  
    1414        "funcref":   { "type": "varint7", "value":  -16, "b3type": "B3::Int64" },
    1515        "externref": { "type": "varint7", "value":  -17, "b3type": "B3::Int64" },
     16        "ref_null":  { "type": "varint7", "value":  -20, "b3type": "B3::Int64" },
     17        "ref":       { "type": "varint7", "value":  -21, "b3type": "B3::Int64" },
    1618        "func":      { "type": "varint7", "value":  -32, "b3type": "B3::Void" },
    1719        "void":      { "type": "varint7", "value":  -64, "b3type": "B3::Void" },
Note: See TracChangeset for help on using the changeset viewer.