diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
| commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
| tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/wasm | |
| parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
| download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz | |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/wasm')
| -rw-r--r-- | Source/JavaScriptCore/wasm/JSWASMModule.cpp | 68 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/JSWASMModule.h | 118 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMConstants.h | 329 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMFormat.h | 98 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMFunctionB3IRGenerator.h | 394 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMFunctionCompiler.h | 1541 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMFunctionParser.cpp | 1225 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMFunctionParser.h | 148 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h | 287 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMModuleParser.cpp | 377 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMModuleParser.h | 77 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMReader.cpp | 249 | ||||
| -rw-r--r-- | Source/JavaScriptCore/wasm/WASMReader.h | 79 |
13 files changed, 0 insertions, 4990 deletions
diff --git a/Source/JavaScriptCore/wasm/JSWASMModule.cpp b/Source/JavaScriptCore/wasm/JSWASMModule.cpp deleted file mode 100644 index c7ea4a6ed..000000000 --- a/Source/JavaScriptCore/wasm/JSWASMModule.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSWASMModule.h" - -#if ENABLE(WEBASSEMBLY) - -#include "JSArrayBuffer.h" -#include "JSCJSValueInlines.h" -#include "JSCellInlines.h" -#include "JSFunction.h" -#include "SlotVisitorInlines.h" - -namespace JSC { - -const ClassInfo JSWASMModule::s_info = { "WASMModule", &Base::s_info, 0, CREATE_METHOD_TABLE(JSWASMModule) }; - -JSWASMModule::JSWASMModule(VM& vm, Structure* structure, JSArrayBuffer* arrayBuffer) - : Base(vm, structure) -{ - if (arrayBuffer) - m_arrayBuffer.set(vm, this, arrayBuffer); -} - -void JSWASMModule::destroy(JSCell* cell) -{ - JSWASMModule* thisObject = jsCast<JSWASMModule*>(cell); - thisObject->JSWASMModule::~JSWASMModule(); -} - -void JSWASMModule::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - JSWASMModule* thisObject = jsCast<JSWASMModule*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - Base::visitChildren(thisObject, visitor); - visitor.append(&thisObject->m_arrayBuffer); - for (auto function : thisObject->m_functions) - visitor.append(&function); - for (auto importedFunction : thisObject->m_importedFunctions) - visitor.append(&importedFunction); -} - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) diff --git a/Source/JavaScriptCore/wasm/JSWASMModule.h b/Source/JavaScriptCore/wasm/JSWASMModule.h deleted file mode 100644 index 2d16791cc..000000000 --- a/Source/JavaScriptCore/wasm/JSWASMModule.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSWASMModule_h -#define JSWASMModule_h - -#if ENABLE(WEBASSEMBLY) - -#include "JSDestructibleObject.h" -#include "WASMFormat.h" - -namespace JSC { - -class JSWASMModule : public JSDestructibleObject { -public: - typedef JSDestructibleObject Base; - - union GlobalVariable { - GlobalVariable(int32_t value) - : intValue(value) - { - } - GlobalVariable(float value) - : floatValue(value) - { - } - GlobalVariable(double value) - : doubleValue(value) - { - } - - int32_t intValue; - float floatValue; - double doubleValue; - }; - - static JSWASMModule* create(VM& vm, Structure* structure, JSArrayBuffer* arrayBuffer) - { - JSWASMModule* module = new (NotNull, allocateCell<JSWASMModule>(vm.heap)) JSWASMModule(vm, structure, arrayBuffer); - module->finishCreation(vm); - return module; - } - - DECLARE_INFO; - - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject) - { - return Structure::create(vm, globalObject, jsNull(), TypeInfo(ObjectType, StructureFlags), info()); - } - - static void destroy(JSCell*); - static void visitChildren(JSCell*, SlotVisitor&); - - Vector<uint32_t>& i32Constants() { return m_i32Constants; } - Vector<float>& f32Constants() { return m_f32Constants; } - Vector<double>& f64Constants() { return m_f64Constants; } - Vector<WASMSignature>& signatures() { return m_signatures; } - Vector<WASMFunctionImport>& functionImports() { return m_functionImports; } - Vector<WASMFunctionImportSignature>& functionImportSignatures() { return m_functionImportSignatures; } - Vector<WASMType>& globalVariableTypes() { return m_globalVariableTypes; } - Vector<WASMFunctionDeclaration>& functionDeclarations() { return m_functionDeclarations; } - Vector<WASMFunctionPointerTable>& functionPointerTables() { return m_functionPointerTables; } - - const JSArrayBuffer* arrayBuffer() const { return m_arrayBuffer.get(); } - Vector<WriteBarrier<JSFunction>>& functions() { return m_functions; } - Vector<unsigned>& functionStartOffsetsInSource() { return m_functionStartOffsetsInSource; } - Vector<unsigned>& functionStackHeights() { return m_functionStackHeights; } - Vector<GlobalVariable>& globalVariables() { return m_globalVariables; } - Vector<WriteBarrier<JSFunction>>& importedFunctions() { return m_importedFunctions; } - -private: - JSWASMModule(VM&, Structure*, JSArrayBuffer*); - - Vector<uint32_t> m_i32Constants; - Vector<float> m_f32Constants; - Vector<double> m_f64Constants; - Vector<WASMSignature> m_signatures; - Vector<WASMFunctionImport> m_functionImports; - Vector<WASMFunctionImportSignature> m_functionImportSignatures; - Vector<WASMType> m_globalVariableTypes; - Vector<WASMFunctionDeclaration> m_functionDeclarations; - Vector<WASMFunctionPointerTable> m_functionPointerTables; - - WriteBarrier<JSArrayBuffer> m_arrayBuffer; - Vector<WriteBarrier<JSFunction>> m_functions; - Vector<unsigned> m_functionStartOffsetsInSource; - Vector<unsigned> m_functionStackHeights; - Vector<GlobalVariable> m_globalVariables; - Vector<WriteBarrier<JSFunction>> m_importedFunctions; -}; - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) - -#endif // JSWASMModule_h diff --git a/Source/JavaScriptCore/wasm/WASMConstants.h b/Source/JavaScriptCore/wasm/WASMConstants.h deleted file mode 100644 index 4e3bd443f..000000000 --- a/Source/JavaScriptCore/wasm/WASMConstants.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ========================================================================= - * - * Copyright (c) 2015 by the repository authors of - * WebAssembly/polyfill-prototype-1. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WASMConstants_h -#define WASMConstants_h - -#if ENABLE(WEBASSEMBLY) - -namespace JSC { - -static const uint32_t wasmMagicNumber = 0x6d736177; - -enum class WASMOpKind { - Statement, - Expression -}; - -enum class WASMOpStatement : uint8_t { - SetLocal, - SetGlobal, - I32Store8, - I32StoreWithOffset8, - I32Store16, - I32StoreWithOffset16, - I32Store32, - I32StoreWithOffset32, - F32Store, - F32StoreWithOffset, - F64Store, - F64StoreWithOffset, - CallInternal, - CallIndirect, - CallImport, - Return, - Block, - If, - IfElse, - While, - Do, - Label, - Break, - BreakLabel, - Continue, - ContinueLabel, - Switch, - NumberOfWASMOpStatements -}; - -enum class WASMOpStatementWithImmediate : uint8_t { - SetLocal, - SetGlobal, - NumberOfWASMOpStatementWithImmediates -}; - -enum class WASMOpExpressionI32 : uint8_t { - ConstantPoolIndex, - Immediate, - GetLocal, - GetGlobal, - SetLocal, - SetGlobal, - SLoad8, - SLoadWithOffset8, - ULoad8, - ULoadWithOffset8, - SLoad16, - SLoadWithOffset16, - ULoad16, - ULoadWithOffset16, - Load32, - LoadWithOffset32, - Store8, - StoreWithOffset8, - Store16, - StoreWithOffset16, - Store32, - StoreWithOffset32, - CallInternal, - CallIndirect, - CallImport, - Conditional, - Comma, - FromF32, - FromF64, - Negate, - Add, - Sub, - Mul, - SDiv, - UDiv, - SMod, - UMod, - BitNot, - BitOr, - BitAnd, - BitXor, - LeftShift, - ArithmeticRightShift, - LogicalRightShift, - CountLeadingZeros, - LogicalNot, - EqualI32, - EqualF32, - EqualF64, - NotEqualI32, - NotEqualF32, - NotEqualF64, - SLessThanI32, - ULessThanI32, - LessThanF32, - LessThanF64, - SLessThanOrEqualI32, - ULessThanOrEqualI32, - LessThanOrEqualF32, - LessThanOrEqualF64, - SGreaterThanI32, - UGreaterThanI32, - GreaterThanF32, - GreaterThanF64, - SGreaterThanOrEqualI32, - UGreaterThanOrEqualI32, - GreaterThanOrEqualF32, - GreaterThanOrEqualF64, - SMin, - UMin, - SMax, - UMax, - Abs, - NumberOfWASMOpExpressionI32s -}; - -enum class WASMOpExpressionI32WithImmediate : uint8_t { - ConstantPoolIndex, - Immediate, - GetLocal, - NumberOfWASMOpExpressionI32WithImmediates -}; - -enum class WASMOpExpressionF32 : uint8_t { - ConstantPoolIndex, - Immediate, - GetLocal, - GetGlobal, - SetLocal, - SetGlobal, - Load, - LoadWithOffset, - Store, - StoreWithOffset, - CallInternal, - CallIndirect, - Conditional, - Comma, - FromS32, - FromU32, - FromF64, - Negate, - Add, - Sub, - Mul, - Div, - Abs, - Ceil, - Floor, - Sqrt, - NumberOfWASMOpExpressionF32s -}; - -enum class WASMOpExpressionF32WithImmediate : uint8_t { - ConstantPoolIndex, - GetLocal, - NumberOfWASMOpExpressionF32WithImmediates -}; - -enum class WASMOpExpressionF64 : uint8_t { - ConstantPoolIndex, - Immediate, - GetLocal, - GetGlobal, - SetLocal, - SetGlobal, - Load, - LoadWithOffset, - Store, - StoreWithOffset, - CallInternal, - CallIndirect, - CallImport, - Conditional, - Comma, - FromS32, - FromU32, - FromF32, - Negate, - Add, - Sub, - Mul, - Div, - Mod, - Min, - Max, - Abs, - Ceil, - Floor, - Sqrt, - Cos, - Sin, - Tan, - ACos, - ASin, - ATan, - ATan2, - Exp, - Ln, - Pow, - NumberOfWASMOpExpressionF64s -}; - -enum class WASMOpExpressionF64WithImmediate : uint8_t { - ConstantPoolIndex, - GetLocal, - NumberOfWASMOpExpressionF64WithImmediates -}; - -enum class WASMOpExpressionVoid : uint8_t { - CallInternal, - CallIndirect, - CallImport, - NumberOfWASMOpExpressionVoids -}; - -enum class WASMVariableTypes : uint8_t { - I32 = 1 << 0, - F32 = 1 << 1, - F64 = 1 << 2, - NumberOfVariableTypes = 8 -}; - -enum class WASMVariableTypesWithImmediate : uint8_t { - I32, - NumberOfVariableTypesWithImmediates -}; - -enum class WASMSwitchCase : uint8_t { - CaseWithNoStatements, - CaseWithStatement, - CaseWithBlockStatement, - DefaultWithNoStatements, - DefaultWithStatement, - DefaultWithBlockStatement, - NumberOfSwitchCases -}; - -enum class WASMExportFormat : uint8_t { - Default, - Record, - NumberOfExportFormats -}; - -enum class WASMTypeConversion { - ConvertSigned, - ConvertUnsigned, - Promote, - Demote, -}; - -enum class WASMMemoryType { - I8, - I16, - I32, - F32, - F64 -}; - -enum class MemoryAccessOffsetMode { NoOffset, WithOffset }; -enum class MemoryAccessConversion { NoConversion, SignExtend, ZeroExtend }; - -static const uint8_t hasImmediateInOpFlag = 0x80; - -static const unsigned opWithImmediateBits = 2; -static const uint32_t opWithImmediateLimit = 1 << opWithImmediateBits; - -static const unsigned immediateBits = 5; -static const uint32_t immediateLimit = 1 << immediateBits; - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) - -#endif // WASMConstants_h diff --git a/Source/JavaScriptCore/wasm/WASMFormat.h b/Source/JavaScriptCore/wasm/WASMFormat.h deleted file mode 100644 index b36341056..000000000 --- a/Source/JavaScriptCore/wasm/WASMFormat.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ========================================================================= - * - * Copyright (c) 2015 by the repository authors of - * WebAssembly/polyfill-prototype-1. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WASMFormat_h -#define WASMFormat_h - -#if ENABLE(WEBASSEMBLY) - -#include <wtf/Vector.h> -#include <wtf/text/WTFString.h> - -namespace JSC { - -class JSFunction; - -enum class WASMType : uint8_t { - I32, - F32, - F64, - NumberOfTypes -}; - -enum class WASMExpressionType : uint8_t { - I32, - F32, - F64, - Void, - NumberOfExpressionTypes -}; - -struct WASMSignature { - WASMExpressionType returnType; - Vector<WASMType> arguments; -}; - -struct WASMFunctionImport { - String functionName; -}; - -struct WASMFunctionImportSignature { - uint32_t signatureIndex; - uint32_t functionImportIndex; -}; - -struct WASMFunctionDeclaration { - uint32_t signatureIndex; -}; - -struct WASMFunctionPointerTable { - uint32_t signatureIndex; - Vector<uint32_t> functionIndices; - Vector<JSFunction*> functions; -}; - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) - -#endif // WASMFormat_h diff --git a/Source/JavaScriptCore/wasm/WASMFunctionB3IRGenerator.h b/Source/JavaScriptCore/wasm/WASMFunctionB3IRGenerator.h deleted file mode 100644 index 7813a23da..000000000 --- a/Source/JavaScriptCore/wasm/WASMFunctionB3IRGenerator.h +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WASMFunctionB3IRGenerator_h -#define WASMFunctionB3IRGenerator_h - -#if ENABLE(WEBASSEMBLY) && ENABLE(FTL_JIT) - -#include "FTLAbbreviatedTypes.h" - -#define UNUSED 0 - -namespace JSC { - -using FTL::LBasicBlock; -using FTL::LValue; - -class WASMFunctionB3IRGenerator { -public: - typedef LValue Expression; - typedef int Statement; - typedef Vector<LValue> ExpressionList; - struct MemoryAddress { - MemoryAddress(void*) { } - MemoryAddress(LValue index, uint32_t offset) - : index(index) - , offset(offset) - { - } - LValue index; - uint32_t offset; - }; - typedef LBasicBlock JumpTarget; - enum class JumpCondition { Zero, NonZero }; - - void startFunction(const Vector<WASMType>& arguments, uint32_t numberOfI32LocalVariables, uint32_t numberOfF32LocalVariables, uint32_t numberOfF64LocalVariables) - { - // FIXME: Implement this method. - UNUSED_PARAM(arguments); - UNUSED_PARAM(numberOfI32LocalVariables); - UNUSED_PARAM(numberOfF32LocalVariables); - UNUSED_PARAM(numberOfF64LocalVariables); - } - - void endFunction() - { - // FIXME: Implement this method. - } - - LValue buildSetLocal(WASMOpKind opKind, uint32_t localIndex, LValue value, WASMType type) - { - // FIXME: Implement this method. - UNUSED_PARAM(opKind); - UNUSED_PARAM(localIndex); - UNUSED_PARAM(value); - UNUSED_PARAM(type); - return UNUSED; - } - - LValue buildSetGlobal(WASMOpKind opKind, uint32_t globalIndex, LValue value, WASMType type) - { - // FIXME: Implement this method. - UNUSED_PARAM(opKind); - UNUSED_PARAM(globalIndex); - UNUSED_PARAM(value); - UNUSED_PARAM(type); - return UNUSED; - } - - void buildReturn(LValue value, WASMExpressionType returnType) - { - // FIXME: Implement this method. - UNUSED_PARAM(value); - UNUSED_PARAM(returnType); - } - - LValue buildImmediateI32(uint32_t immediate) - { - // FIXME: Implement this method. - UNUSED_PARAM(immediate); - return UNUSED; - } - - LValue buildImmediateF32(float immediate) - { - // FIXME: Implement this method. - UNUSED_PARAM(immediate); - return UNUSED; - } - - LValue buildImmediateF64(double immediate) - { - // FIXME: Implement this method. - UNUSED_PARAM(immediate); - return UNUSED; - } - - LValue buildGetLocal(uint32_t localIndex, WASMType type) - { - // FIXME: Implement this method. - UNUSED_PARAM(localIndex); - UNUSED_PARAM(type); - return UNUSED; - } - - LValue buildGetGlobal(uint32_t globalIndex, WASMType type) - { - // FIXME: Implement this method. - UNUSED_PARAM(globalIndex); - UNUSED_PARAM(type); - return UNUSED; - } - - LValue buildConvertType(LValue value, WASMExpressionType fromType, WASMExpressionType toType, WASMTypeConversion conversion) - { - // FIXME: Implement this method. - UNUSED_PARAM(value); - UNUSED_PARAM(fromType); - UNUSED_PARAM(toType); - UNUSED_PARAM(conversion); - return UNUSED; - } - - LValue buildLoad(const MemoryAddress& memoryAddress, WASMExpressionType expressionType, WASMMemoryType memoryType, MemoryAccessConversion conversion) - { - // FIXME: Implement this method. - UNUSED_PARAM(memoryAddress); - UNUSED_PARAM(expressionType); - UNUSED_PARAM(memoryType); - UNUSED_PARAM(conversion); - return UNUSED; - } - - LValue buildStore(WASMOpKind opKind, const MemoryAddress& memoryAddress, WASMExpressionType expressionType, WASMMemoryType memoryType, LValue value) - { - // FIXME: Implement this method. - UNUSED_PARAM(opKind); - UNUSED_PARAM(memoryAddress); - UNUSED_PARAM(expressionType); - UNUSED_PARAM(memoryType); - UNUSED_PARAM(value); - return UNUSED; - } - - LValue buildUnaryI32(LValue value, WASMOpExpressionI32 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(value); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildUnaryF32(LValue value, WASMOpExpressionF32 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(value); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildUnaryF64(LValue value, WASMOpExpressionF64 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(value); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildBinaryI32(LValue left, LValue right, WASMOpExpressionI32 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(left); - UNUSED_PARAM(right); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildBinaryF32(LValue left, LValue right, WASMOpExpressionF32 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(left); - UNUSED_PARAM(right); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildBinaryF64(LValue left, LValue right, WASMOpExpressionF64 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(left); - UNUSED_PARAM(right); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildRelationalI32(LValue left, LValue right, WASMOpExpressionI32 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(left); - UNUSED_PARAM(right); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildRelationalF32(LValue left, LValue right, WASMOpExpressionI32 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(left); - UNUSED_PARAM(right); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildRelationalF64(LValue left, LValue right, WASMOpExpressionI32 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(left); - UNUSED_PARAM(right); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildMinOrMaxI32(LValue left, LValue right, WASMOpExpressionI32 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(left); - UNUSED_PARAM(right); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildMinOrMaxF64(LValue left, LValue right, WASMOpExpressionF64 op) - { - // FIXME: Implement this method. - UNUSED_PARAM(left); - UNUSED_PARAM(right); - UNUSED_PARAM(op); - return UNUSED; - } - - LValue buildCallInternal(uint32_t functionIndex, const Vector<LValue>& argumentList, const WASMSignature& signature, WASMExpressionType returnType) - { - // FIXME: Implement this method. - UNUSED_PARAM(functionIndex); - UNUSED_PARAM(argumentList); - UNUSED_PARAM(signature); - UNUSED_PARAM(returnType); - return UNUSED; - } - - LValue buildCallIndirect(uint32_t functionPointerTableIndex, LValue index, const Vector<LValue>& argumentList, const WASMSignature& signature, WASMExpressionType returnType) - { - // FIXME: Implement this method. - UNUSED_PARAM(functionPointerTableIndex); - UNUSED_PARAM(index); - UNUSED_PARAM(argumentList); - UNUSED_PARAM(signature); - UNUSED_PARAM(returnType); - return UNUSED; - } - - LValue buildCallImport(uint32_t functionImportIndex, const Vector<LValue>& argumentList, const WASMSignature& signature, WASMExpressionType returnType) - { - // FIXME: Implement this method. - UNUSED_PARAM(functionImportIndex); - UNUSED_PARAM(argumentList); - UNUSED_PARAM(signature); - UNUSED_PARAM(returnType); - return UNUSED; - } - - void appendExpressionList(Vector<LValue>& expressionList, LValue value) - { - // FIXME: Implement this method. - UNUSED_PARAM(expressionList); - UNUSED_PARAM(value); - } - - void discard(LValue) - { - } - - void linkTarget(LBasicBlock target) - { - // FIXME: Implement this method. - UNUSED_PARAM(target); - } - - void jumpToTarget(LBasicBlock target) - { - // FIXME: Implement this method. - UNUSED_PARAM(target); - } - - void jumpToTargetIf(JumpCondition, LValue value, LBasicBlock target) - { - // FIXME: Implement this method. - UNUSED_PARAM(value); - UNUSED_PARAM(target); - } - - void startLoop() - { - // FIXME: Implement this method. - } - - void endLoop() - { - // FIXME: Implement this method. - } - - void startSwitch() - { - // FIXME: Implement this method. - } - - void endSwitch() - { - // FIXME: Implement this method. - } - - void startLabel() - { - // FIXME: Implement this method. - } - - void endLabel() - { - // FIXME: Implement this method. - } - - LBasicBlock breakTarget() - { - // FIXME: Implement this method. - return UNUSED; - } - - LBasicBlock continueTarget() - { - // FIXME: Implement this method. - return UNUSED; - } - - LBasicBlock breakLabelTarget(uint32_t labelIndex) - { - // FIXME: Implement this method. - UNUSED_PARAM(labelIndex); - return UNUSED; - } - - LBasicBlock continueLabelTarget(uint32_t labelIndex) - { - // FIXME: Implement this method. - UNUSED_PARAM(labelIndex); - return UNUSED; - } - - void buildSwitch(LValue value, const Vector<int64_t>& cases, const Vector<LBasicBlock>& targets, LBasicBlock defaultTarget) - { - // FIXME: Implement this method. - UNUSED_PARAM(value); - UNUSED_PARAM(cases); - UNUSED_PARAM(targets); - UNUSED_PARAM(defaultTarget); - } -}; - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) - -#endif // WASMFunctionB3IRGenerator_h diff --git a/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h b/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h deleted file mode 100644 index de439ba07..000000000 --- a/Source/JavaScriptCore/wasm/WASMFunctionCompiler.h +++ /dev/null @@ -1,1541 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WASMFunctionCompiler_h -#define WASMFunctionCompiler_h - -#if ENABLE(WEBASSEMBLY) - -#include "BinarySwitch.h" -#include "CCallHelpers.h" -#include "JIT.h" -#include "JITOperations.h" -#include "JSArrayBuffer.h" -#include "LinkBuffer.h" -#include "MaxFrameExtentForSlowPathCall.h" - -#define UNUSED 0 - -namespace JSC { - -static int32_t JIT_OPERATION operationConvertJSValueToInt32(ExecState* exec, EncodedJSValue value) -{ - return JSValue::decode(value).toInt32(exec); -} - -static double JIT_OPERATION operationConvertJSValueToDouble(ExecState* exec, EncodedJSValue value) -{ - return JSValue::decode(value).toNumber(exec); -} - -#if !CPU(X86) && !CPU(X86_64) -static int32_t JIT_OPERATION operationDiv(int32_t left, int32_t right) -{ - return left / right; -} - -static int32_t JIT_OPERATION operationMod(int32_t left, int32_t right) -{ - return left % right; -} - -static uint32_t JIT_OPERATION operationUnsignedDiv(uint32_t left, uint32_t right) -{ - return left / right; -} - -static uint32_t JIT_OPERATION operationUnsignedMod(uint32_t left, uint32_t right) -{ - return left % right; -} -#endif - -#if !USE(JSVALUE64) -static double JIT_OPERATION operationConvertUnsignedInt32ToDouble(uint32_t value) -{ - return static_cast<double>(value); -} -#endif - -static size_t sizeOfMemoryType(WASMMemoryType memoryType) -{ - switch (memoryType) { - case WASMMemoryType::I8: - return 1; - case WASMMemoryType::I16: - return 2; - case WASMMemoryType::I32: - case WASMMemoryType::F32: - return 4; - case WASMMemoryType::F64: - return 8; - default: - ASSERT_NOT_REACHED(); - } - RELEASE_ASSERT_NOT_REACHED(); - return 0; -} - -class WASMFunctionCompiler : private CCallHelpers { -public: - typedef int Expression; - typedef int Statement; - typedef int ExpressionList; - struct MemoryAddress { - MemoryAddress(void*) { } - MemoryAddress(int, uint32_t offset) - : offset(offset) - { - } - uint32_t offset; - }; - struct JumpTarget { - Label label; - JumpList jumpList; - }; - enum class JumpCondition { Zero, NonZero }; - - WASMFunctionCompiler(VM& vm, CodeBlock* codeBlock, JSWASMModule* module, unsigned stackHeight) - : CCallHelpers(&vm, codeBlock) - , m_module(module) - , m_stackHeight(stackHeight) - { - } - - void startFunction(const Vector<WASMType>& arguments, uint32_t numberOfI32LocalVariables, uint32_t numberOfF32LocalVariables, uint32_t numberOfF64LocalVariables) - { - m_calleeSaveSpace = WTF::roundUpToMultipleOf(sizeof(StackSlot), RegisterSet::webAssemblyCalleeSaveRegisters().numberOfSetRegisters() * sizeof(void*)); - m_codeBlock->setCalleeSaveRegisters(RegisterSet::webAssemblyCalleeSaveRegisters()); - - emitFunctionPrologue(); - emitPutToCallFrameHeader(m_codeBlock, JSStack::CodeBlock); - - m_beginLabel = label(); - - addPtr(TrustedImm32(-m_calleeSaveSpace - WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, GPRInfo::regT1); - m_stackOverflow = branchPtr(Above, AbsoluteAddress(m_vm->addressOfStackLimit()), GPRInfo::regT1); - - move(GPRInfo::regT1, stackPointerRegister); - checkStackPointerAlignment(); - - emitSaveCalleeSaves(); - emitMaterializeTagCheckRegisters(); - - m_numberOfLocals = arguments.size() + numberOfI32LocalVariables + numberOfF32LocalVariables + numberOfF64LocalVariables; - - unsigned localIndex = 0; - for (size_t i = 0; i < arguments.size(); ++i) { - // FIXME: No need to do type conversion if the caller is a WebAssembly function. - // https://bugs.webkit.org/show_bug.cgi?id=149310 - Address address(GPRInfo::callFrameRegister, CallFrame::argumentOffset(i) * sizeof(Register)); -#if USE(JSVALUE64) - JSValueRegs valueRegs(GPRInfo::regT0); -#else - JSValueRegs valueRegs(GPRInfo::regT1, GPRInfo::regT0); -#endif - loadValue(address, valueRegs); - switch (arguments[i]) { - case WASMType::I32: - convertValueToInt32(valueRegs, GPRInfo::regT0); - store32(GPRInfo::regT0, localAddress(localIndex++)); - break; - case WASMType::F32: - case WASMType::F64: -#if USE(JSVALUE64) - convertValueToDouble(valueRegs, FPRInfo::fpRegT0, GPRInfo::regT1); -#else - convertValueToDouble(valueRegs, FPRInfo::fpRegT0, GPRInfo::regT2, FPRInfo::fpRegT1); -#endif - if (arguments[i] == WASMType::F32) - convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, localAddress(localIndex++)); - break; - default: - ASSERT_NOT_REACHED(); - } - } - for (uint32_t i = 0; i < numberOfI32LocalVariables; ++i) - store32(TrustedImm32(0), localAddress(localIndex++)); - for (uint32_t i = 0; i < numberOfF32LocalVariables; ++i) - store32(TrustedImm32(0), localAddress(localIndex++)); - for (uint32_t i = 0; i < numberOfF64LocalVariables; ++i) { -#if USE(JSVALUE64) - store64(TrustedImm64(0), localAddress(localIndex++)); -#else - store32(TrustedImm32(0), localAddress(localIndex)); - store32(TrustedImm32(0), localAddress(localIndex).withOffset(4)); - localIndex++; -#endif - } - - m_codeBlock->setNumParameters(1 + arguments.size()); - } - - void endFunction() - { - ASSERT(!m_tempStackTop); - - // FIXME: Remove these if the last statement is a return statement. -#if USE(JSVALUE64) - JSValueRegs returnValueRegs(GPRInfo::returnValueGPR); -#else - JSValueRegs returnValueRegs(GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR); -#endif - moveTrustedValue(jsUndefined(), returnValueRegs); - emitRestoreCalleeSaves(); - emitFunctionEpilogue(); - ret(); - - m_stackOverflow.link(this); - if (maxFrameExtentForSlowPathCall) - addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister); - setupArgumentsWithExecState(TrustedImmPtr(m_codeBlock)); - appendCallWithExceptionCheck(operationThrowStackOverflowError); - - // FIXME: Implement arity check. - Label arityCheck = label(); - emitFunctionPrologue(); - emitPutToCallFrameHeader(m_codeBlock, JSStack::CodeBlock); - jump(m_beginLabel); - - if (!m_divideErrorJumpList.empty()) { - m_divideErrorJumpList.link(this); - - setupArgumentsExecState(); - appendCallWithExceptionCheck(operationThrowDivideError); - } - - if (!m_outOfBoundsErrorJumpList.empty()) { - m_outOfBoundsErrorJumpList.link(this); - - setupArgumentsExecState(); - appendCallWithExceptionCheck(operationThrowOutOfBoundsAccessError); - } - - if (!m_exceptionChecks.empty()) { - m_exceptionChecks.link(this); - - copyCalleeSavesToVMCalleeSavesBuffer(); - - // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*). - move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0); - move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1); - -#if CPU(X86) - // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer! - poke(GPRInfo::argumentGPR0); - poke(GPRInfo::argumentGPR1, 1); -#endif - m_calls.append(std::make_pair(call(), FunctionPtr(lookupExceptionHandlerFromCallerFrame).value())); - jumpToExceptionHandler(); - } - - LinkBuffer patchBuffer(*m_vm, *this, m_codeBlock, JITCompilationMustSucceed); - - for (const auto& iterator : m_calls) - patchBuffer.link(iterator.first, FunctionPtr(iterator.second)); - - for (size_t i = 0; i < m_callCompilationInfo.size(); ++i) { - CallCompilationInfo& compilationInfo = m_callCompilationInfo[i]; - CallLinkInfo& info = *compilationInfo.callLinkInfo; - info.setCallLocations(patchBuffer.locationOfNearCall(compilationInfo.callReturnLocation), - patchBuffer.locationOf(compilationInfo.hotPathBegin), - patchBuffer.locationOfNearCall(compilationInfo.hotPathOther)); - } - - MacroAssemblerCodePtr withArityCheck = patchBuffer.locationOf(arityCheck); - CodeRef result = FINALIZE_CODE(patchBuffer, ("Baseline JIT code for WebAssembly")); - m_codeBlock->setJITCode(adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT))); - m_codeBlock->capabilityLevel(); - } - - int buildSetLocal(WASMOpKind opKind, uint32_t localIndex, int, WASMType type) - { - switch (type) { - case WASMType::I32: - case WASMType::F32: - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT0); - store32(GPRInfo::regT0, localAddress(localIndex)); - break; - case WASMType::F64: - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, localAddress(localIndex)); - break; - default: - ASSERT_NOT_REACHED(); - } - if (opKind == WASMOpKind::Statement) - m_tempStackTop--; - return UNUSED; - } - - int buildSetGlobal(WASMOpKind opKind, uint32_t globalIndex, int, WASMType type) - { - move(TrustedImmPtr(&m_module->globalVariables()[globalIndex]), GPRInfo::regT0); - switch (type) { - case WASMType::I32: - case WASMType::F32: - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT1); - store32(GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMType::F64: - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, GPRInfo::regT0); - break; - default: - ASSERT_NOT_REACHED(); - } - if (opKind == WASMOpKind::Statement) - m_tempStackTop--; - return UNUSED; - } - - void buildReturn(int, WASMExpressionType returnType) - { -#if USE(JSVALUE64) - JSValueRegs returnValueRegs(GPRInfo::returnValueGPR); -#else - JSValueRegs returnValueRegs(GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR); -#endif - switch (returnType) { - case WASMExpressionType::I32: - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::returnValueGPR); -#if USE(JSVALUE64) - or64(GPRInfo::tagTypeNumberRegister, GPRInfo::returnValueGPR); -#else - move(TrustedImm32(JSValue::Int32Tag), GPRInfo::returnValueGPR2); -#endif - m_tempStackTop--; - break; - case WASMExpressionType::F32: - case WASMExpressionType::F64: - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT0); - if (returnType == WASMExpressionType::F32) - convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - convertDoubleToValue(FPRInfo::fpRegT0, returnValueRegs); - m_tempStackTop--; - break; - case WASMExpressionType::Void: - moveTrustedValue(jsUndefined(), returnValueRegs); - break; - default: - ASSERT_NOT_REACHED(); - } - emitRestoreCalleeSaves(); - emitFunctionEpilogue(); - ret(); - } - - int buildImmediateI32(uint32_t immediate) - { - store32(Imm32(immediate), temporaryAddress(m_tempStackTop++)); - return UNUSED; - } - - int buildImmediateF32(float immediate) - { - store32(Imm32(bitwise_cast<int32_t>(immediate)), temporaryAddress(m_tempStackTop++)); - return UNUSED; - } - - int buildImmediateF64(double immediate) - { -#if USE(JSVALUE64) - store64(Imm64(bitwise_cast<int64_t>(immediate)), temporaryAddress(m_tempStackTop++)); -#else - union { - double doubleValue; - int32_t int32Values[2]; - } u = { immediate }; - m_tempStackTop++; - store32(Imm32(u.int32Values[0]), temporaryAddress(m_tempStackTop - 1)); - store32(Imm32(u.int32Values[1]), temporaryAddress(m_tempStackTop - 1).withOffset(4)); -#endif - return UNUSED; - } - - int buildGetLocal(uint32_t localIndex, WASMType type) - { - switch (type) { - case WASMType::I32: - case WASMType::F32: - load32(localAddress(localIndex), GPRInfo::regT0); - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop++)); - break; - case WASMType::F64: - loadDouble(localAddress(localIndex), FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop++)); - break; - default: - ASSERT_NOT_REACHED(); - } - return UNUSED; - } - - int buildGetGlobal(uint32_t globalIndex, WASMType type) - { - move(TrustedImmPtr(&m_module->globalVariables()[globalIndex]), GPRInfo::regT0); - switch (type) { - case WASMType::I32: - case WASMType::F32: - load32(GPRInfo::regT0, GPRInfo::regT0); - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop++)); - break; - case WASMType::F64: - loadDouble(GPRInfo::regT0, FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop++)); - break; - default: - ASSERT_NOT_REACHED(); - } - return UNUSED; - } - - int buildConvertType(int, WASMExpressionType fromType, WASMExpressionType toType, WASMTypeConversion conversion) - { - switch (fromType) { - case WASMExpressionType::I32: - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT0); - ASSERT(toType == WASMExpressionType::F32 || toType == WASMExpressionType::F64); - if (conversion == WASMTypeConversion::ConvertSigned) - convertInt32ToDouble(GPRInfo::regT0, FPRInfo::fpRegT0); - else { - ASSERT(conversion == WASMTypeConversion::ConvertUnsigned); -#if USE(JSVALUE64) - convertInt64ToDouble(GPRInfo::regT0, FPRInfo::fpRegT0); -#else - callOperation(operationConvertUnsignedInt32ToDouble, GPRInfo::regT0, FPRInfo::fpRegT0); -#endif - } - if (toType == WASMExpressionType::F32) - convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); - break; - case WASMExpressionType::F32: - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT0); - switch (toType) { - case WASMExpressionType::I32: - ASSERT(conversion == WASMTypeConversion::ConvertSigned); - convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - truncateDoubleToInt32(FPRInfo::fpRegT0, GPRInfo::regT0); - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1)); - break; - case WASMExpressionType::F64: - ASSERT(conversion == WASMTypeConversion::Promote); - convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); - break; - default: - ASSERT_NOT_REACHED(); - } - break; - case WASMExpressionType::F64: - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT0); - switch (toType) { - case WASMExpressionType::I32: - ASSERT(conversion == WASMTypeConversion::ConvertSigned); - truncateDoubleToInt32(FPRInfo::fpRegT0, GPRInfo::regT0); - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1)); - break; - case WASMExpressionType::F32: - ASSERT(conversion == WASMTypeConversion::Demote); - convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); - break; - default: - ASSERT_NOT_REACHED(); - } - break; - default: - ASSERT_NOT_REACHED(); - } - return UNUSED; - } - - int buildLoad(const MemoryAddress& memoryAddress, WASMExpressionType expressionType, WASMMemoryType memoryType, MemoryAccessConversion conversion) - { - const ArrayBuffer* arrayBuffer = m_module->arrayBuffer()->impl(); - move(TrustedImmPtr(arrayBuffer->data()), GPRInfo::regT0); - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT1); - if (memoryAddress.offset) - add32(TrustedImm32(memoryAddress.offset), GPRInfo::regT1, GPRInfo::regT1); - and32(TrustedImm32(~(sizeOfMemoryType(memoryType) - 1)), GPRInfo::regT1); - - ASSERT(arrayBuffer->byteLength() < (unsigned)(1 << 31)); - if (arrayBuffer->byteLength() >= sizeOfMemoryType(memoryType)) - m_outOfBoundsErrorJumpList.append(branch32(Above, GPRInfo::regT1, TrustedImm32(arrayBuffer->byteLength() - sizeOfMemoryType(memoryType)))); - else - m_outOfBoundsErrorJumpList.append(jump()); - - BaseIndex address = BaseIndex(GPRInfo::regT0, GPRInfo::regT1, TimesOne); - - switch (expressionType) { - case WASMExpressionType::I32: - switch (memoryType) { - case WASMMemoryType::I8: - if (conversion == MemoryAccessConversion::SignExtend) - load8SignedExtendTo32(address, GPRInfo::regT0); - else { - ASSERT(conversion == MemoryAccessConversion::ZeroExtend); - load8(address, GPRInfo::regT0); - } - break; - case WASMMemoryType::I16: - if (conversion == MemoryAccessConversion::SignExtend) - load16SignedExtendTo32(address, GPRInfo::regT0); - else { - ASSERT(conversion == MemoryAccessConversion::ZeroExtend); - load16(address, GPRInfo::regT0); - } - break; - case WASMMemoryType::I32: - load32(address, GPRInfo::regT0); - break; - default: - ASSERT_NOT_REACHED(); - } - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1)); - break; - case WASMExpressionType::F32: - ASSERT(memoryType == WASMMemoryType::F32 && conversion == MemoryAccessConversion::NoConversion); - load32(address, GPRInfo::regT0); - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1)); - break; - case WASMExpressionType::F64: - ASSERT(memoryType == WASMMemoryType::F64 && conversion == MemoryAccessConversion::NoConversion); - loadDouble(address, FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); - break; - default: - ASSERT_NOT_REACHED(); - } - return UNUSED; - } - - int buildStore(WASMOpKind opKind, const MemoryAddress& memoryAddress, WASMExpressionType expressionType, WASMMemoryType memoryType, int) - { - const ArrayBuffer* arrayBuffer = m_module->arrayBuffer()->impl(); - move(TrustedImmPtr(arrayBuffer->data()), GPRInfo::regT0); - load32(temporaryAddress(m_tempStackTop - 2), GPRInfo::regT1); - if (memoryAddress.offset) - add32(TrustedImm32(memoryAddress.offset), GPRInfo::regT1, GPRInfo::regT1); - and32(TrustedImm32(~(sizeOfMemoryType(memoryType) - 1)), GPRInfo::regT1); - - ASSERT(arrayBuffer->byteLength() < (1u << 31)); - if (arrayBuffer->byteLength() >= sizeOfMemoryType(memoryType)) - m_outOfBoundsErrorJumpList.append(branch32(Above, GPRInfo::regT1, TrustedImm32(arrayBuffer->byteLength() - sizeOfMemoryType(memoryType)))); - else - m_outOfBoundsErrorJumpList.append(jump()); - - BaseIndex address = BaseIndex(GPRInfo::regT0, GPRInfo::regT1, TimesOne); - - switch (expressionType) { - case WASMExpressionType::I32: - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT2); - switch (memoryType) { - case WASMMemoryType::I8: - store8(GPRInfo::regT2, address); - break; - case WASMMemoryType::I16: - store16(GPRInfo::regT2, address); - break; - case WASMMemoryType::I32: - store32(GPRInfo::regT2, address); - break; - default: - ASSERT_NOT_REACHED(); - } - break; - case WASMExpressionType::F32: - ASSERT(memoryType == WASMMemoryType::F32); - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT2); - store32(GPRInfo::regT2, address); - break; - case WASMExpressionType::F64: - ASSERT(memoryType == WASMMemoryType::F64); - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, address); - break; - default: - ASSERT_NOT_REACHED(); - } - m_tempStackTop -= 2; - - if (opKind == WASMOpKind::Expression) { - switch (expressionType) { - case WASMExpressionType::I32: - case WASMExpressionType::F32: - store32(GPRInfo::regT2, temporaryAddress(m_tempStackTop++)); - break; - case WASMExpressionType::F64: - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop++)); - break; - default: - ASSERT_NOT_REACHED(); - } - } - return UNUSED; - } - - int buildUnaryI32(int, WASMOpExpressionI32 op) - { - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT0); - switch (op) { - case WASMOpExpressionI32::Negate: - neg32(GPRInfo::regT0); - break; - case WASMOpExpressionI32::BitNot: - xor32(TrustedImm32(-1), GPRInfo::regT0); - break; - case WASMOpExpressionI32::CountLeadingZeros: - countLeadingZeros32(GPRInfo::regT0, GPRInfo::regT0); - break; - case WASMOpExpressionI32::LogicalNot: { - // FIXME: Don't use branches. - Jump zero = branchTest32(Zero, GPRInfo::regT0); - move(TrustedImm32(0), GPRInfo::regT0); - Jump end = jump(); - zero.link(this); - move(TrustedImm32(1), GPRInfo::regT0); - end.link(this); - break; - } - case WASMOpExpressionI32::Abs: { - // FIXME: Don't use branches. - Jump end = branchTest32(PositiveOrZero, GPRInfo::regT0); - neg32(GPRInfo::regT0); - end.link(this); - break; - } - default: - ASSERT_NOT_REACHED(); - } - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1)); - return UNUSED; - } - - int buildUnaryF32(int, WASMOpExpressionF32 op) - { - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1); - switch (op) { - case WASMOpExpressionF32::Negate: - convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1); - negateDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF32::Abs: - convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1); - absDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF32::Ceil: - callOperation(ceilf, FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF32::Floor: - callOperation(floorf, FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF32::Sqrt: - convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1); - sqrtDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - break; - default: - ASSERT_NOT_REACHED(); - } - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); - return UNUSED; - } - - int buildUnaryF64(int, WASMOpExpressionF64 op) - { - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1); - switch (op) { - case WASMOpExpressionF64::Negate: - negateDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF64::Abs: - absDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF64::Sqrt: - sqrtDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF64::Ceil: - case WASMOpExpressionF64::Floor: - case WASMOpExpressionF64::Cos: - case WASMOpExpressionF64::Sin: - case WASMOpExpressionF64::Tan: - case WASMOpExpressionF64::ACos: - case WASMOpExpressionF64::ASin: - case WASMOpExpressionF64::ATan: - case WASMOpExpressionF64::Exp: - case WASMOpExpressionF64::Ln: - D_JITOperation_D operation; - switch (op) { - case WASMOpExpressionF64::Ceil: - operation = ceil; - break; - case WASMOpExpressionF64::Floor: - operation = floor; - break; - case WASMOpExpressionF64::Cos: - operation = cos; - break; - case WASMOpExpressionF64::Sin: - operation = sin; - break; - case WASMOpExpressionF64::Tan: - operation = tan; - break; - case WASMOpExpressionF64::ACos: - operation = acos; - break; - case WASMOpExpressionF64::ASin: - operation = asin; - break; - case WASMOpExpressionF64::ATan: - operation = atan; - break; - case WASMOpExpressionF64::Exp: - operation = exp; - break; - case WASMOpExpressionF64::Ln: - operation = log; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - } - callOperation(operation, FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - default: - ASSERT_NOT_REACHED(); - } - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); - return UNUSED; - } - - int buildBinaryI32(int, int, WASMOpExpressionI32 op) - { - load32(temporaryAddress(m_tempStackTop - 2), GPRInfo::regT0); - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT1); - switch (op) { - case WASMOpExpressionI32::Add: - add32(GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::Sub: - sub32(GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::Mul: - mul32(GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::SDiv: - case WASMOpExpressionI32::UDiv: - case WASMOpExpressionI32::SMod: - case WASMOpExpressionI32::UMod: { - m_divideErrorJumpList.append(branchTest32(Zero, GPRInfo::regT1)); - if (op == WASMOpExpressionI32::SDiv || op == WASMOpExpressionI32::SMod) { - Jump denominatorNotNeg1 = branch32(NotEqual, GPRInfo::regT1, TrustedImm32(-1)); - m_divideErrorJumpList.append(branch32(Equal, GPRInfo::regT0, TrustedImm32(-2147483647-1))); - denominatorNotNeg1.link(this); - } -#if CPU(X86) || CPU(X86_64) - ASSERT(GPRInfo::regT0 == X86Registers::eax); - move(GPRInfo::regT1, X86Registers::ecx); - if (op == WASMOpExpressionI32::SDiv || op == WASMOpExpressionI32::SMod) { - x86ConvertToDoubleWord32(); - x86Div32(X86Registers::ecx); - } else { - ASSERT(op == WASMOpExpressionI32::UDiv || op == WASMOpExpressionI32::UMod); - xor32(X86Registers::edx, X86Registers::edx); - m_assembler.divl_r(X86Registers::ecx); - } - if (op == WASMOpExpressionI32::SMod || op == WASMOpExpressionI32::UMod) - move(X86Registers::edx, GPRInfo::regT0); -#else - // FIXME: We should be able to do an inline div on ARMv7 and ARM64. - switch (op) { - case WASMOpExpressionI32::SDiv: - callOperation(operationDiv, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::UDiv: - callOperation(operationUnsignedDiv, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::SMod: - callOperation(operationMod, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::UMod: - callOperation(operationUnsignedMod, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT0); - break; - default: - ASSERT_NOT_REACHED(); - } -#endif - break; - } - case WASMOpExpressionI32::BitOr: - or32(GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::BitAnd: - and32(GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::BitXor: - xor32(GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::LeftShift: - lshift32(GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::ArithmeticRightShift: - rshift32(GPRInfo::regT1, GPRInfo::regT0); - break; - case WASMOpExpressionI32::LogicalRightShift: - urshift32(GPRInfo::regT1, GPRInfo::regT0); - break; - default: - ASSERT_NOT_REACHED(); - } - m_tempStackTop--; - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1)); - return UNUSED; - } - - int buildBinaryF32(int, int, WASMOpExpressionF32 op) - { - loadDouble(temporaryAddress(m_tempStackTop - 2), FPRInfo::fpRegT0); - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1); - convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1); - switch (op) { - case WASMOpExpressionF32::Add: - addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF32::Sub: - subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF32::Mul: - mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF32::Div: - divDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - } - convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - m_tempStackTop--; - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); - return UNUSED; - } - - int buildBinaryF64(int, int, WASMOpExpressionF64 op) - { - loadDouble(temporaryAddress(m_tempStackTop - 2), FPRInfo::fpRegT0); - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1); - switch (op) { - case WASMOpExpressionF64::Add: - addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF64::Sub: - subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF64::Mul: - mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF64::Div: - divDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - case WASMOpExpressionF64::Mod: - case WASMOpExpressionF64::ATan2: - case WASMOpExpressionF64::Pow: - D_JITOperation_DD operation; - switch (op) { - case WASMOpExpressionF64::Mod: - operation = fmod; - break; - case WASMOpExpressionF64::ATan2: - operation = atan2; - break; - case WASMOpExpressionF64::Pow: - operation = pow; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - } - callOperation(operation, FPRInfo::fpRegT0, FPRInfo::fpRegT1, FPRInfo::fpRegT0); - break; - default: - ASSERT_NOT_REACHED(); - } - m_tempStackTop--; - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop - 1)); - return UNUSED; - } - - int buildRelationalI32(int, int, WASMOpExpressionI32 op) - { - load32(temporaryAddress(m_tempStackTop - 2), GPRInfo::regT0); - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT1); - RelationalCondition condition; - switch (op) { - case WASMOpExpressionI32::EqualI32: - condition = Equal; - break; - case WASMOpExpressionI32::NotEqualI32: - condition = NotEqual; - break; - case WASMOpExpressionI32::SLessThanI32: - condition = LessThan; - break; - case WASMOpExpressionI32::ULessThanI32: - condition = Below; - break; - case WASMOpExpressionI32::SLessThanOrEqualI32: - condition = LessThanOrEqual; - break; - case WASMOpExpressionI32::ULessThanOrEqualI32: - condition = BelowOrEqual; - break; - case WASMOpExpressionI32::SGreaterThanI32: - condition = GreaterThan; - break; - case WASMOpExpressionI32::UGreaterThanI32: - condition = Above; - break; - case WASMOpExpressionI32::SGreaterThanOrEqualI32: - condition = GreaterThanOrEqual; - break; - case WASMOpExpressionI32::UGreaterThanOrEqualI32: - condition = AboveOrEqual; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - } - compare32(condition, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT0); - m_tempStackTop--; - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop - 1)); - return UNUSED; - } - - int buildRelationalF32(int, int, WASMOpExpressionI32 op) - { - loadDouble(temporaryAddress(m_tempStackTop - 2), FPRInfo::fpRegT0); - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1); - convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - convertFloatToDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT1); - DoubleCondition condition; - switch (op) { - case WASMOpExpressionI32::EqualF32: - condition = DoubleEqual; - break; - case WASMOpExpressionI32::NotEqualF32: - condition = DoubleNotEqual; - break; - case WASMOpExpressionI32::LessThanF32: - condition = DoubleLessThan; - break; - case WASMOpExpressionI32::LessThanOrEqualF32: - condition = DoubleLessThanOrEqual; - break; - case WASMOpExpressionI32::GreaterThanF32: - condition = DoubleGreaterThan; - break; - case WASMOpExpressionI32::GreaterThanOrEqualF32: - condition = DoubleGreaterThanOrEqual; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - } - m_tempStackTop--; - Jump trueCase = branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1); - store32(TrustedImm32(0), temporaryAddress(m_tempStackTop - 1)); - Jump end = jump(); - trueCase.link(this); - store32(TrustedImm32(1), temporaryAddress(m_tempStackTop - 1)); - end.link(this); - return UNUSED; - } - - int buildRelationalF64(int, int, WASMOpExpressionI32 op) - { - loadDouble(temporaryAddress(m_tempStackTop - 2), FPRInfo::fpRegT0); - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1); - DoubleCondition condition; - switch (op) { - case WASMOpExpressionI32::EqualF64: - condition = DoubleEqual; - break; - case WASMOpExpressionI32::NotEqualF64: - condition = DoubleNotEqual; - break; - case WASMOpExpressionI32::LessThanF64: - condition = DoubleLessThan; - break; - case WASMOpExpressionI32::LessThanOrEqualF64: - condition = DoubleLessThanOrEqual; - break; - case WASMOpExpressionI32::GreaterThanF64: - condition = DoubleGreaterThan; - break; - case WASMOpExpressionI32::GreaterThanOrEqualF64: - condition = DoubleGreaterThanOrEqual; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - } - m_tempStackTop--; - Jump trueCase = branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1); - store32(TrustedImm32(0), temporaryAddress(m_tempStackTop - 1)); - Jump end = jump(); - trueCase.link(this); - store32(TrustedImm32(1), temporaryAddress(m_tempStackTop - 1)); - end.link(this); - return UNUSED; - } - - int buildMinOrMaxI32(int, int, WASMOpExpressionI32 op) - { - load32(temporaryAddress(m_tempStackTop - 2), GPRInfo::regT0); - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT1); - RelationalCondition condition; - switch (op) { - case WASMOpExpressionI32::SMin: - condition = LessThanOrEqual; - break; - case WASMOpExpressionI32::UMin: - condition = BelowOrEqual; - break; - case WASMOpExpressionI32::SMax: - condition = GreaterThanOrEqual; - break; - case WASMOpExpressionI32::UMax: - condition = AboveOrEqual; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - } - Jump useLeft = branch32(condition, GPRInfo::regT0, GPRInfo::regT1); - store32(GPRInfo::regT1, temporaryAddress(m_tempStackTop - 2)); - useLeft.link(this); - m_tempStackTop--; - return UNUSED; - } - - int buildMinOrMaxF64(int, int, WASMOpExpressionF64 op) - { - loadDouble(temporaryAddress(m_tempStackTop - 2), FPRInfo::fpRegT0); - loadDouble(temporaryAddress(m_tempStackTop - 1), FPRInfo::fpRegT1); - DoubleCondition condition; - switch (op) { - case WASMOpExpressionF64::Min: - condition = DoubleLessThanOrEqual; - break; - case WASMOpExpressionF64::Max: - condition = DoubleGreaterThanOrEqual; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - } - Jump useLeft = branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1); - storeDouble(FPRInfo::fpRegT1, temporaryAddress(m_tempStackTop - 2)); - useLeft.link(this); - m_tempStackTop--; - return UNUSED; - } - - int buildCallInternal(uint32_t functionIndex, int, const WASMSignature& signature, WASMExpressionType returnType) - { - boxArgumentsAndAdjustStackPointer(signature.arguments); - - JSFunction* function = m_module->functions()[functionIndex].get(); - move(TrustedImmPtr(function), GPRInfo::regT0); - - callAndUnboxResult(returnType); - return UNUSED; - } - - int buildCallIndirect(uint32_t functionPointerTableIndex, int, int, const WASMSignature& signature, WASMExpressionType returnType) - { - boxArgumentsAndAdjustStackPointer(signature.arguments); - - const Vector<JSFunction*>& functions = m_module->functionPointerTables()[functionPointerTableIndex].functions; - move(TrustedImmPtr(functions.data()), GPRInfo::regT0); - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT1); - m_tempStackTop--; - and32(TrustedImm32(functions.size() - 1), GPRInfo::regT1); - loadPtr(BaseIndex(GPRInfo::regT0, GPRInfo::regT1, timesPtr()), GPRInfo::regT0); - - callAndUnboxResult(returnType); - return UNUSED; - } - - int buildCallImport(uint32_t functionImportIndex, int, const WASMSignature& signature, WASMExpressionType returnType) - { - boxArgumentsAndAdjustStackPointer(signature.arguments); - - JSFunction* function = m_module->importedFunctions()[functionImportIndex].get(); - move(TrustedImmPtr(function), GPRInfo::regT0); - - callAndUnboxResult(returnType); - return UNUSED; - } - - void appendExpressionList(int&, int) { } - - void discard(int) - { - m_tempStackTop--; - } - - void linkTarget(JumpTarget& target) - { - target.label = label(); - target.jumpList.link(this); - } - - void jumpToTarget(JumpTarget& target) - { - if (target.label.isSet()) - jump(target.label); - else - target.jumpList.append(jump()); - } - - void jumpToTargetIf(JumpCondition condition, int, JumpTarget& target) - { - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT0); - m_tempStackTop--; - Jump taken = branchTest32((condition == JumpCondition::Zero) ? Zero : NonZero, GPRInfo::regT0); - if (target.label.isSet()) - taken.linkTo(target.label, this); - else - target.jumpList.append(taken); - } - - void startLoop() - { - m_breakTargets.append(JumpTarget()); - m_continueTargets.append(JumpTarget()); - } - - void endLoop() - { - m_breakTargets.removeLast(); - m_continueTargets.removeLast(); - } - - void startSwitch() - { - m_breakTargets.append(JumpTarget()); - } - - void endSwitch() - { - m_breakTargets.removeLast(); - } - - void startLabel() - { - m_breakLabelTargets.append(JumpTarget()); - m_continueLabelTargets.append(JumpTarget()); - - linkTarget(m_continueLabelTargets.last()); - } - - void endLabel() - { - linkTarget(m_breakLabelTargets.last()); - - m_breakLabelTargets.removeLast(); - m_continueLabelTargets.removeLast(); - } - - JumpTarget& breakTarget() - { - return m_breakTargets.last(); - } - - JumpTarget& continueTarget() - { - return m_continueTargets.last(); - } - - JumpTarget& breakLabelTarget(uint32_t labelIndex) - { - return m_breakLabelTargets[labelIndex]; - } - - JumpTarget& continueLabelTarget(uint32_t labelIndex) - { - return m_continueLabelTargets[labelIndex]; - } - - void buildSwitch(int, const Vector<int64_t>& cases, Vector<JumpTarget>& targets, JumpTarget defaultTarget) - { - load32(temporaryAddress(m_tempStackTop - 1), GPRInfo::regT0); - m_tempStackTop--; - BinarySwitch binarySwitch(GPRInfo::regT0, cases, BinarySwitch::Int32); - while (binarySwitch.advance(*this)) { - unsigned index = binarySwitch.caseIndex(); - jump(targets[index].label); - } - binarySwitch.fallThrough().linkTo(defaultTarget.label, this); - } - -private: - union StackSlot { - int32_t intValue; - float floatValue; - double doubleValue; - }; - - enum class FloatingPointPrecision { Single, Double }; - - Address localAddress(unsigned localIndex) const - { - ASSERT(localIndex < m_numberOfLocals); - return Address(GPRInfo::callFrameRegister, -m_calleeSaveSpace - (localIndex + 1) * sizeof(StackSlot)); - } - - Address temporaryAddress(unsigned temporaryIndex) const - { - ASSERT(m_numberOfLocals + temporaryIndex < m_stackHeight); - return Address(GPRInfo::callFrameRegister, -m_calleeSaveSpace - (m_numberOfLocals + temporaryIndex + 1) * sizeof(StackSlot)); - } - - void appendCall(const FunctionPtr& function) - { - m_calls.append(std::make_pair(call(), function.value())); - } - - void appendCallWithExceptionCheck(const FunctionPtr& function) - { - appendCall(function); - m_exceptionChecks.append(emitExceptionCheck()); - } - - Call emitNakedCall(CodePtr function) - { - Call nakedCall = nearCall(); - m_calls.append(std::make_pair(nakedCall, function.executableAddress())); - return nakedCall; - } - - void appendCallSetResult(const FunctionPtr& function, GPRReg result) - { - appendCall(function); - move(GPRInfo::returnValueGPR, result); - } - -#if CPU(X86) - void appendCallSetResult(const FunctionPtr& function, FPRReg result, FloatingPointPrecision precision) - { - appendCall(function); - switch (precision) { - case FloatingPointPrecision::Single: - m_assembler.fstps(0, stackPointerRegister); - break; - case FloatingPointPrecision::Double: - m_assembler.fstpl(0, stackPointerRegister); - break; - } - loadDouble(stackPointerRegister, result); - } -#elif CPU(ARM) && !CPU(ARM_HARDFP) - void appendCallSetResult(const FunctionPtr& function, FPRReg result, FloatingPointPrecision) - { - appendCall(function); - m_assembler.vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2); - } -#else // CPU(X86_64) || (CPU(ARM) && CPU(ARM_HARDFP)) || CPU(ARM64) || CPU(MIPS) || CPU(SH4) - void appendCallSetResult(const FunctionPtr& function, FPRReg result, FloatingPointPrecision) - { - appendCall(function); - moveDouble(FPRInfo::returnValueFPR, result); - } -#endif - -#if USE(JSVALUE64) - void callOperation(Z_JITOperation_EJ operation, GPRReg src, GPRReg dst) - { - setupArgumentsWithExecState(src); - appendCallSetResult(operation, dst); - } - - void callOperation(D_JITOperation_EJ operation, GPRReg src, FPRReg dst) - { - setupArgumentsWithExecState(src); - appendCallSetResult(operation, dst, FloatingPointPrecision::Double); - } -#else -// EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned on an even-numbered register (r0, r2 or [sp]). -// To prevent the assembler from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary. -#if (COMPILER_SUPPORTS(EABI) && CPU(ARM)) || CPU(MIPS) -#define EABI_32BIT_DUMMY_ARG TrustedImm32(0), -#else -#define EABI_32BIT_DUMMY_ARG -#endif - - void callOperation(Z_JITOperation_EJ operation, GPRReg srcTag, GPRReg srcPayload, GPRReg dst) - { - setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG srcPayload, srcTag); - appendCallSetResult(operation, dst); - } - - void callOperation(D_JITOperation_EJ operation, GPRReg srcTag, GPRReg srcPayload, FPRReg dst) - { - setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG srcPayload, srcTag); - appendCallSetResult(operation, dst, FloatingPointPrecision::Double); - } -#endif - - void callOperation(float JIT_OPERATION (*operation)(float), FPRegisterID src, FPRegisterID dst) - { - setupArguments(src); - appendCallSetResult(operation, dst, FloatingPointPrecision::Single); - } - - void callOperation(D_JITOperation_D operation, FPRegisterID src, FPRegisterID dst) - { - setupArguments(src); - appendCallSetResult(operation, dst, FloatingPointPrecision::Double); - } - - void callOperation(int32_t JIT_OPERATION (*operation)(int32_t, int32_t), GPRReg src1, GPRReg src2, GPRReg dst) - { - setupArguments(src1, src2); - appendCallSetResult(operation, dst); - } - - void callOperation(uint32_t JIT_OPERATION (*operation)(uint32_t, uint32_t), GPRReg src1, GPRReg src2, GPRReg dst) - { - setupArguments(src1, src2); - appendCallSetResult(operation, dst); - } - - void callOperation(D_JITOperation_DD operation, FPRegisterID src1, FPRegisterID src2, FPRegisterID dst) - { - setupArguments(src1, src2); - appendCallSetResult(operation, dst, FloatingPointPrecision::Double); - } - - void callOperation(double JIT_OPERATION (*operation)(uint32_t), GPRReg src, FPRegisterID dst) - { - setupArguments(src); - appendCallSetResult(operation, dst, FloatingPointPrecision::Double); - } - - void boxArgumentsAndAdjustStackPointer(const Vector<WASMType>& arguments) - { - size_t argumentCount = arguments.size(); - int stackOffset = -m_calleeSaveSpace - WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_numberOfLocals + m_tempStackTop + argumentCount + 1 + JSStack::CallFrameHeaderSize); - - storeTrustedValue(jsUndefined(), Address(GPRInfo::callFrameRegister, (stackOffset + CallFrame::thisArgumentOffset()) * sizeof(Register))); - - for (size_t i = 0; i < argumentCount; ++i) { - Address address(GPRInfo::callFrameRegister, (stackOffset + CallFrame::argumentOffset(i)) * sizeof(Register)); -#if USE(JSVALUE64) - JSValueRegs valueRegs(GPRInfo::regT0); -#else - JSValueRegs valueRegs(GPRInfo::regT1, GPRInfo::regT0); -#endif - switch (arguments[i]) { - case WASMType::I32: - load32(temporaryAddress(m_tempStackTop - argumentCount + i), GPRInfo::regT0); -#if USE(JSVALUE64) - or64(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0); - store64(GPRInfo::regT0, address); -#else - store32(GPRInfo::regT0, address.withOffset(PayloadOffset)); - store32(TrustedImm32(JSValue::Int32Tag), address.withOffset(TagOffset)); -#endif - break; - case WASMType::F32: - case WASMType::F64: - loadDouble(temporaryAddress(m_tempStackTop - argumentCount + i), FPRInfo::fpRegT0); - if (arguments[i] == WASMType::F32) - convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - convertDoubleToValue(FPRInfo::fpRegT0, valueRegs); - storeValue(valueRegs, address); - break; - default: - ASSERT_NOT_REACHED(); - } - } - m_tempStackTop -= argumentCount; - - addPtr(TrustedImm32(stackOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), GPRInfo::callFrameRegister, stackPointerRegister); - store32(TrustedImm32(argumentCount + 1), Address(stackPointerRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC))); - } - - void callAndUnboxResult(WASMExpressionType returnType) - { - // regT0 holds callee. -#if USE(JSVALUE64) - store64(GPRInfo::regT0, Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) - sizeof(CallerFrameAndPC))); -#else - store32(GPRInfo::regT0, Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC))); - store32(TrustedImm32(JSValue::CellTag), Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) + TagOffset - sizeof(CallerFrameAndPC))); -#endif - - DataLabelPtr addressOfLinkedFunctionCheck; - Jump slowCase = branchPtrWithPatch(NotEqual, GPRInfo::regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(0)); - - CallLinkInfo* info = m_codeBlock->addCallLinkInfo(); - info->setUpCall(CallLinkInfo::Call, CodeOrigin(), GPRInfo::regT0); - m_callCompilationInfo.append(CallCompilationInfo()); - m_callCompilationInfo.last().hotPathBegin = addressOfLinkedFunctionCheck; - m_callCompilationInfo.last().callLinkInfo = info; - m_callCompilationInfo.last().hotPathOther = nearCall(); - Jump end = jump(); - - slowCase.link(this); - move(TrustedImmPtr(info), GPRInfo::regT2); - m_callCompilationInfo.last().callReturnLocation = emitNakedCall(m_vm->getCTIStub(linkCallThunkGenerator).code()); - - end.link(this); - addPtr(TrustedImm32(-m_calleeSaveSpace - WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight) * sizeof(StackSlot) - maxFrameExtentForSlowPathCall), GPRInfo::callFrameRegister, stackPointerRegister); - checkStackPointerAlignment(); - - // FIXME: No need to do type conversion if the callee is a WebAssembly function. - // https://bugs.webkit.org/show_bug.cgi?id=149310 -#if USE(JSVALUE64) - JSValueRegs valueRegs(GPRInfo::returnValueGPR); -#else - JSValueRegs valueRegs(GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR); -#endif - switch (returnType) { - case WASMExpressionType::I32: - convertValueToInt32(valueRegs, GPRInfo::regT0); - store32(GPRInfo::regT0, temporaryAddress(m_tempStackTop++)); - break; - case WASMExpressionType::F32: - case WASMExpressionType::F64: -#if USE(JSVALUE64) - convertValueToDouble(valueRegs, FPRInfo::fpRegT0, GPRInfo::nonPreservedNonReturnGPR); -#else - convertValueToDouble(valueRegs, FPRInfo::fpRegT0, GPRInfo::nonPreservedNonReturnGPR, FPRInfo::fpRegT1); -#endif - if (returnType == WASMExpressionType::F32) - convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0); - storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_tempStackTop++)); - break; - case WASMExpressionType::Void: - break; - default: - ASSERT_NOT_REACHED(); - } - } - -#if USE(JSVALUE64) - void convertValueToInt32(JSValueRegs valueRegs, GPRReg dst) - { - Jump checkJSInt32 = branchIfInt32(valueRegs); - - callOperation(operationConvertJSValueToInt32, valueRegs.gpr(), valueRegs.gpr()); - - checkJSInt32.link(this); - move(valueRegs.gpr(), dst); - } - - void convertValueToDouble(JSValueRegs valueRegs, FPRReg dst, GPRReg scratch) - { - Jump checkJSInt32 = branchIfInt32(valueRegs); - Jump checkJSNumber = branchIfNumber(valueRegs, scratch); - JumpList end; - - callOperation(operationConvertJSValueToDouble, valueRegs.gpr(), dst); - end.append(jump()); - - checkJSInt32.link(this); - convertInt32ToDouble(valueRegs.gpr(), dst); - end.append(jump()); - - checkJSNumber.link(this); - unboxDoubleWithoutAssertions(valueRegs.gpr(), dst); - end.link(this); - } -#else - void convertValueToInt32(JSValueRegs valueRegs, GPRReg dst) - { - Jump checkJSInt32 = branchIfInt32(valueRegs); - - callOperation(operationConvertJSValueToInt32, valueRegs.tagGPR(), valueRegs.payloadGPR(), valueRegs.payloadGPR()); - - checkJSInt32.link(this); - move(valueRegs.payloadGPR(), dst); - } - - void convertValueToDouble(JSValueRegs valueRegs, FPRReg dst, GPRReg scratch, FPRReg fpScratch) - { - Jump checkJSInt32 = branchIfInt32(valueRegs); - Jump checkJSNumber = branchIfNumber(valueRegs, scratch); - JumpList end; - - callOperation(operationConvertJSValueToDouble, valueRegs.tagGPR(), valueRegs.payloadGPR(), dst); - end.append(jump()); - - checkJSInt32.link(this); - convertInt32ToDouble(valueRegs.payloadGPR(), dst); - end.append(jump()); - - checkJSNumber.link(this); - unboxDouble(valueRegs.tagGPR(), valueRegs.payloadGPR(), dst, fpScratch); - end.link(this); - } -#endif - - void convertDoubleToValue(FPRReg fpr, JSValueRegs valueRegs) - { -#if USE(JSVALUE64) - boxDouble(fpr, valueRegs.gpr()); -#else - boxDouble(fpr, valueRegs.tagGPR(), valueRegs.payloadGPR()); -#endif - } - - JSWASMModule* m_module; - unsigned m_stackHeight; - unsigned m_numberOfLocals; - unsigned m_tempStackTop { 0 }; - unsigned m_calleeSaveSpace; - - Vector<JumpTarget> m_breakTargets; - Vector<JumpTarget> m_continueTargets; - Vector<JumpTarget> m_breakLabelTargets; - Vector<JumpTarget> m_continueLabelTargets; - - Label m_beginLabel; - Jump m_stackOverflow; - JumpList m_divideErrorJumpList; - JumpList m_outOfBoundsErrorJumpList; - JumpList m_exceptionChecks; - - Vector<std::pair<Call, void*>> m_calls; - Vector<CallCompilationInfo> m_callCompilationInfo; -}; - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) - -#endif // WASMFunctionCompiler_h diff --git a/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp b/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp deleted file mode 100644 index e65da5885..000000000 --- a/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "WASMFunctionParser.h" - -#if ENABLE(WEBASSEMBLY) - -#include "JSCJSValueInlines.h" -#include "JSWASMModule.h" -#include "WASMFunctionCompiler.h" -#include "WASMFunctionB3IRGenerator.h" -#include "WASMFunctionSyntaxChecker.h" - -#define PROPAGATE_ERROR() do { if (!m_errorMessage.isNull()) return 0; } while (0) -#define FAIL_WITH_MESSAGE(errorMessage) do { m_errorMessage = errorMessage; return 0; } while (0) -#define READ_FLOAT_OR_FAIL(result, errorMessage) do { if (!m_reader.readFloat(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_DOUBLE_OR_FAIL(result, errorMessage) do { if (!m_reader.readDouble(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_COMPACT_INT32_OR_FAIL(result, errorMessage) do { if (!m_reader.readCompactInt32(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_COMPACT_UINT32_OR_FAIL(result, errorMessage) do { if (!m_reader.readCompactUInt32(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_EXPRESSION_TYPE_OR_FAIL(result, errorMessage) do { if (!m_reader.readExpressionType(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_OP_STATEMENT_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpStatement(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_OP_EXPRESSION_I32_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpExpressionI32(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_OP_EXPRESSION_F32_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpExpressionF32(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_OP_EXPRESSION_F64_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, errorMessage) do { if (!m_reader.readOpExpressionF64(hasImmediate, op, opWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_OP_EXPRESSION_VOID_OR_FAIL(op, errorMessage) do { if (!m_reader.readOpExpressionVoid(op)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_VARIABLE_TYPES_OR_FAIL(hasImmediate, variableTypes, variableTypesWithImmediate, immediate, errorMessage) do { if (!m_reader.readVariableTypes(hasImmediate, variableTypes, variableTypesWithImmediate, immediate)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_SWITCH_CASE_OR_FAIL(result, errorMessage) do { if (!m_reader.readSwitchCase(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define FAIL_IF_FALSE(condition, errorMessage) do { if (!(condition)) FAIL_WITH_MESSAGE(errorMessage); } while (0) - -#define UNUSED 0 - -namespace JSC { - -static String nameOfType(WASMType type) -{ - switch (type) { - case WASMType::I32: - return "int32"; - case WASMType::F32: - return "float32"; - case WASMType::F64: - return "float64"; - default: - RELEASE_ASSERT_NOT_REACHED(); - } -} - -bool WASMFunctionParser::checkSyntax(JSWASMModule* module, const SourceCode& source, size_t functionIndex, unsigned startOffsetInSource, unsigned& endOffsetInSource, unsigned& stackHeight, String& errorMessage) -{ - WASMFunctionParser parser(module, source, functionIndex); - WASMFunctionSyntaxChecker syntaxChecker; - parser.m_reader.setOffset(startOffsetInSource); - parser.parseFunction(syntaxChecker); - if (!parser.m_errorMessage.isNull()) { - errorMessage = parser.m_errorMessage; - return false; - } - endOffsetInSource = parser.m_reader.offset(); - stackHeight = syntaxChecker.stackHeight(); - return true; -} - -void WASMFunctionParser::compile(VM& vm, CodeBlock* codeBlock, JSWASMModule* module, const SourceCode& source, size_t functionIndex) -{ - WASMFunctionParser parser(module, source, functionIndex); - WASMFunctionCompiler compiler(vm, codeBlock, module, module->functionStackHeights()[functionIndex]); - parser.m_reader.setOffset(module->functionStartOffsetsInSource()[functionIndex]); - parser.parseFunction(compiler); - ASSERT(parser.m_errorMessage.isNull()); -} - -template <class Context> -bool WASMFunctionParser::parseFunction(Context& context) -{ - const WASMSignature& signature = m_module->signatures()[m_module->functionDeclarations()[m_functionIndex].signatureIndex]; - - m_returnType = signature.returnType; - - parseLocalVariables(); - PROPAGATE_ERROR(); - - const Vector<WASMType>& arguments = signature.arguments; - for (size_t i = 0; i < arguments.size(); ++i) - m_localTypes.append(arguments[i]); - for (uint32_t i = 0; i < m_numberOfI32LocalVariables; ++i) - m_localTypes.append(WASMType::I32); - for (uint32_t i = 0; i < m_numberOfF32LocalVariables; ++i) - m_localTypes.append(WASMType::F32); - for (uint32_t i = 0; i < m_numberOfF64LocalVariables; ++i) - m_localTypes.append(WASMType::F64); - - context.startFunction(arguments, m_numberOfI32LocalVariables, m_numberOfF32LocalVariables, m_numberOfF64LocalVariables); - - parseBlockStatement(context); - PROPAGATE_ERROR(); - - context.endFunction(); - return true; -} - -bool WASMFunctionParser::parseLocalVariables() -{ - m_numberOfI32LocalVariables = 0; - m_numberOfF32LocalVariables = 0; - m_numberOfF64LocalVariables = 0; - - bool hasImmediate; - WASMVariableTypes variableTypes; - WASMVariableTypesWithImmediate variableTypesWithImmediate; - uint8_t immediate; - READ_VARIABLE_TYPES_OR_FAIL(hasImmediate, variableTypes, variableTypesWithImmediate, immediate, "Cannot read the types of local variables."); - if (!hasImmediate) { - if (static_cast<uint8_t>(variableTypes) & static_cast<uint8_t>(WASMVariableTypes::I32)) - READ_COMPACT_UINT32_OR_FAIL(m_numberOfI32LocalVariables, "Cannot read the number of int32 local variables."); - if (static_cast<uint8_t>(variableTypes) & static_cast<uint8_t>(WASMVariableTypes::F32)) - READ_COMPACT_UINT32_OR_FAIL(m_numberOfF32LocalVariables, "Cannot read the number of float32 local variables."); - if (static_cast<uint8_t>(variableTypes) & static_cast<uint8_t>(WASMVariableTypes::F64)) - READ_COMPACT_UINT32_OR_FAIL(m_numberOfF64LocalVariables, "Cannot read the number of float64 local variables."); - } else - m_numberOfI32LocalVariables = immediate; - return true; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseStatement(Context& context) -{ - bool hasImmediate; - WASMOpStatement op; - WASMOpStatementWithImmediate opWithImmediate; - uint8_t immediate; - READ_OP_STATEMENT_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, "Cannot read the statement opcode."); - if (!hasImmediate) { - switch (op) { - case WASMOpStatement::SetLocal: - parseSetLocal(context, WASMOpKind::Statement, WASMExpressionType::Void); - break; - case WASMOpStatement::SetGlobal: - parseSetGlobal(context, WASMOpKind::Statement, WASMExpressionType::Void); - break; - case WASMOpStatement::I32Store8: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset); - break; - case WASMOpStatement::I32StoreWithOffset8: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset); - break; - case WASMOpStatement::I32Store16: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset); - break; - case WASMOpStatement::I32StoreWithOffset16: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset); - break; - case WASMOpStatement::I32Store32: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::NoOffset); - break; - case WASMOpStatement::I32StoreWithOffset32: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset); - break; - case WASMOpStatement::F32Store: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::NoOffset); - break; - case WASMOpStatement::F32StoreWithOffset: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset); - break; - case WASMOpStatement::F64Store: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::NoOffset); - break; - case WASMOpStatement::F64StoreWithOffset: - parseStore(context, WASMOpKind::Statement, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset); - break; - case WASMOpStatement::CallInternal: - parseCallInternal(context, WASMOpKind::Statement, WASMExpressionType::Void); - break; - case WASMOpStatement::CallIndirect: - parseCallIndirect(context, WASMOpKind::Statement, WASMExpressionType::Void); - break; - case WASMOpStatement::CallImport: - parseCallImport(context, WASMOpKind::Statement, WASMExpressionType::Void); - break; - case WASMOpStatement::Return: - parseReturnStatement(context); - break; - case WASMOpStatement::Block: - parseBlockStatement(context); - break; - case WASMOpStatement::If: - parseIfStatement(context); - break; - case WASMOpStatement::IfElse: - parseIfElseStatement(context); - break; - case WASMOpStatement::While: - parseWhileStatement(context); - break; - case WASMOpStatement::Do: - parseDoStatement(context); - break; - case WASMOpStatement::Label: - parseLabelStatement(context); - break; - case WASMOpStatement::Break: - parseBreakStatement(context); - break; - case WASMOpStatement::BreakLabel: - parseBreakLabelStatement(context); - break; - case WASMOpStatement::Continue: - parseContinueStatement(context); - break; - case WASMOpStatement::ContinueLabel: - parseContinueLabelStatement(context); - break; - case WASMOpStatement::Switch: - parseSwitchStatement(context); - break; - default: - ASSERT_NOT_REACHED(); - } - } else { - switch (opWithImmediate) { - case WASMOpStatementWithImmediate::SetLocal: - parseSetLocal(context, WASMOpKind::Statement, WASMExpressionType::Void, immediate); - break; - case WASMOpStatementWithImmediate::SetGlobal: - parseSetGlobal(context, WASMOpKind::Statement, WASMExpressionType::Void, immediate); - break; - default: - ASSERT_NOT_REACHED(); - } - } - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseReturnStatement(Context& context) -{ - ContextExpression expression = 0; - if (m_returnType != WASMExpressionType::Void) { - expression = parseExpression(context, m_returnType); - PROPAGATE_ERROR(); - } - context.buildReturn(expression, m_returnType); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseBlockStatement(Context& context) -{ - uint32_t numberOfStatements; - READ_COMPACT_UINT32_OR_FAIL(numberOfStatements, "Cannot read the number of statements."); - for (uint32_t i = 0; i < numberOfStatements; ++i) { - parseStatement(context); - PROPAGATE_ERROR(); - } - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseIfStatement(Context& context) -{ - ContextJumpTarget end; - - ContextExpression expression = parseExpressionI32(context); - PROPAGATE_ERROR(); - - context.jumpToTargetIf(Context::JumpCondition::Zero, expression, end); - - parseStatement(context); - PROPAGATE_ERROR(); - - context.linkTarget(end); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseIfElseStatement(Context& context) -{ - ContextJumpTarget elseTarget; - ContextJumpTarget end; - - ContextExpression expression = parseExpressionI32(context); - PROPAGATE_ERROR(); - - context.jumpToTargetIf(Context::JumpCondition::Zero, expression, elseTarget); - - parseStatement(context); - PROPAGATE_ERROR(); - - context.jumpToTarget(end); - context.linkTarget(elseTarget); - - parseStatement(context); - PROPAGATE_ERROR(); - - context.linkTarget(end); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseWhileStatement(Context& context) -{ - context.startLoop(); - context.linkTarget(context.continueTarget()); - - ContextExpression expression = parseExpressionI32(context); - PROPAGATE_ERROR(); - - context.jumpToTargetIf(Context::JumpCondition::Zero, expression, context.breakTarget()); - - m_breakScopeDepth++; - m_continueScopeDepth++; - parseStatement(context); - PROPAGATE_ERROR(); - m_continueScopeDepth--; - m_breakScopeDepth--; - - context.jumpToTarget(context.continueTarget()); - - context.linkTarget(context.breakTarget()); - context.endLoop(); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseDoStatement(Context& context) -{ - context.startLoop(); - - ContextJumpTarget topOfLoop; - context.linkTarget(topOfLoop); - - m_breakScopeDepth++; - m_continueScopeDepth++; - parseStatement(context); - PROPAGATE_ERROR(); - m_continueScopeDepth--; - m_breakScopeDepth--; - - context.linkTarget(context.continueTarget()); - - ContextExpression expression = parseExpressionI32(context); - PROPAGATE_ERROR(); - - context.jumpToTargetIf(Context::JumpCondition::NonZero, expression, topOfLoop); - - context.linkTarget(context.breakTarget()); - context.endLoop(); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseLabelStatement(Context& context) -{ - context.startLabel(); - m_labelDepth++; - parseStatement(context); - PROPAGATE_ERROR(); - m_labelDepth--; - context.endLabel(); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseBreakStatement(Context& context) -{ - FAIL_IF_FALSE(m_breakScopeDepth, "'break' is only valid inside a switch or loop statement."); - context.jumpToTarget(context.breakTarget()); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseBreakLabelStatement(Context& context) -{ - uint32_t labelIndex; - READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index."); - FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect."); - context.jumpToTarget(context.breakLabelTarget(labelIndex)); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseContinueStatement(Context& context) -{ - FAIL_IF_FALSE(m_continueScopeDepth, "'continue' is only valid inside a loop statement."); - context.jumpToTarget(context.continueTarget()); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseContinueLabelStatement(Context& context) -{ - uint32_t labelIndex; - READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index."); - FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect."); - context.jumpToTarget(context.continueLabelTarget(labelIndex)); - return UNUSED; -} - -template <class Context> -ContextStatement WASMFunctionParser::parseSwitchStatement(Context& context) -{ - context.startSwitch(); - uint32_t numberOfCases; - READ_COMPACT_UINT32_OR_FAIL(numberOfCases, "Cannot read the number of cases."); - ContextExpression expression = parseExpressionI32(context); - PROPAGATE_ERROR(); - - ContextJumpTarget compare; - context.jumpToTarget(compare); - - Vector<int64_t> cases; - Vector<ContextJumpTarget> targets; - cases.reserveInitialCapacity(numberOfCases); - targets.reserveInitialCapacity(numberOfCases); - bool hasDefault = false; - ContextJumpTarget defaultTarget; - - m_breakScopeDepth++; - for (uint32_t i = 0; i < numberOfCases; ++i) { - WASMSwitchCase switchCase; - READ_SWITCH_CASE_OR_FAIL(switchCase, "Cannot read the switch case."); - switch (switchCase) { - case WASMSwitchCase::CaseWithNoStatements: - case WASMSwitchCase::CaseWithStatement: - case WASMSwitchCase::CaseWithBlockStatement: { - uint32_t value; - READ_COMPACT_INT32_OR_FAIL(value, "Cannot read the value of the switch case."); - cases.uncheckedAppend(value); - ContextJumpTarget target; - context.linkTarget(target); - targets.uncheckedAppend(target); - if (switchCase == WASMSwitchCase::CaseWithStatement) { - parseStatement(context); - PROPAGATE_ERROR(); - } else if (switchCase == WASMSwitchCase::CaseWithBlockStatement) { - parseBlockStatement(context); - PROPAGATE_ERROR(); - } - break; - } - case WASMSwitchCase::DefaultWithNoStatements: - case WASMSwitchCase::DefaultWithStatement: - case WASMSwitchCase::DefaultWithBlockStatement: { - FAIL_IF_FALSE(i == numberOfCases - 1, "The default case must be the last case."); - hasDefault = true; - context.linkTarget(defaultTarget); - if (switchCase == WASMSwitchCase::DefaultWithStatement) { - parseStatement(context); - PROPAGATE_ERROR(); - } else if (switchCase == WASMSwitchCase::DefaultWithBlockStatement) { - parseBlockStatement(context); - PROPAGATE_ERROR(); - } - break; - } - default: - ASSERT_NOT_REACHED(); - } - } - if (!hasDefault) - context.linkTarget(defaultTarget); - - m_breakScopeDepth--; - - context.jumpToTarget(context.breakTarget()); - context.linkTarget(compare); - - context.buildSwitch(expression, cases, targets, defaultTarget); - - context.linkTarget(context.breakTarget()); - context.endSwitch(); - return UNUSED; -} - -template <class Context> -ContextExpression WASMFunctionParser::parseExpression(Context& context, WASMExpressionType expressionType) -{ - switch (expressionType) { - case WASMExpressionType::I32: - return parseExpressionI32(context); - case WASMExpressionType::F32: - return parseExpressionF32(context); - case WASMExpressionType::F64: - return parseExpressionF64(context); - case WASMExpressionType::Void: - return parseExpressionVoid(context); - default: - RELEASE_ASSERT_NOT_REACHED(); - } -} - -template <class Context> -ContextExpression WASMFunctionParser::parseExpressionI32(Context& context) -{ - bool hasImmediate; - WASMOpExpressionI32 op; - WASMOpExpressionI32WithImmediate opWithImmediate; - uint8_t immediate; - READ_OP_EXPRESSION_I32_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, "Cannot read the int32 expression opcode."); - if (!hasImmediate) { - switch (op) { - case WASMOpExpressionI32::ConstantPoolIndex: - return parseConstantPoolIndexExpressionI32(context); - case WASMOpExpressionI32::Immediate: - return parseImmediateExpressionI32(context); - case WASMOpExpressionI32::GetLocal: - return parseGetLocalExpression(context, WASMType::I32); - case WASMOpExpressionI32::GetGlobal: - return parseGetGlobalExpression(context, WASMType::I32); - case WASMOpExpressionI32::SetLocal: - return parseSetLocal(context, WASMOpKind::Expression, WASMExpressionType::I32); - case WASMOpExpressionI32::SetGlobal: - return parseSetGlobal(context, WASMOpKind::Expression, WASMExpressionType::I32); - case WASMOpExpressionI32::SLoad8: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset, MemoryAccessConversion::SignExtend); - case WASMOpExpressionI32::SLoadWithOffset8: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset, MemoryAccessConversion::SignExtend); - case WASMOpExpressionI32::ULoad8: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset, MemoryAccessConversion::ZeroExtend); - case WASMOpExpressionI32::ULoadWithOffset8: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset, MemoryAccessConversion::ZeroExtend); - case WASMOpExpressionI32::SLoad16: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset, MemoryAccessConversion::SignExtend); - case WASMOpExpressionI32::SLoadWithOffset16: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset, MemoryAccessConversion::SignExtend); - case WASMOpExpressionI32::ULoad16: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset, MemoryAccessConversion::ZeroExtend); - case WASMOpExpressionI32::ULoadWithOffset16: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset, MemoryAccessConversion::ZeroExtend); - case WASMOpExpressionI32::Load32: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::NoOffset); - case WASMOpExpressionI32::LoadWithOffset32: - return parseLoad(context, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset); - case WASMOpExpressionI32::Store8: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::NoOffset); - case WASMOpExpressionI32::StoreWithOffset8: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I8, MemoryAccessOffsetMode::WithOffset); - case WASMOpExpressionI32::Store16: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::NoOffset); - case WASMOpExpressionI32::StoreWithOffset16: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I16, MemoryAccessOffsetMode::WithOffset); - case WASMOpExpressionI32::Store32: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::NoOffset); - case WASMOpExpressionI32::StoreWithOffset32: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::I32, WASMMemoryType::I32, MemoryAccessOffsetMode::WithOffset); - case WASMOpExpressionI32::CallInternal: - return parseCallInternal(context, WASMOpKind::Expression, WASMExpressionType::I32); - case WASMOpExpressionI32::CallIndirect: - return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::I32); - case WASMOpExpressionI32::CallImport: - return parseCallImport(context, WASMOpKind::Expression, WASMExpressionType::I32); - case WASMOpExpressionI32::Conditional: - return parseConditional(context, WASMExpressionType::I32); - case WASMOpExpressionI32::Comma: - return parseComma(context, WASMExpressionType::I32); - case WASMOpExpressionI32::FromF32: - return parseConvertType(context, WASMExpressionType::F32, WASMExpressionType::I32, WASMTypeConversion::ConvertSigned); - case WASMOpExpressionI32::FromF64: - return parseConvertType(context, WASMExpressionType::F64, WASMExpressionType::I32, WASMTypeConversion::ConvertSigned); - case WASMOpExpressionI32::Negate: - case WASMOpExpressionI32::BitNot: - case WASMOpExpressionI32::CountLeadingZeros: - case WASMOpExpressionI32::LogicalNot: - case WASMOpExpressionI32::Abs: - return parseUnaryExpressionI32(context, op); - case WASMOpExpressionI32::Add: - case WASMOpExpressionI32::Sub: - case WASMOpExpressionI32::Mul: - case WASMOpExpressionI32::SDiv: - case WASMOpExpressionI32::UDiv: - case WASMOpExpressionI32::SMod: - case WASMOpExpressionI32::UMod: - case WASMOpExpressionI32::BitOr: - case WASMOpExpressionI32::BitAnd: - case WASMOpExpressionI32::BitXor: - case WASMOpExpressionI32::LeftShift: - case WASMOpExpressionI32::ArithmeticRightShift: - case WASMOpExpressionI32::LogicalRightShift: - return parseBinaryExpressionI32(context, op); - case WASMOpExpressionI32::EqualI32: - case WASMOpExpressionI32::NotEqualI32: - case WASMOpExpressionI32::SLessThanI32: - case WASMOpExpressionI32::ULessThanI32: - case WASMOpExpressionI32::SLessThanOrEqualI32: - case WASMOpExpressionI32::ULessThanOrEqualI32: - case WASMOpExpressionI32::SGreaterThanI32: - case WASMOpExpressionI32::UGreaterThanI32: - case WASMOpExpressionI32::SGreaterThanOrEqualI32: - case WASMOpExpressionI32::UGreaterThanOrEqualI32: - return parseRelationalI32ExpressionI32(context, op); - case WASMOpExpressionI32::EqualF32: - case WASMOpExpressionI32::NotEqualF32: - case WASMOpExpressionI32::LessThanF32: - case WASMOpExpressionI32::LessThanOrEqualF32: - case WASMOpExpressionI32::GreaterThanF32: - case WASMOpExpressionI32::GreaterThanOrEqualF32: - return parseRelationalF32ExpressionI32(context, op); - case WASMOpExpressionI32::EqualF64: - case WASMOpExpressionI32::NotEqualF64: - case WASMOpExpressionI32::LessThanF64: - case WASMOpExpressionI32::LessThanOrEqualF64: - case WASMOpExpressionI32::GreaterThanF64: - case WASMOpExpressionI32::GreaterThanOrEqualF64: - return parseRelationalF64ExpressionI32(context, op); - case WASMOpExpressionI32::SMin: - case WASMOpExpressionI32::UMin: - case WASMOpExpressionI32::SMax: - case WASMOpExpressionI32::UMax: - return parseMinOrMaxExpressionI32(context, op); - default: - ASSERT_NOT_REACHED(); - } - } else { - switch (opWithImmediate) { - case WASMOpExpressionI32WithImmediate::ConstantPoolIndex: - return parseConstantPoolIndexExpressionI32(context, immediate); - case WASMOpExpressionI32WithImmediate::Immediate: - return parseImmediateExpressionI32(context, immediate); - case WASMOpExpressionI32WithImmediate::GetLocal: - return parseGetLocalExpression(context, WASMType::I32, immediate); - default: - ASSERT_NOT_REACHED(); - } - } - return 0; -} - -template <class Context> -ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionI32(Context& context, uint32_t constantPoolIndex) -{ - FAIL_IF_FALSE(constantPoolIndex < m_module->i32Constants().size(), "The constant pool index is incorrect."); - return context.buildImmediateI32(m_module->i32Constants()[constantPoolIndex]); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionI32(Context& context) -{ - uint32_t constantPoolIndex; - READ_COMPACT_UINT32_OR_FAIL(constantPoolIndex, "Cannot read the constant pool index."); - return parseConstantPoolIndexExpressionI32(context, constantPoolIndex); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseImmediateExpressionI32(Context& context, uint32_t immediate) -{ - return context.buildImmediateI32(immediate); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseImmediateExpressionI32(Context& context) -{ - uint32_t immediate; - READ_COMPACT_UINT32_OR_FAIL(immediate, "Cannot read the immediate."); - return parseImmediateExpressionI32(context, immediate); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseUnaryExpressionI32(Context& context, WASMOpExpressionI32 op) -{ - ContextExpression expression = parseExpressionI32(context); - PROPAGATE_ERROR(); - return context.buildUnaryI32(expression, op); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseBinaryExpressionI32(Context& context, WASMOpExpressionI32 op) -{ - ContextExpression left = parseExpressionI32(context); - PROPAGATE_ERROR(); - ContextExpression right = parseExpressionI32(context); - PROPAGATE_ERROR(); - return context.buildBinaryI32(left, right, op); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseRelationalI32ExpressionI32(Context& context, WASMOpExpressionI32 op) -{ - ContextExpression left = parseExpressionI32(context); - PROPAGATE_ERROR(); - ContextExpression right = parseExpressionI32(context); - PROPAGATE_ERROR(); - return context.buildRelationalI32(left, right, op); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseRelationalF32ExpressionI32(Context& context, WASMOpExpressionI32 op) -{ - ContextExpression left = parseExpressionF32(context); - PROPAGATE_ERROR(); - ContextExpression right = parseExpressionF32(context); - PROPAGATE_ERROR(); - return context.buildRelationalF32(left, right, op); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseRelationalF64ExpressionI32(Context& context, WASMOpExpressionI32 op) -{ - ContextExpression left = parseExpressionF64(context); - PROPAGATE_ERROR(); - ContextExpression right = parseExpressionF64(context); - PROPAGATE_ERROR(); - return context.buildRelationalF64(left, right, op); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseMinOrMaxExpressionI32(Context& context, WASMOpExpressionI32 op) -{ - uint32_t numberOfArguments; - READ_COMPACT_UINT32_OR_FAIL(numberOfArguments, "Cannot read the number of arguments to min/max."); - FAIL_IF_FALSE(numberOfArguments >= 2, "Min/max must be passed at least 2 arguments."); - ContextExpression current = parseExpressionI32(context); - PROPAGATE_ERROR(); - for (uint32_t i = 1; i < numberOfArguments; ++i) { - ContextExpression expression = parseExpressionI32(context); - PROPAGATE_ERROR(); - current = context.buildMinOrMaxI32(current, expression, op); - } - return current; -} - -template <class Context> -ContextExpression WASMFunctionParser::parseExpressionF32(Context& context) -{ - bool hasImmediate; - WASMOpExpressionF32 op; - WASMOpExpressionF32WithImmediate opWithImmediate; - uint8_t immediate; - READ_OP_EXPRESSION_F32_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, "Cannot read the float32 expression opcode."); - if (!hasImmediate) { - switch (op) { - case WASMOpExpressionF32::ConstantPoolIndex: - return parseConstantPoolIndexExpressionF32(context); - case WASMOpExpressionF32::Immediate: - return parseImmediateExpressionF32(context); - case WASMOpExpressionF32::GetLocal: - return parseGetLocalExpression(context, WASMType::F32); - case WASMOpExpressionF32::GetGlobal: - return parseGetGlobalExpression(context, WASMType::F32); - case WASMOpExpressionF32::SetLocal: - return parseSetLocal(context, WASMOpKind::Expression, WASMExpressionType::F32); - case WASMOpExpressionF32::SetGlobal: - return parseSetGlobal(context, WASMOpKind::Expression, WASMExpressionType::F32); - case WASMOpExpressionF32::Load: - return parseLoad(context, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::NoOffset); - case WASMOpExpressionF32::LoadWithOffset: - return parseLoad(context, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset); - case WASMOpExpressionF32::Store: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::NoOffset); - case WASMOpExpressionF32::StoreWithOffset: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F32, WASMMemoryType::F32, MemoryAccessOffsetMode::WithOffset); - case WASMOpExpressionF32::CallInternal: - return parseCallInternal(context, WASMOpKind::Expression, WASMExpressionType::F32); - case WASMOpExpressionF32::CallIndirect: - return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::F32); - case WASMOpExpressionF32::Conditional: - return parseConditional(context, WASMExpressionType::F32); - case WASMOpExpressionF32::Comma: - return parseComma(context, WASMExpressionType::F32); - case WASMOpExpressionF32::FromS32: - return parseConvertType(context, WASMExpressionType::I32, WASMExpressionType::F32, WASMTypeConversion::ConvertSigned); - case WASMOpExpressionF32::FromU32: - return parseConvertType(context, WASMExpressionType::I32, WASMExpressionType::F32, WASMTypeConversion::ConvertUnsigned); - case WASMOpExpressionF32::FromF64: - return parseConvertType(context, WASMExpressionType::F64, WASMExpressionType::F32, WASMTypeConversion::Demote); - case WASMOpExpressionF32::Negate: - case WASMOpExpressionF32::Abs: - case WASMOpExpressionF32::Ceil: - case WASMOpExpressionF32::Floor: - case WASMOpExpressionF32::Sqrt: - return parseUnaryExpressionF32(context, op); - case WASMOpExpressionF32::Add: - case WASMOpExpressionF32::Sub: - case WASMOpExpressionF32::Mul: - case WASMOpExpressionF32::Div: - return parseBinaryExpressionF32(context, op); - default: - ASSERT_NOT_REACHED(); - } - } else { - switch (opWithImmediate) { - case WASMOpExpressionF32WithImmediate::ConstantPoolIndex: - return parseConstantPoolIndexExpressionF32(context, immediate); - case WASMOpExpressionF32WithImmediate::GetLocal: - return parseGetLocalExpression(context, WASMType::F32, immediate); - default: - ASSERT_NOT_REACHED(); - } - } - return 0; -} - -template <class Context> -ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionF32(Context& context, uint32_t constantIndex) -{ - FAIL_IF_FALSE(constantIndex < m_module->f32Constants().size(), "The constant pool index is incorrect."); - return context.buildImmediateF32(m_module->f32Constants()[constantIndex]); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionF32(Context& context) -{ - uint32_t constantIndex; - READ_COMPACT_UINT32_OR_FAIL(constantIndex, "Cannot read the constant pool index."); - return parseConstantPoolIndexExpressionF32(context, constantIndex); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseImmediateExpressionF32(Context& context) -{ - float immediate; - READ_FLOAT_OR_FAIL(immediate, "Cannot read the immediate."); - return context.buildImmediateF32(immediate); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseUnaryExpressionF32(Context& context, WASMOpExpressionF32 op) -{ - ContextExpression expression = parseExpressionF32(context); - PROPAGATE_ERROR(); - return context.buildUnaryF32(expression, op); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseBinaryExpressionF32(Context& context, WASMOpExpressionF32 op) -{ - ContextExpression left = parseExpressionF32(context); - PROPAGATE_ERROR(); - ContextExpression right = parseExpressionF32(context); - PROPAGATE_ERROR(); - return context.buildBinaryF32(left, right, op); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseExpressionF64(Context& context) -{ - bool hasImmediate; - WASMOpExpressionF64 op; - WASMOpExpressionF64WithImmediate opWithImmediate; - uint8_t immediate; - READ_OP_EXPRESSION_F64_OR_FAIL(hasImmediate, op, opWithImmediate, immediate, "Cannot read the float64 expression opcode."); - if (!hasImmediate) { - switch (op) { - case WASMOpExpressionF64::ConstantPoolIndex: - return parseConstantPoolIndexExpressionF64(context); - case WASMOpExpressionF64::Immediate: - return parseImmediateExpressionF64(context); - case WASMOpExpressionF64::GetLocal: - return parseGetLocalExpression(context, WASMType::F64); - case WASMOpExpressionF64::GetGlobal: - return parseGetGlobalExpression(context, WASMType::F64); - case WASMOpExpressionF64::SetLocal: - return parseSetLocal(context, WASMOpKind::Expression, WASMExpressionType::F64); - case WASMOpExpressionF64::SetGlobal: - return parseSetGlobal(context, WASMOpKind::Expression, WASMExpressionType::F64); - case WASMOpExpressionF64::Load: - return parseLoad(context, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::NoOffset); - case WASMOpExpressionF64::LoadWithOffset: - return parseLoad(context, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset); - case WASMOpExpressionF64::Store: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::NoOffset); - case WASMOpExpressionF64::StoreWithOffset: - return parseStore(context, WASMOpKind::Expression, WASMExpressionType::F64, WASMMemoryType::F64, MemoryAccessOffsetMode::WithOffset); - case WASMOpExpressionF64::CallInternal: - return parseCallInternal(context, WASMOpKind::Expression, WASMExpressionType::F64); - case WASMOpExpressionF64::CallImport: - return parseCallImport(context, WASMOpKind::Expression, WASMExpressionType::F64); - case WASMOpExpressionF64::CallIndirect: - return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::F64); - case WASMOpExpressionF64::Conditional: - return parseConditional(context, WASMExpressionType::F64); - case WASMOpExpressionF64::Comma: - return parseComma(context, WASMExpressionType::F64); - case WASMOpExpressionF64::FromS32: - return parseConvertType(context, WASMExpressionType::I32, WASMExpressionType::F64, WASMTypeConversion::ConvertSigned); - case WASMOpExpressionF64::FromU32: - return parseConvertType(context, WASMExpressionType::I32, WASMExpressionType::F64, WASMTypeConversion::ConvertUnsigned); - case WASMOpExpressionF64::FromF32: - return parseConvertType(context, WASMExpressionType::F32, WASMExpressionType::F64, WASMTypeConversion::Promote); - case WASMOpExpressionF64::Negate: - case WASMOpExpressionF64::Abs: - case WASMOpExpressionF64::Ceil: - case WASMOpExpressionF64::Floor: - case WASMOpExpressionF64::Sqrt: - case WASMOpExpressionF64::Cos: - case WASMOpExpressionF64::Sin: - case WASMOpExpressionF64::Tan: - case WASMOpExpressionF64::ACos: - case WASMOpExpressionF64::ASin: - case WASMOpExpressionF64::ATan: - case WASMOpExpressionF64::Exp: - case WASMOpExpressionF64::Ln: - return parseUnaryExpressionF64(context, op); - case WASMOpExpressionF64::Add: - case WASMOpExpressionF64::Sub: - case WASMOpExpressionF64::Mul: - case WASMOpExpressionF64::Div: - case WASMOpExpressionF64::Mod: - case WASMOpExpressionF64::ATan2: - case WASMOpExpressionF64::Pow: - return parseBinaryExpressionF64(context, op); - case WASMOpExpressionF64::Min: - case WASMOpExpressionF64::Max: - return parseMinOrMaxExpressionF64(context, op); - default: - ASSERT_NOT_REACHED(); - } - } else { - switch (opWithImmediate) { - case WASMOpExpressionF64WithImmediate::ConstantPoolIndex: - return parseConstantPoolIndexExpressionF64(context, immediate); - case WASMOpExpressionF64WithImmediate::GetLocal: - return parseGetLocalExpression(context, WASMType::F64, immediate); - default: - ASSERT_NOT_REACHED(); - } - } - return 0; -} - -template <class Context> -ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionF64(Context& context, uint32_t constantIndex) -{ - FAIL_IF_FALSE(constantIndex < m_module->f64Constants().size(), "The constant index is incorrect."); - return context.buildImmediateF64(m_module->f64Constants()[constantIndex]); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseConstantPoolIndexExpressionF64(Context& context) -{ - uint32_t constantIndex; - READ_COMPACT_UINT32_OR_FAIL(constantIndex, "Cannot read the constant index."); - return parseConstantPoolIndexExpressionF64(context, constantIndex); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseImmediateExpressionF64(Context& context) -{ - double immediate; - READ_DOUBLE_OR_FAIL(immediate, "Cannot read the immediate."); - return context.buildImmediateF64(immediate); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseUnaryExpressionF64(Context& context, WASMOpExpressionF64 op) -{ - ContextExpression expression = parseExpressionF64(context); - PROPAGATE_ERROR(); - return context.buildUnaryF64(expression, op); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseBinaryExpressionF64(Context& context, WASMOpExpressionF64 op) -{ - ContextExpression left = parseExpressionF64(context); - PROPAGATE_ERROR(); - ContextExpression right = parseExpressionF64(context); - PROPAGATE_ERROR(); - return context.buildBinaryF64(left, right, op); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseMinOrMaxExpressionF64(Context& context, WASMOpExpressionF64 op) -{ - uint32_t numberOfArguments; - READ_COMPACT_UINT32_OR_FAIL(numberOfArguments, "Cannot read the number of arguments to min/max."); - FAIL_IF_FALSE(numberOfArguments >= 2, "Min/max must be passed at least 2 arguments."); - ContextExpression current = parseExpressionF64(context); - PROPAGATE_ERROR(); - for (uint32_t i = 1; i < numberOfArguments; ++i) { - ContextExpression expression = parseExpressionF64(context); - PROPAGATE_ERROR(); - current = context.buildMinOrMaxF64(current, expression, op); - } - return current; -} - -template <class Context> -ContextExpression WASMFunctionParser::parseExpressionVoid(Context& context) -{ - WASMOpExpressionVoid op; - READ_OP_EXPRESSION_VOID_OR_FAIL(op, "Cannot read the void expression opcode."); - switch (op) { - case WASMOpExpressionVoid::CallInternal: - return parseCallInternal(context, WASMOpKind::Expression, WASMExpressionType::Void); - case WASMOpExpressionVoid::CallIndirect: - return parseCallIndirect(context, WASMOpKind::Expression, WASMExpressionType::Void); - case WASMOpExpressionVoid::CallImport: - return parseCallImport(context, WASMOpKind::Expression, WASMExpressionType::Void); - default: - RELEASE_ASSERT_NOT_REACHED(); - } -} - -template <class Context> -ContextExpression WASMFunctionParser::parseGetLocalExpression(Context& context, WASMType type, uint32_t localIndex) -{ - FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local index is incorrect."); - FAIL_IF_FALSE(m_localTypes[localIndex] == type, "Expected a local of type " + nameOfType(type) + '.'); - return context.buildGetLocal(localIndex, type); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseGetLocalExpression(Context& context, WASMType type) -{ - uint32_t localIndex; - READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index."); - return parseGetLocalExpression(context, type, localIndex); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseGetGlobalExpression(Context& context, WASMType type) -{ - uint32_t globalIndex; - READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index."); - FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect."); - FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == type, "Expected a global of type " + nameOfType(type) + '.'); - return context.buildGetGlobal(globalIndex, type); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseSetLocal(Context& context, WASMOpKind opKind, WASMExpressionType expressionType, uint32_t localIndex) -{ - FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local variable index is incorrect."); - WASMType type = m_localTypes[localIndex]; - if (opKind == WASMOpKind::Expression) - FAIL_IF_FALSE(expressionType == WASMExpressionType(type), "The type doesn't match."); - ContextExpression expression = parseExpression(context, WASMExpressionType(type)); - PROPAGATE_ERROR(); - return context.buildSetLocal(opKind, localIndex, expression, type); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseSetLocal(Context& context, WASMOpKind opKind, WASMExpressionType expressionType) -{ - uint32_t localIndex; - READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index."); - return parseSetLocal(context, opKind, expressionType, localIndex); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseSetGlobal(Context& context, WASMOpKind opKind, WASMExpressionType expressionType, uint32_t globalIndex) -{ - FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect."); - WASMType type = m_module->globalVariableTypes()[globalIndex]; - if (opKind == WASMOpKind::Expression) - FAIL_IF_FALSE(expressionType == WASMExpressionType(type), "The type doesn't match."); - ContextExpression expression = parseExpression(context, WASMExpressionType(type)); - PROPAGATE_ERROR(); - return context.buildSetGlobal(opKind, globalIndex, expression, type); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseSetGlobal(Context& context, WASMOpKind opKind, WASMExpressionType expressionType) -{ - uint32_t globalIndex; - READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index."); - return parseSetGlobal(context, opKind, expressionType, globalIndex); -} - -template <class Context> -ContextMemoryAddress WASMFunctionParser::parseMemoryAddress(Context& context, MemoryAccessOffsetMode offsetMode) -{ - uint32_t offset = 0; - if (offsetMode == MemoryAccessOffsetMode::WithOffset) - READ_COMPACT_UINT32_OR_FAIL(offset, "Cannot read the address offset."); - ContextExpression index = parseExpressionI32(context); - PROPAGATE_ERROR(); - return ContextMemoryAddress(index, offset); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseLoad(Context& context, WASMExpressionType expressionType, WASMMemoryType memoryType, MemoryAccessOffsetMode offsetMode, MemoryAccessConversion conversion) -{ - FAIL_IF_FALSE(m_module->arrayBuffer(), "An ArrayBuffer is not provided."); - const ContextMemoryAddress& memoryAddress = parseMemoryAddress(context, offsetMode); - PROPAGATE_ERROR(); - return context.buildLoad(memoryAddress, expressionType, memoryType, conversion); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseStore(Context& context, WASMOpKind opKind, WASMExpressionType expressionType, WASMMemoryType memoryType, MemoryAccessOffsetMode offsetMode) -{ - FAIL_IF_FALSE(m_module->arrayBuffer(), "An ArrayBuffer is not provided."); - const ContextMemoryAddress& memoryAddress = parseMemoryAddress(context, offsetMode); - PROPAGATE_ERROR(); - - ContextExpression value = parseExpression(context, expressionType); - PROPAGATE_ERROR(); - return context.buildStore(opKind, memoryAddress, expressionType, memoryType, value); -} - -template <class Context> -ContextExpressionList WASMFunctionParser::parseCallArguments(Context& context, const Vector<WASMType>& arguments) -{ - ContextExpressionList argumentList; - for (size_t i = 0; i < arguments.size(); ++i) { - ContextExpression expression = parseExpression(context, WASMExpressionType(arguments[i])); - PROPAGATE_ERROR(); - context.appendExpressionList(argumentList, expression); - } - return argumentList; -} - -template <class Context> -ContextExpression WASMFunctionParser::parseCallInternal(Context& context, WASMOpKind opKind, WASMExpressionType returnType) -{ - uint32_t functionIndex; - READ_COMPACT_UINT32_OR_FAIL(functionIndex, "Cannot read the function index."); - FAIL_IF_FALSE(functionIndex < m_module->functionDeclarations().size(), "The function index is incorrect."); - const WASMSignature& signature = m_module->signatures()[m_module->functionDeclarations()[functionIndex].signatureIndex]; - if (opKind == WASMOpKind::Expression) - FAIL_IF_FALSE(signature.returnType == returnType, "Wrong return type."); - - ContextExpressionList argumentList = parseCallArguments(context, signature.arguments); - PROPAGATE_ERROR(); - return context.buildCallInternal(functionIndex, argumentList, signature, returnType); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseCallIndirect(Context& context, WASMOpKind opKind, WASMExpressionType returnType) -{ - uint32_t functionPointerTableIndex; - READ_COMPACT_UINT32_OR_FAIL(functionPointerTableIndex, "Cannot read the function pointer table index."); - FAIL_IF_FALSE(functionPointerTableIndex < m_module->functionPointerTables().size(), "The function pointer table index is incorrect."); - const WASMFunctionPointerTable& functionPointerTable = m_module->functionPointerTables()[functionPointerTableIndex]; - const WASMSignature& signature = m_module->signatures()[functionPointerTable.signatureIndex]; - if (opKind == WASMOpKind::Expression) - FAIL_IF_FALSE(signature.returnType == returnType, "Wrong return type."); - - ContextExpression index = parseExpressionI32(context); - PROPAGATE_ERROR(); - - ContextExpressionList argumentList = parseCallArguments(context, signature.arguments); - PROPAGATE_ERROR(); - return context.buildCallIndirect(functionPointerTableIndex, index, argumentList, signature, returnType); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseCallImport(Context& context, WASMOpKind opKind, WASMExpressionType returnType) -{ - uint32_t functionImportSignatureIndex; - READ_COMPACT_UINT32_OR_FAIL(functionImportSignatureIndex, "Cannot read the function import signature index."); - FAIL_IF_FALSE(functionImportSignatureIndex < m_module->functionImportSignatures().size(), "The function import signature index is incorrect."); - const WASMFunctionImportSignature& functionImportSignature = m_module->functionImportSignatures()[functionImportSignatureIndex]; - const WASMSignature& signature = m_module->signatures()[functionImportSignature.signatureIndex]; - if (opKind == WASMOpKind::Expression) - FAIL_IF_FALSE(signature.returnType == returnType, "Wrong return type."); - - ContextExpressionList argumentList = parseCallArguments(context, signature.arguments); - PROPAGATE_ERROR(); - return context.buildCallImport(functionImportSignature.functionImportIndex, argumentList, signature, returnType); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseConditional(Context& context, WASMExpressionType expressionType) -{ - ContextJumpTarget elseTarget; - ContextJumpTarget end; - - ContextExpression condition = parseExpressionI32(context); - PROPAGATE_ERROR(); - - context.jumpToTargetIf(Context::JumpCondition::Zero, condition, elseTarget); - - parseExpression(context, expressionType); - PROPAGATE_ERROR(); - - context.jumpToTarget(end); - context.linkTarget(elseTarget); - - // We use discard() here to decrement the stack top in the baseline JIT. - context.discard(UNUSED); - parseExpression(context, expressionType); - PROPAGATE_ERROR(); - - context.linkTarget(end); - return UNUSED; -} - -template <class Context> -ContextExpression WASMFunctionParser::parseComma(Context& context, WASMExpressionType expressionType) -{ - WASMExpressionType leftExpressionType; - READ_EXPRESSION_TYPE_OR_FAIL(leftExpressionType, "Cannot read the expression type."); - ContextExpression leftExpression = parseExpression(context, leftExpressionType); - PROPAGATE_ERROR(); - if (leftExpressionType != WASMExpressionType::Void) - context.discard(leftExpression); - return parseExpression(context, expressionType); -} - -template <class Context> -ContextExpression WASMFunctionParser::parseConvertType(Context& context, WASMExpressionType fromType, WASMExpressionType toType, WASMTypeConversion conversion) -{ - ContextExpression expression = parseExpression(context, fromType); - PROPAGATE_ERROR(); - - return context.buildConvertType(expression, fromType, toType, conversion); -} - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) diff --git a/Source/JavaScriptCore/wasm/WASMFunctionParser.h b/Source/JavaScriptCore/wasm/WASMFunctionParser.h deleted file mode 100644 index 7f09e3e85..000000000 --- a/Source/JavaScriptCore/wasm/WASMFunctionParser.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WASMFunctionParser_h -#define WASMFunctionParser_h - -#if ENABLE(WEBASSEMBLY) - -#include "SourceCode.h" -#include "WASMReader.h" - -#define ContextExpression typename Context::Expression -#define ContextStatement typename Context::Statement -#define ContextExpressionList typename Context::ExpressionList -#define ContextMemoryAddress typename Context::MemoryAddress -#define ContextJumpTarget typename Context::JumpTarget - -namespace JSC { - -class CodeBlock; -class JSWASMModule; -class VM; - -class WASMFunctionParser { -public: - static bool checkSyntax(JSWASMModule*, const SourceCode&, size_t functionIndex, unsigned startOffsetInSource, unsigned& endOffsetInSource, unsigned& stackHeight, String& errorMessage); - static void compile(VM&, CodeBlock*, JSWASMModule*, const SourceCode&, size_t functionIndex); - -private: - WASMFunctionParser(JSWASMModule* module, const SourceCode& source, size_t functionIndex) - : m_module(module) - , m_reader(static_cast<WebAssemblySourceProvider*>(source.provider())->data()) - , m_functionIndex(functionIndex) - , m_breakScopeDepth(0) - , m_continueScopeDepth(0) - , m_labelDepth(0) - { - } - - template <class Context> bool parseFunction(Context&); - bool parseLocalVariables(); - - template <class Context> ContextStatement parseStatement(Context&); - template <class Context> ContextStatement parseReturnStatement(Context&); - template <class Context> ContextStatement parseBlockStatement(Context&); - template <class Context> ContextStatement parseIfStatement(Context&); - template <class Context> ContextStatement parseIfElseStatement(Context&); - template <class Context> ContextStatement parseWhileStatement(Context&); - template <class Context> ContextStatement parseDoStatement(Context&); - template <class Context> ContextStatement parseLabelStatement(Context&); - template <class Context> ContextStatement parseBreakStatement(Context&); - template <class Context> ContextStatement parseBreakLabelStatement(Context&); - template <class Context> ContextStatement parseContinueStatement(Context&); - template <class Context> ContextStatement parseContinueLabelStatement(Context&); - template <class Context> ContextStatement parseSwitchStatement(Context&); - - template <class Context> ContextExpression parseExpression(Context&, WASMExpressionType); - - template <class Context> ContextExpression parseExpressionI32(Context&); - template <class Context> ContextExpression parseConstantPoolIndexExpressionI32(Context&, uint32_t constantPoolIndex); - template <class Context> ContextExpression parseConstantPoolIndexExpressionI32(Context&); - template <class Context> ContextExpression parseImmediateExpressionI32(Context&, uint32_t immediate); - template <class Context> ContextExpression parseImmediateExpressionI32(Context&); - template <class Context> ContextExpression parseUnaryExpressionI32(Context&, WASMOpExpressionI32); - template <class Context> ContextExpression parseBinaryExpressionI32(Context&, WASMOpExpressionI32); - template <class Context> ContextExpression parseRelationalI32ExpressionI32(Context&, WASMOpExpressionI32); - template <class Context> ContextExpression parseRelationalF32ExpressionI32(Context&, WASMOpExpressionI32); - template <class Context> ContextExpression parseRelationalF64ExpressionI32(Context&, WASMOpExpressionI32); - template <class Context> ContextExpression parseMinOrMaxExpressionI32(Context&, WASMOpExpressionI32); - - template <class Context> ContextExpression parseExpressionF32(Context&); - template <class Context> ContextExpression parseConstantPoolIndexExpressionF32(Context&, uint32_t constantIndex); - template <class Context> ContextExpression parseConstantPoolIndexExpressionF32(Context&); - template <class Context> ContextExpression parseImmediateExpressionF32(Context&); - template <class Context> ContextExpression parseUnaryExpressionF32(Context&, WASMOpExpressionF32); - template <class Context> ContextExpression parseBinaryExpressionF32(Context&, WASMOpExpressionF32); - - template <class Context> ContextExpression parseExpressionF64(Context&); - template <class Context> ContextExpression parseConstantPoolIndexExpressionF64(Context&, uint32_t constantIndex); - template <class Context> ContextExpression parseConstantPoolIndexExpressionF64(Context&); - template <class Context> ContextExpression parseImmediateExpressionF64(Context&); - template <class Context> ContextExpression parseUnaryExpressionF64(Context&, WASMOpExpressionF64); - template <class Context> ContextExpression parseBinaryExpressionF64(Context&, WASMOpExpressionF64); - template <class Context> ContextExpression parseMinOrMaxExpressionF64(Context&, WASMOpExpressionF64); - - template <class Context> ContextExpression parseExpressionVoid(Context&); - - template <class Context> ContextExpression parseGetLocalExpression(Context&, WASMType, uint32_t localIndex); - template <class Context> ContextExpression parseGetLocalExpression(Context&, WASMType); - template <class Context> ContextExpression parseGetGlobalExpression(Context&, WASMType); - template <class Context> ContextExpression parseSetLocal(Context&, WASMOpKind, WASMExpressionType, uint32_t localIndex); - template <class Context> ContextExpression parseSetLocal(Context&, WASMOpKind, WASMExpressionType); - template <class Context> ContextExpression parseSetGlobal(Context&, WASMOpKind, WASMExpressionType, uint32_t globalIndex); - template <class Context> ContextExpression parseSetGlobal(Context&, WASMOpKind, WASMExpressionType); - template <class Context> ContextMemoryAddress parseMemoryAddress(Context&, MemoryAccessOffsetMode); - template <class Context> ContextExpression parseLoad(Context&, WASMExpressionType, WASMMemoryType, MemoryAccessOffsetMode, MemoryAccessConversion = MemoryAccessConversion::NoConversion); - template <class Context> ContextExpression parseStore(Context&, WASMOpKind, WASMExpressionType, WASMMemoryType, MemoryAccessOffsetMode); - template <class Context> ContextExpressionList parseCallArguments(Context&, const Vector<WASMType>& arguments); - template <class Context> ContextExpression parseCallInternal(Context&, WASMOpKind, WASMExpressionType returnType); - template <class Context> ContextExpression parseCallIndirect(Context&, WASMOpKind, WASMExpressionType returnType); - template <class Context> ContextExpression parseCallImport(Context&, WASMOpKind, WASMExpressionType returnType); - template <class Context> ContextExpression parseConditional(Context&, WASMExpressionType); - template <class Context> ContextExpression parseComma(Context&, WASMExpressionType); - template <class Context> ContextExpression parseConvertType(Context&, WASMExpressionType fromType, WASMExpressionType toType, WASMTypeConversion); - - JSWASMModule* m_module; - WASMReader m_reader; - size_t m_functionIndex; - String m_errorMessage; - - WASMExpressionType m_returnType; - Vector<WASMType> m_localTypes; - uint32_t m_numberOfI32LocalVariables; - uint32_t m_numberOfF32LocalVariables; - uint32_t m_numberOfF64LocalVariables; - - unsigned m_breakScopeDepth; - unsigned m_continueScopeDepth; - unsigned m_labelDepth; -}; - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) - -#endif // WASMFunctionParser_h diff --git a/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h b/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h deleted file mode 100644 index edfe42808..000000000 --- a/Source/JavaScriptCore/wasm/WASMFunctionSyntaxChecker.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WASMFunctionSyntaxChecker_h -#define WASMFunctionSyntaxChecker_h - -#if ENABLE(WEBASSEMBLY) - -#define UNUSED 0 - -namespace JSC { - -class WASMFunctionSyntaxChecker { -public: - typedef int Expression; - typedef int Statement; - typedef int ExpressionList; - struct MemoryAddress { - MemoryAddress(void*) { } - MemoryAddress(int, uint32_t) { } - }; - typedef int JumpTarget; - enum class JumpCondition { Zero, NonZero }; - - void startFunction(const Vector<WASMType>& arguments, uint32_t numberOfI32LocalVariables, uint32_t numberOfF32LocalVariables, uint32_t numberOfF64LocalVariables) - { - m_numberOfLocals = arguments.size() + numberOfI32LocalVariables + numberOfF32LocalVariables + numberOfF64LocalVariables; - } - - void endFunction() - { - ASSERT(!m_tempStackTop); - } - - int buildSetLocal(WASMOpKind opKind, uint32_t, int, WASMType) - { - if (opKind == WASMOpKind::Statement) - m_tempStackTop--; - return UNUSED; - } - - int buildSetGlobal(WASMOpKind opKind, uint32_t, int, WASMType) - { - if (opKind == WASMOpKind::Statement) - m_tempStackTop--; - return UNUSED; - } - - void buildReturn(int, WASMExpressionType returnType) - { - if (returnType != WASMExpressionType::Void) - m_tempStackTop--; - } - - int buildImmediateI32(uint32_t) - { - m_tempStackTop++; - updateTempStackHeight(); - return UNUSED; - } - - int buildImmediateF32(float) - { - m_tempStackTop++; - updateTempStackHeight(); - return UNUSED; - } - - int buildImmediateF64(double) - { - m_tempStackTop++; - updateTempStackHeight(); - return UNUSED; - } - - int buildGetLocal(uint32_t, WASMType) - { - m_tempStackTop++; - updateTempStackHeight(); - return UNUSED; - } - - int buildGetGlobal(uint32_t, WASMType) - { - m_tempStackTop++; - updateTempStackHeight(); - return UNUSED; - } - - int buildConvertType(int, WASMExpressionType, WASMExpressionType, WASMTypeConversion) - { - return UNUSED; - } - - int buildLoad(const MemoryAddress&, WASMExpressionType, WASMMemoryType, MemoryAccessConversion) - { - return UNUSED; - } - - int buildStore(WASMOpKind opKind, const MemoryAddress&, WASMExpressionType, WASMMemoryType, int) - { - m_tempStackTop -= 2; - if (opKind == WASMOpKind::Expression) - m_tempStackTop++; - return UNUSED; - } - - int buildUnaryI32(int, WASMOpExpressionI32) - { - return UNUSED; - } - - int buildUnaryF32(int, WASMOpExpressionF32) - { - return UNUSED; - } - - int buildUnaryF64(int, WASMOpExpressionF64) - { - return UNUSED; - } - - int buildBinaryI32(int, int, WASMOpExpressionI32) - { - m_tempStackTop--; - return UNUSED; - } - - int buildBinaryF32(int, int, WASMOpExpressionF32) - { - m_tempStackTop--; - return UNUSED; - } - - int buildBinaryF64(int, int, WASMOpExpressionF64) - { - m_tempStackTop--; - return UNUSED; - } - - int buildRelationalI32(int, int, WASMOpExpressionI32) - { - m_tempStackTop--; - return UNUSED; - } - - int buildRelationalF32(int, int, WASMOpExpressionI32) - { - m_tempStackTop--; - return UNUSED; - } - - int buildRelationalF64(int, int, WASMOpExpressionI32) - { - m_tempStackTop--; - return UNUSED; - } - - int buildMinOrMaxI32(int, int, WASMOpExpressionI32) - { - m_tempStackTop--; - return UNUSED; - } - - int buildMinOrMaxF64(int, int, WASMOpExpressionF64) - { - m_tempStackTop--; - return UNUSED; - } - - int buildCallInternal(uint32_t, int, const WASMSignature& signature, WASMExpressionType returnType) - { - size_t argumentCount = signature.arguments.size(); - updateTempStackHeightForCall(argumentCount); - m_tempStackTop -= argumentCount; - if (returnType != WASMExpressionType::Void) { - m_tempStackTop++; - updateTempStackHeight(); - } - return UNUSED; - } - - int buildCallImport(uint32_t, int, const WASMSignature& signature, WASMExpressionType returnType) - { - size_t argumentCount = signature.arguments.size(); - updateTempStackHeightForCall(argumentCount); - m_tempStackTop -= argumentCount; - if (returnType != WASMExpressionType::Void) { - m_tempStackTop++; - updateTempStackHeight(); - } - return UNUSED; - } - - int buildCallIndirect(uint32_t, int, int, const WASMSignature& signature, WASMExpressionType returnType) - { - size_t argumentCount = signature.arguments.size(); - updateTempStackHeightForCall(argumentCount); - m_tempStackTop -= argumentCount + 1; - if (returnType != WASMExpressionType::Void) - m_tempStackTop++; - return UNUSED; - } - - void appendExpressionList(int&, int) { } - - void discard(int) - { - m_tempStackTop--; - } - - void linkTarget(const int&) { } - void jumpToTarget(const int&) { } - void jumpToTargetIf(JumpCondition, int, const int&) - { - m_tempStackTop--; - } - - void startLoop() { } - void endLoop() { } - void startSwitch() { } - void endSwitch() { } - void startLabel() { } - void endLabel() { } - - int breakTarget() { return UNUSED; } - int continueTarget() { return UNUSED; } - int breakLabelTarget(uint32_t) { return UNUSED; } - int continueLabelTarget(uint32_t) { return UNUSED; } - - void buildSwitch(int, const Vector<int64_t>&, const Vector<int>&, const int&) - { - m_tempStackTop--; - } - - unsigned stackHeight() - { - return m_numberOfLocals + m_tempStackHeight; - } - -private: - void updateTempStackHeight() - { - if (m_tempStackTop > m_tempStackHeight) - m_tempStackHeight = m_tempStackTop; - } - - void updateTempStackHeightForCall(size_t argumentCount) - { - // Boxed arguments + this argument + call frame header + maximum padding. - m_tempStackTop += argumentCount + 1 + JSStack::CallFrameHeaderSize + 1; - updateTempStackHeight(); - m_tempStackTop -= argumentCount + 1 + JSStack::CallFrameHeaderSize + 1; - } - - unsigned m_numberOfLocals; - unsigned m_tempStackTop { 0 }; - unsigned m_tempStackHeight { 0 }; -}; - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) - -#endif // WASMFunctionSyntaxChecker_h diff --git a/Source/JavaScriptCore/wasm/WASMModuleParser.cpp b/Source/JavaScriptCore/wasm/WASMModuleParser.cpp deleted file mode 100644 index 8ce35f483..000000000 --- a/Source/JavaScriptCore/wasm/WASMModuleParser.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "WASMModuleParser.h" - -#if ENABLE(WEBASSEMBLY) - -#include "JSArrayBuffer.h" -#include "JSCInlines.h" -#include "JSWASMModule.h" -#include "StrongInlines.h" -#include "WASMConstants.h" -#include "WASMFunctionParser.h" -#include <wtf/MathExtras.h> - -#define FAIL_WITH_MESSAGE(errorMessage) do { m_errorMessage = errorMessage; return; } while (0) -#define READ_UINT32_OR_FAIL(result, errorMessage) do { if (!m_reader.readUInt32(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_FLOAT_OR_FAIL(result, errorMessage) do { if (!m_reader.readFloat(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_DOUBLE_OR_FAIL(result, errorMessage) do { if (!m_reader.readDouble(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_COMPACT_UINT32_OR_FAIL(result, errorMessage) do { if (!m_reader.readCompactUInt32(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_STRING_OR_FAIL(result, errorMessage) do { if (!m_reader.readString(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_TYPE_OR_FAIL(result, errorMessage) do { if (!m_reader.readType(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_EXPRESSION_TYPE_OR_FAIL(result, errorMessage) do { if (!m_reader.readExpressionType(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define READ_EXPORT_FORMAT_OR_FAIL(result, errorMessage) do { if (!m_reader.readExportFormat(result)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define FAIL_IF_FALSE(condition, errorMessage) do { if (!(condition)) FAIL_WITH_MESSAGE(errorMessage); } while (0) -#define PROPAGATE_ERROR() do { if (!m_errorMessage.isNull()) return; } while (0) - -namespace JSC { - -WASMModuleParser::WASMModuleParser(VM& vm, JSGlobalObject* globalObject, const SourceCode& source, JSObject* imports, JSArrayBuffer* arrayBuffer) - : m_vm(vm) - , m_globalObject(vm, globalObject) - , m_source(source) - , m_imports(vm, imports) - , m_reader(static_cast<WebAssemblySourceProvider*>(source.provider())->data()) - , m_module(vm, JSWASMModule::create(vm, globalObject->wasmModuleStructure(), arrayBuffer)) -{ -} - -JSWASMModule* WASMModuleParser::parse(ExecState* exec, String& errorMessage) -{ - parseModule(exec); - if (!m_errorMessage.isNull()) { - errorMessage = m_errorMessage; - return nullptr; - } - return m_module.get(); -} - -void WASMModuleParser::parseModule(ExecState* exec) -{ - uint32_t magicNumber; - READ_UINT32_OR_FAIL(magicNumber, "Cannot read the magic number."); - FAIL_IF_FALSE(magicNumber == wasmMagicNumber, "The magic number is incorrect."); - - uint32_t outputSizeInASMJS; - READ_UINT32_OR_FAIL(outputSizeInASMJS, "Cannot read the output size in asm.js format."); - - parseConstantPoolSection(); - PROPAGATE_ERROR(); - parseSignatureSection(); - PROPAGATE_ERROR(); - parseFunctionImportSection(exec); - PROPAGATE_ERROR(); - parseGlobalSection(exec); - PROPAGATE_ERROR(); - parseFunctionDeclarationSection(); - PROPAGATE_ERROR(); - parseFunctionPointerTableSection(); - PROPAGATE_ERROR(); - parseFunctionDefinitionSection(); - PROPAGATE_ERROR(); - parseExportSection(); - PROPAGATE_ERROR(); - - FAIL_IF_FALSE(!m_module->arrayBuffer() || m_module->arrayBuffer()->impl()->byteLength() < (1u << 31), "The ArrayBuffer's length must be less than 2^31."); -} - -void WASMModuleParser::parseConstantPoolSection() -{ - uint32_t numberOfI32Constants; - uint32_t numberOfF32Constants; - uint32_t numberOfF64Constants; - READ_COMPACT_UINT32_OR_FAIL(numberOfI32Constants, "Cannot read the number of int32 constants."); - READ_COMPACT_UINT32_OR_FAIL(numberOfF32Constants, "Cannot read the number of float32 constants."); - READ_COMPACT_UINT32_OR_FAIL(numberOfF64Constants, "Cannot read the number of float64 constants."); - m_module->i32Constants().reserveInitialCapacity(numberOfI32Constants); - m_module->f32Constants().reserveInitialCapacity(numberOfF32Constants); - m_module->f64Constants().reserveInitialCapacity(numberOfF64Constants); - - for (uint32_t i = 0; i < numberOfI32Constants; ++i) { - uint32_t constant; - READ_COMPACT_UINT32_OR_FAIL(constant, "Cannot read an int32 constant."); - m_module->i32Constants().uncheckedAppend(constant); - } - for (uint32_t i = 0; i < numberOfF32Constants; ++i) { - float constant; - READ_FLOAT_OR_FAIL(constant, "Cannot read a float32 constant."); - m_module->f32Constants().uncheckedAppend(constant); - } - for (uint32_t i = 0; i < numberOfF64Constants; ++i) { - double constant; - READ_DOUBLE_OR_FAIL(constant, "Cannot read a float64 constant."); - m_module->f64Constants().uncheckedAppend(constant); - } -} - -void WASMModuleParser::parseSignatureSection() -{ - uint32_t numberOfSignatures; - READ_COMPACT_UINT32_OR_FAIL(numberOfSignatures, "Cannot read the number of signatures."); - m_module->signatures().reserveInitialCapacity(numberOfSignatures); - for (uint32_t signatureIndex = 0; signatureIndex < numberOfSignatures; ++signatureIndex) { - WASMSignature signature; - READ_EXPRESSION_TYPE_OR_FAIL(signature.returnType, "Cannot read the return type."); - uint32_t argumentCount; - READ_COMPACT_UINT32_OR_FAIL(argumentCount, "Cannot read the number of arguments."); - signature.arguments.reserveInitialCapacity(argumentCount); - for (uint32_t argumentIndex = 0; argumentIndex < argumentCount; ++argumentIndex) { - WASMType type; - READ_TYPE_OR_FAIL(type, "Cannot read the type of an argument."); - signature.arguments.uncheckedAppend(type); - } - m_module->signatures().uncheckedAppend(signature); - } -} - -void WASMModuleParser::parseFunctionImportSection(ExecState* exec) -{ - uint32_t numberOfFunctionImports; - uint32_t numberOfFunctionImportSignatures; - READ_COMPACT_UINT32_OR_FAIL(numberOfFunctionImports, "Cannot read the number of function imports."); - READ_COMPACT_UINT32_OR_FAIL(numberOfFunctionImportSignatures, "Cannot read the number of function import signatures."); - m_module->functionImports().reserveInitialCapacity(numberOfFunctionImports); - m_module->functionImportSignatures().reserveInitialCapacity(numberOfFunctionImportSignatures); - m_module->importedFunctions().reserveInitialCapacity(numberOfFunctionImports); - - for (uint32_t functionImportIndex = 0; functionImportIndex < numberOfFunctionImports; ++functionImportIndex) { - WASMFunctionImport functionImport; - READ_STRING_OR_FAIL(functionImport.functionName, "Cannot read the function import name."); - m_module->functionImports().uncheckedAppend(functionImport); - - uint32_t numberOfSignatures; - READ_COMPACT_UINT32_OR_FAIL(numberOfSignatures, "Cannot read the number of signatures."); - FAIL_IF_FALSE(numberOfSignatures <= numberOfFunctionImportSignatures - m_module->functionImportSignatures().size(), "The number of signatures is incorrect."); - - for (uint32_t i = 0; i < numberOfSignatures; ++i) { - WASMFunctionImportSignature functionImportSignature; - READ_COMPACT_UINT32_OR_FAIL(functionImportSignature.signatureIndex, "Cannot read the signature index."); - FAIL_IF_FALSE(functionImportSignature.signatureIndex < m_module->signatures().size(), "The signature index is incorrect."); - functionImportSignature.functionImportIndex = functionImportIndex; - m_module->functionImportSignatures().uncheckedAppend(functionImportSignature); - } - - JSValue value; - getImportedValue(exec, functionImport.functionName, value); - PROPAGATE_ERROR(); - FAIL_IF_FALSE(value.isFunction(), "\"" + functionImport.functionName + "\" is not a function."); - JSFunction* function = jsCast<JSFunction*>(value.asCell()); - m_module->importedFunctions().uncheckedAppend(WriteBarrier<JSFunction>(m_vm, m_module.get(), function)); - } - FAIL_IF_FALSE(m_module->functionImportSignatures().size() == numberOfFunctionImportSignatures, "The number of function import signatures is incorrect."); -} - -void WASMModuleParser::parseGlobalSection(ExecState* exec) -{ - uint32_t numberOfInternalI32GlobalVariables; - uint32_t numberOfInternalF32GlobalVariables; - uint32_t numberOfInternalF64GlobalVariables; - uint32_t numberOfImportedI32GlobalVariables; - uint32_t numberOfImportedF32GlobalVariables; - uint32_t numberOfImportedF64GlobalVariables; - READ_COMPACT_UINT32_OR_FAIL(numberOfInternalI32GlobalVariables, "Cannot read the number of internal int32 global variables."); - READ_COMPACT_UINT32_OR_FAIL(numberOfInternalF32GlobalVariables, "Cannot read the number of internal float32 global variables."); - READ_COMPACT_UINT32_OR_FAIL(numberOfInternalF64GlobalVariables, "Cannot read the number of internal float64 global variables."); - READ_COMPACT_UINT32_OR_FAIL(numberOfImportedI32GlobalVariables, "Cannot read the number of imported int32 global variables."); - READ_COMPACT_UINT32_OR_FAIL(numberOfImportedF32GlobalVariables, "Cannot read the number of imported float32 global variables."); - READ_COMPACT_UINT32_OR_FAIL(numberOfImportedF64GlobalVariables, "Cannot read the number of imported float64 global variables."); - uint32_t numberOfGlobalVariables = numberOfInternalI32GlobalVariables + numberOfInternalF32GlobalVariables + numberOfInternalF64GlobalVariables + - numberOfImportedI32GlobalVariables + numberOfImportedF32GlobalVariables + numberOfImportedF64GlobalVariables; - - Vector<WASMType>& globalVariableTypes = m_module->globalVariableTypes(); - globalVariableTypes.reserveInitialCapacity(numberOfGlobalVariables); - Vector<JSWASMModule::GlobalVariable>& globalVariables = m_module->globalVariables(); - globalVariables.reserveInitialCapacity(numberOfGlobalVariables); - for (uint32_t i = 0; i < numberOfInternalI32GlobalVariables; ++i) { - globalVariableTypes.uncheckedAppend(WASMType::I32); - globalVariables.uncheckedAppend(JSWASMModule::GlobalVariable(0)); - } - for (uint32_t i = 0; i < numberOfInternalF32GlobalVariables; ++i) { - globalVariableTypes.uncheckedAppend(WASMType::F32); - globalVariables.uncheckedAppend(JSWASMModule::GlobalVariable(0.0f)); - } - for (uint32_t i = 0; i < numberOfInternalF64GlobalVariables; ++i) { - globalVariableTypes.uncheckedAppend(WASMType::F64); - globalVariables.uncheckedAppend(JSWASMModule::GlobalVariable(0.0)); - } - for (uint32_t i = 0; i < numberOfImportedI32GlobalVariables; ++i) { - String importName; - READ_STRING_OR_FAIL(importName, "Cannot read the import name of an int32 global variable."); - globalVariableTypes.uncheckedAppend(WASMType::I32); - JSValue value; - getImportedValue(exec, importName, value); - PROPAGATE_ERROR(); - FAIL_IF_FALSE(value.isPrimitive() && !value.isSymbol(), "\"" + importName + "\" is not a primitive or is a Symbol."); - globalVariables.uncheckedAppend(JSWASMModule::GlobalVariable(value.toInt32(exec))); - } - for (uint32_t i = 0; i < numberOfImportedF32GlobalVariables; ++i) { - String importName; - READ_STRING_OR_FAIL(importName, "Cannot read the import name of a float32 global variable."); - globalVariableTypes.uncheckedAppend(WASMType::F32); - JSValue value; - getImportedValue(exec, importName, value); - PROPAGATE_ERROR(); - FAIL_IF_FALSE(value.isPrimitive() && !value.isSymbol(), "\"" + importName + "\" is not a primitive or is a Symbol."); - globalVariables.uncheckedAppend(JSWASMModule::GlobalVariable(static_cast<float>(value.toNumber(exec)))); - } - for (uint32_t i = 0; i < numberOfImportedF64GlobalVariables; ++i) { - String importName; - READ_STRING_OR_FAIL(importName, "Cannot read the import name of a float64 global variable."); - globalVariableTypes.uncheckedAppend(WASMType::F64); - JSValue value; - getImportedValue(exec, importName, value); - PROPAGATE_ERROR(); - FAIL_IF_FALSE(value.isPrimitive() && !value.isSymbol(), "\"" + importName + "\" is not a primitive or is a Symbol."); - globalVariables.uncheckedAppend(JSWASMModule::GlobalVariable(value.toNumber(exec))); - } -} - -void WASMModuleParser::parseFunctionDeclarationSection() -{ - uint32_t numberOfFunctionDeclarations; - READ_COMPACT_UINT32_OR_FAIL(numberOfFunctionDeclarations, "Cannot read the number of function declarations."); - m_module->functionDeclarations().reserveInitialCapacity(numberOfFunctionDeclarations); - m_module->functions().reserveInitialCapacity(numberOfFunctionDeclarations); - m_module->functionStartOffsetsInSource().reserveInitialCapacity(numberOfFunctionDeclarations); - m_module->functionStackHeights().reserveInitialCapacity(numberOfFunctionDeclarations); - for (uint32_t i = 0; i < numberOfFunctionDeclarations; ++i) { - WASMFunctionDeclaration functionDeclaration; - READ_COMPACT_UINT32_OR_FAIL(functionDeclaration.signatureIndex, "Cannot read the signature index."); - FAIL_IF_FALSE(functionDeclaration.signatureIndex < m_module->signatures().size(), "The signature index is incorrect."); - m_module->functionDeclarations().uncheckedAppend(functionDeclaration); - } -} - -void WASMModuleParser::parseFunctionPointerTableSection() -{ - uint32_t numberOfFunctionPointerTables; - READ_COMPACT_UINT32_OR_FAIL(numberOfFunctionPointerTables, "Cannot read the number of function pointer tables."); - m_module->functionPointerTables().reserveInitialCapacity(numberOfFunctionPointerTables); - for (uint32_t i = 0; i < numberOfFunctionPointerTables; ++i) { - WASMFunctionPointerTable functionPointerTable; - READ_COMPACT_UINT32_OR_FAIL(functionPointerTable.signatureIndex, "Cannot read the signature index."); - FAIL_IF_FALSE(functionPointerTable.signatureIndex < m_module->signatures().size(), "The signature index is incorrect."); - uint32_t numberOfFunctions; - READ_COMPACT_UINT32_OR_FAIL(numberOfFunctions, "Cannot read the number of functions of a function pointer table."); - FAIL_IF_FALSE(hasOneBitSet(numberOfFunctions), "The number of functions must be a power of two."); - functionPointerTable.functionIndices.reserveInitialCapacity(numberOfFunctions); - functionPointerTable.functions.reserveInitialCapacity(numberOfFunctions); - for (uint32_t j = 0; j < numberOfFunctions; ++j) { - uint32_t functionIndex; - READ_COMPACT_UINT32_OR_FAIL(functionIndex, "Cannot read a function index of a function pointer table."); - FAIL_IF_FALSE(functionIndex < m_module->functionDeclarations().size(), "The function index is incorrect."); - FAIL_IF_FALSE(m_module->functionDeclarations()[functionIndex].signatureIndex == functionPointerTable.signatureIndex, "The signature of the function doesn't match that of the function pointer table."); - functionPointerTable.functionIndices.uncheckedAppend(functionIndex); - } - m_module->functionPointerTables().uncheckedAppend(functionPointerTable); - } -} - -void WASMModuleParser::parseFunctionDefinitionSection() -{ - for (size_t functionIndex = 0; functionIndex < m_module->functionDeclarations().size(); ++functionIndex) { - parseFunctionDefinition(functionIndex); - PROPAGATE_ERROR(); - } - - for (WASMFunctionPointerTable& functionPointerTable : m_module->functionPointerTables()) { - for (size_t i = 0; i < functionPointerTable.functionIndices.size(); ++i) - functionPointerTable.functions.uncheckedAppend(m_module->functions()[functionPointerTable.functionIndices[i]].get()); - } -} - -void WASMModuleParser::parseFunctionDefinition(size_t functionIndex) -{ - unsigned startOffsetInSource = m_reader.offset(); - unsigned endOffsetInSource; - unsigned stackHeight; - String errorMessage; - if (!WASMFunctionParser::checkSyntax(m_module.get(), m_source, functionIndex, startOffsetInSource, endOffsetInSource, stackHeight, errorMessage)) { - m_errorMessage = errorMessage; - return; - } - m_reader.setOffset(endOffsetInSource); - - WebAssemblyExecutable* webAssemblyExecutable = WebAssemblyExecutable::create(m_vm, m_source, m_module.get(), functionIndex); - JSFunction* function = JSFunction::create(m_vm, webAssemblyExecutable, m_globalObject.get()); - m_module->functions().uncheckedAppend(WriteBarrier<JSFunction>(m_vm, m_module.get(), function)); - m_module->functionStartOffsetsInSource().uncheckedAppend(startOffsetInSource); - m_module->functionStackHeights().uncheckedAppend(stackHeight); -} - -void WASMModuleParser::parseExportSection() -{ - WASMExportFormat exportFormat; - READ_EXPORT_FORMAT_OR_FAIL(exportFormat, "Cannot read the export format."); - switch (exportFormat) { - case WASMExportFormat::Default: { - uint32_t functionIndex; - READ_COMPACT_UINT32_OR_FAIL(functionIndex, "Cannot read the function index."); - FAIL_IF_FALSE(functionIndex < m_module->functionDeclarations().size(), "The function index is incorrect."); - // FIXME: Export the function. - break; - } - case WASMExportFormat::Record: { - uint32_t numberOfExports; - READ_COMPACT_UINT32_OR_FAIL(numberOfExports, "Cannot read the number of exports."); - for (uint32_t exportIndex = 0; exportIndex < numberOfExports; ++exportIndex) { - String exportName; - READ_STRING_OR_FAIL(exportName, "Cannot read the function export name."); - uint32_t functionIndex; - READ_COMPACT_UINT32_OR_FAIL(functionIndex, "Cannot read the function index."); - FAIL_IF_FALSE(functionIndex < m_module->functionDeclarations().size(), "The function index is incorrect."); - Identifier identifier = Identifier::fromString(&m_vm, exportName); - m_module->putDirect(m_vm, identifier, m_module->functions()[functionIndex].get()); - } - break; - } - default: - ASSERT_NOT_REACHED(); - } -} - -void WASMModuleParser::getImportedValue(ExecState* exec, const String& importName, JSValue& value) -{ - FAIL_IF_FALSE(m_imports, "Accessing property of non-object."); - Identifier identifier = Identifier::fromString(&m_vm, importName); - PropertySlot slot(m_imports.get(), PropertySlot::InternalMethodType::Get); - if (!m_imports->getPropertySlot(exec, identifier, slot)) - FAIL_WITH_MESSAGE("Can't find a property named \"" + importName + '"'); - FAIL_IF_FALSE(slot.isValue(), "\"" + importName + "\" is not a data property."); - // We only retrieve data properties. So, this does not cause any user-observable effect. - value = slot.getValue(exec, identifier); -} - -JSWASMModule* parseWebAssembly(ExecState* exec, const SourceCode& source, JSObject* imports, JSArrayBuffer* arrayBuffer, String& errorMessage) -{ - WASMModuleParser moduleParser(exec->vm(), exec->lexicalGlobalObject(), source, imports, arrayBuffer); - return moduleParser.parse(exec, errorMessage); -} - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) diff --git a/Source/JavaScriptCore/wasm/WASMModuleParser.h b/Source/JavaScriptCore/wasm/WASMModuleParser.h deleted file mode 100644 index 5017bc1ce..000000000 --- a/Source/JavaScriptCore/wasm/WASMModuleParser.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WASMModuleParser_h -#define WASMModuleParser_h - -#if ENABLE(WEBASSEMBLY) - -#include "Strong.h" -#include "WASMReader.h" -#include <wtf/text/WTFString.h> - -namespace JSC { - -class ExecState; -class JSArrayBuffer; -class JSGlobalObject; -class JSWASMModule; -class SourceCode; -class VM; - -class WASMModuleParser { -public: - WASMModuleParser(VM&, JSGlobalObject*, const SourceCode&, JSObject* imports, JSArrayBuffer*); - JSWASMModule* parse(ExecState*, String& errorMessage); - -private: - void parseModule(ExecState*); - void parseConstantPoolSection(); - void parseSignatureSection(); - void parseFunctionImportSection(ExecState*); - void parseGlobalSection(ExecState*); - void parseFunctionDeclarationSection(); - void parseFunctionPointerTableSection(); - void parseFunctionDefinitionSection(); - void parseFunctionDefinition(size_t functionIndex); - void parseExportSection(); - void getImportedValue(ExecState*, const String& importName, JSValue&); - - VM& m_vm; - Strong<JSGlobalObject> m_globalObject; - const SourceCode& m_source; - Strong<JSObject> m_imports; - WASMReader m_reader; - Strong<JSWASMModule> m_module; - String m_errorMessage; -}; - -JS_EXPORT_PRIVATE JSWASMModule* parseWebAssembly(ExecState*, const SourceCode&, JSObject* imports, JSArrayBuffer*, String& errorMessage); - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) - -#endif // WASMModuleParser_h diff --git a/Source/JavaScriptCore/wasm/WASMReader.cpp b/Source/JavaScriptCore/wasm/WASMReader.cpp deleted file mode 100644 index f6ac8e2fc..000000000 --- a/Source/JavaScriptCore/wasm/WASMReader.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ========================================================================= - * - * Copyright (c) 2015 by the repository authors of - * WebAssembly/polyfill-prototype-1. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "config.h" -#include "WASMReader.h" - -#if ENABLE(WEBASSEMBLY) - -#include <wtf/text/StringBuilder.h> - -#define CHECK_READ(length) do { if (m_cursor + length > m_buffer.end()) return false; } while (0) - -namespace JSC { - -bool WASMReader::readUInt32(uint32_t& result) -{ - CHECK_READ(4); - result = m_cursor[0] | m_cursor[1] << 8 | m_cursor[2] << 16 | m_cursor[3] << 24; - m_cursor += 4; - return true; -} - -bool WASMReader::readFloat(float& result) -{ - CHECK_READ(4); - union { - uint8_t bytes[4]; - float floatValue; - } u = { -#if CPU(BIG_ENDIAN) - { m_cursor[3], m_cursor[2], m_cursor[1], m_cursor[0] } -#else - { m_cursor[0], m_cursor[1], m_cursor[2], m_cursor[3] } -#endif - }; - result = u.floatValue; - m_cursor += 4; - return true; -} - -bool WASMReader::readDouble(double& result) -{ - CHECK_READ(8); - union { - uint8_t bytes[8]; - double doubleValue; - } u = { -#if CPU(BIG_ENDIAN) - { m_cursor[7], m_cursor[6], m_cursor[5], m_cursor[4], m_cursor[3], m_cursor[2], m_cursor[1], m_cursor[0] } -#else - { m_cursor[0], m_cursor[1], m_cursor[2], m_cursor[3], m_cursor[4], m_cursor[5], m_cursor[6], m_cursor[7] } -#endif - }; - result = u.doubleValue; - m_cursor += 8; - return true; -} - -bool WASMReader::readCompactInt32(uint32_t& result) -{ - uint32_t sum = 0; - unsigned shift = 0; - do { - CHECK_READ(1); - uint8_t byte = *m_cursor++; - if (byte < 0x80) { - sum |= byte << shift; - int signExtend = (32 - 7) - shift; - if (signExtend > 0) - result = int32_t(sum) << signExtend >> signExtend; - else - result = int32_t(sum); - return true; - } - sum |= (byte & firstSevenBitsMask) << shift; - shift += 7; - } while (shift < 35); - return false; -} - -bool WASMReader::readCompactUInt32(uint32_t& result) -{ - uint32_t sum = 0; - unsigned shift = 0; - do { - CHECK_READ(1); - uint32_t byte = *m_cursor++; - if (byte < 0x80) { - if ((shift == 28 && byte >= 0x10) || (shift && !byte)) - return false; - result = sum | (byte << shift); - return true; - } - sum |= (byte & firstSevenBitsMask) << shift; - shift += 7; - } while (shift < 35); - return false; -} - -bool WASMReader::readString(String& result) -{ - StringBuilder builder; - while (true) { - CHECK_READ(1); - char c = *m_cursor++; - if (!c) - break; - builder.append(c); - } - result = builder.toString(); - return true; -} - -bool WASMReader::readType(WASMType& result) -{ - return readByte<WASMType>(result, static_cast<uint8_t>(WASMType::NumberOfTypes)); -} - -bool WASMReader::readExpressionType(WASMExpressionType& result) -{ - return readByte<WASMExpressionType>(result, static_cast<uint8_t>(WASMExpressionType::NumberOfExpressionTypes)); -} - -bool WASMReader::readExportFormat(WASMExportFormat& result) -{ - return readByte<WASMExportFormat>(result, static_cast<uint8_t>(WASMExportFormat::NumberOfExportFormats)); -} - -template <class T> bool WASMReader::readByte(T& result, uint8_t numberOfValues) -{ - CHECK_READ(1); - uint8_t byte = *m_cursor++; - if (byte >= numberOfValues) - return false; - result = T(byte); - return true; -} - -bool WASMReader::readOpStatement(bool& hasImmediate, WASMOpStatement& op, WASMOpStatementWithImmediate& opWithImmediate, uint8_t& immediate) -{ - return readOp(hasImmediate, op, opWithImmediate, immediate, - static_cast<uint8_t>(WASMOpStatement::NumberOfWASMOpStatements), - static_cast<uint8_t>(WASMOpStatementWithImmediate::NumberOfWASMOpStatementWithImmediates)); -} - -bool WASMReader::readOpExpressionI32(bool& hasImmediate, WASMOpExpressionI32& op, WASMOpExpressionI32WithImmediate& opWithImmediate, uint8_t& immediate) -{ - return readOp(hasImmediate, op, opWithImmediate, immediate, - static_cast<uint8_t>(WASMOpExpressionI32::NumberOfWASMOpExpressionI32s), - static_cast<uint8_t>(WASMOpExpressionI32WithImmediate::NumberOfWASMOpExpressionI32WithImmediates)); -} - -bool WASMReader::readOpExpressionF32(bool& hasImmediate, WASMOpExpressionF32& op, WASMOpExpressionF32WithImmediate& opWithImmediate, uint8_t& immediate) -{ - return readOp(hasImmediate, op, opWithImmediate, immediate, - static_cast<uint8_t>(WASMOpExpressionF32::NumberOfWASMOpExpressionF32s), - static_cast<uint8_t>(WASMOpExpressionF32WithImmediate::NumberOfWASMOpExpressionF32WithImmediates)); -} - -bool WASMReader::readOpExpressionF64(bool& hasImmediate, WASMOpExpressionF64& op, WASMOpExpressionF64WithImmediate& opWithImmediate, uint8_t& immediate) -{ - return readOp(hasImmediate, op, opWithImmediate, immediate, - static_cast<uint8_t>(WASMOpExpressionF64::NumberOfWASMOpExpressionF64s), - static_cast<uint8_t>(WASMOpExpressionF64WithImmediate::NumberOfWASMOpExpressionF64WithImmediates)); -} - -bool WASMReader::readOpExpressionVoid(WASMOpExpressionVoid& op) -{ - return readByte<WASMOpExpressionVoid>(op, - static_cast<uint8_t>(WASMOpExpressionVoid::NumberOfWASMOpExpressionVoids)); -} - -bool WASMReader::readVariableTypes(bool& hasImmediate, WASMVariableTypes& variableTypes, WASMVariableTypesWithImmediate& variableTypesWithImmediate, uint8_t& immediate) -{ - return readOp(hasImmediate, variableTypes, variableTypesWithImmediate, immediate, - static_cast<uint8_t>(WASMVariableTypes::NumberOfVariableTypes), - static_cast<uint8_t>(WASMVariableTypesWithImmediate::NumberOfVariableTypesWithImmediates)); -} - -template <class T, class TWithImmediate> -bool WASMReader::readOp(bool& hasImmediate, T& op, TWithImmediate& opWithImmediate, uint8_t& immediate, uint8_t numberOfValues, uint8_t numberOfValuesWithImmediate) -{ - CHECK_READ(1); - uint8_t byte = *m_cursor++; - - if (!(byte & hasImmediateInOpFlag)) { - if (byte >= numberOfValues) - return false; - hasImmediate = false; - op = T(byte); - return true; - } - - uint8_t byteWithoutImmediate = (byte >> immediateBits) & (opWithImmediateLimit - 1); - if (byteWithoutImmediate >= numberOfValuesWithImmediate) - return false; - hasImmediate = true; - opWithImmediate = TWithImmediate(byteWithoutImmediate); - immediate = byte & (immediateLimit - 1); - return true; -} - -bool WASMReader::readSwitchCase(WASMSwitchCase& result) -{ - return readByte<WASMSwitchCase>(result, static_cast<uint8_t>(WASMSwitchCase::NumberOfSwitchCases)); -} - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) diff --git a/Source/JavaScriptCore/wasm/WASMReader.h b/Source/JavaScriptCore/wasm/WASMReader.h deleted file mode 100644 index 83dc29681..000000000 --- a/Source/JavaScriptCore/wasm/WASMReader.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WASMReader_h -#define WASMReader_h - -#if ENABLE(WEBASSEMBLY) - -#include "WASMConstants.h" -#include "WASMFormat.h" -#include <wtf/Vector.h> - -namespace JSC { - -class WASMReader { -public: - WASMReader(const Vector<uint8_t>& buffer) - : m_buffer(buffer) - , m_cursor(buffer.data()) - { - } - - unsigned offset() const { return m_cursor - m_buffer.data(); } - void setOffset(unsigned offset) { m_cursor = m_buffer.data() + offset; } - - bool readUInt32(uint32_t& result); - bool readFloat(float& result); - bool readDouble(double& result); - bool readCompactInt32(uint32_t& result); - bool readCompactUInt32(uint32_t& result); - bool readString(String& result); - bool readType(WASMType& result); - bool readExpressionType(WASMExpressionType& result); - bool readExportFormat(WASMExportFormat& result); - bool readOpStatement(bool& hasImmediate, WASMOpStatement&, WASMOpStatementWithImmediate&, uint8_t& immediate); - bool readOpExpressionI32(bool& hasImmediate, WASMOpExpressionI32&, WASMOpExpressionI32WithImmediate&, uint8_t& immediate); - bool readOpExpressionF32(bool& hasImmediate, WASMOpExpressionF32&, WASMOpExpressionF32WithImmediate&, uint8_t& immediate); - bool readOpExpressionF64(bool& hasImmediate, WASMOpExpressionF64&, WASMOpExpressionF64WithImmediate&, uint8_t& immediate); - bool readOpExpressionVoid(WASMOpExpressionVoid&); - bool readVariableTypes(bool& hasImmediate, WASMVariableTypes&, WASMVariableTypesWithImmediate&, uint8_t& immediate); - bool readSwitchCase(WASMSwitchCase& result); - -private: - static const uint32_t firstSevenBitsMask = 0x7f; - - template <class T> bool readByte(T& result, uint8_t numberOfValues); - template <class T, class TWithImmediate> bool readOp(bool& hasImmediate, T&, TWithImmediate&, uint8_t& immediate, uint8_t numberOfValues, uint8_t numberOfValuesWithImmediate); - - const Vector<uint8_t>& m_buffer; - const uint8_t* m_cursor; -}; - -} // namespace JSC - -#endif // ENABLE(WEBASSEMBLY) - -#endif // WASMReader_h |
