Source/JavaScriptCore/ChangeLog

 12015-08-05 Sukolsak Sakshuwong <sukolsak@gmail.com>
 2
 3 JSC should natively support WebAssembly
 4 https://bugs.webkit.org/show_bug.cgi?id=146064
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * API/JSScriptRef.cpp:
 9 * CMakeLists.txt:
 10 * JavaScriptCore.xcodeproj/project.pbxproj:
 11 * assembler/X86Assembler.h:
 12 (JSC::X86Assembler::divl_r):
 13 * bytecode/CodeBlock.cpp:
 14 (JSC::CodeBlock::sourceCodeForTools):
 15 (JSC::CodeBlock::CodeBlock):
 16 * bytecode/UnlinkedCodeBlock.cpp:
 17 (JSC::generateFunctionCodeBlock):
 18 (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
 19 (JSC::UnlinkedFunctionExecutable::visitChildren):
 20 * bytecode/UnlinkedCodeBlock.h:
 21 * dfg/DFGByteCodeParser.cpp:
 22 (JSC::DFG::ByteCodeParser::attemptToInlineCall):
 23 * interpreter/StackVisitor.cpp:
 24 (JSC::StackVisitor::readNonInlinedFrame):
 25 * jit/JITDisassembler.cpp:
 26 (JSC::JITDisassembler::dump):
 27 * jsc.cpp:
 28 (GlobalObject::finishCreation):
 29 (functionLoadWebAssembly):
 30 * parser/SourceCode.cpp:
 31 (JSC::SourceCode::toUTF8):
 32 * parser/SourceProvider.h:
 33 * runtime/Executable.cpp:
 34 (JSC::ExecutableBase::isWebAssemblyFunction):
 35 (JSC::ScriptExecutable::newCodeBlockFor):
 36 (JSC::ScriptExecutable::prepareForExecutionImpl):
 37 * runtime/Executable.h:
 38 (JSC::ExecutableBase::isEvalExecutable):
 39 (JSC::ExecutableBase::isFunctionExecutable):
 40 (JSC::ExecutableBase::isProgramExecutable):
 41 * wasm/JSWASMModule.cpp:
 42 (JSC::JSWASMModule::JSWASMModule):
 43 (JSC::JSWASMModule::function):
 44 (JSC::JSWASMModule::destroy):
 45 (JSC::JSWASMModule::visitChildren):
 46 * wasm/JSWASMModule.h:
 47 (JSC::JSWASMModule::GlobalData::GlobalData):
 48 (JSC::JSWASMModule::GlobalData::~GlobalData):
 49 (JSC::JSWASMModule::create):
 50 (JSC::JSWASMModule::i32Constants):
 51 (JSC::JSWASMModule::f32Constants):
 52 (JSC::JSWASMModule::f64Constants):
 53 (JSC::JSWASMModule::signatures):
 54 (JSC::JSWASMModule::functionImports):
 55 (JSC::JSWASMModule::functionImportSignatures):
 56 (JSC::JSWASMModule::globalVariableTypes):
 57 (JSC::JSWASMModule::globalData):
 58 (JSC::JSWASMModule::globalVariableAddresses):
 59 (JSC::JSWASMModule::functionDeclarations):
 60 (JSC::JSWASMModule::functionPointerTables):
 61 (JSC::JSWASMModule::functions):
 62 (JSC::JSWASMModule::importedFunctions):
 63 (JSC::JSWASMModule::arrayBuffer):
 64 (JSC::JSWASMModule::JSWASMModule): Deleted.
 65 * wasm/WASMCodeGenerator.h: Added.
 66 (JSC::getInternalFunction):
 67 (JSC::getImportedFunction):
 68 (JSC::JumpScope::jump):
 69 (JSC::JumpScope::link):
 70 (JSC::WASMCodeGenerator::MemoryAddress::MemoryAddress):
 71 (JSC::WASMCodeGenerator::WASMCodeGenerator):
 72 (JSC::WASMCodeGenerator::startFunction):
 73 (JSC::WASMCodeGenerator::endFunction):
 74 (JSC::WASMCodeGenerator::createFromF64ExpressionI32):
 75 (JSC::WASMCodeGenerator::createFromF64ExpressionF32):
 76 (JSC::WASMCodeGenerator::createFromS32ExpressionF64):
 77 (JSC::WASMCodeGenerator::createFromU32ExpressionF64):
 78 (JSC::WASMCodeGenerator::createUnaryExpressionI32):
 79 (JSC::WASMCodeGenerator::createUnaryExpressionF64):
 80 (JSC::WASMCodeGenerator::createBinaryExpressionI32):
 81 (JSC::WASMCodeGenerator::createBinaryExpressionF64):
 82 (JSC::WASMCodeGenerator::createRelationalI32ExpressionI32):
 83 (JSC::WASMCodeGenerator::createRelationalF64ExpressionI32):
 84 (JSC::WASMCodeGenerator::createLiteralPoolExpressionI32):
 85 (JSC::WASMCodeGenerator::createLiteralPoolExpressionF32):
 86 (JSC::WASMCodeGenerator::createLiteralPoolExpressionF64):
 87 (JSC::WASMCodeGenerator::createLiteralImmediateExpressionI32):
 88 (JSC::WASMCodeGenerator::createLiteralImmediateExpressionF32):
 89 (JSC::WASMCodeGenerator::createLiteralImmediateExpressionF64):
 90 (JSC::WASMCodeGenerator::createGetLocalExpressionI32):
 91 (JSC::WASMCodeGenerator::createGetLocalExpressionF32):
 92 (JSC::WASMCodeGenerator::createGetLocalExpressionF64):
 93 (JSC::WASMCodeGenerator::setLocal):
 94 (JSC::WASMCodeGenerator::createSetLocalExpressionI32):
 95 (JSC::WASMCodeGenerator::createSetLocalExpressionF32):
 96 (JSC::WASMCodeGenerator::createSetLocalExpressionF64):
 97 (JSC::WASMCodeGenerator::createGetGlobalExpressionI32):
 98 (JSC::WASMCodeGenerator::createGetGlobalExpressionF32):
 99 (JSC::WASMCodeGenerator::createGetGlobalExpressionF64):
 100 (JSC::WASMCodeGenerator::createSetGlobal):
 101 (JSC::WASMCodeGenerator::boxArgumentsAndAdjustStackPointer):
 102 (JSC::WASMCodeGenerator::callAndUnboxResult):
 103 (JSC::WASMCodeGenerator::createCallInternal):
 104 (JSC::WASMCodeGenerator::createCallIndirect):
 105 (JSC::WASMCodeGenerator::createCallImport):
 106 (JSC::WASMCodeGenerator::createLoad):
 107 (JSC::WASMCodeGenerator::createStore):
 108 (JSC::WASMCodeGenerator::returnStatement):
 109 (JSC::WASMCodeGenerator::jitJump):
 110 (JSC::WASMCodeGenerator::jitLabel):
 111 (JSC::WASMCodeGenerator::jitBranchIfZero):
 112 (JSC::WASMCodeGenerator::jitBranchIfNonZero):
 113 (JSC::WASMCodeGenerator::generateSwitchTable):
 114 (JSC::WASMCodeGenerator::jitLinkJump):
 115 (JSC::WASMCodeGenerator::jitLinkJumpToLabel):
 116 (JSC::WASMCodeGenerator::pop):
 117 (JSC::WASMCodeGenerator::startLoop):
 118 (JSC::WASMCodeGenerator::endLoop):
 119 (JSC::WASMCodeGenerator::startSwitch):
 120 (JSC::WASMCodeGenerator::endSwitch):
 121 (JSC::WASMCodeGenerator::linkBreak):
 122 (JSC::WASMCodeGenerator::linkContinue):
 123 (JSC::WASMCodeGenerator::breakStatement):
 124 (JSC::WASMCodeGenerator::continueStatement):
 125 (JSC::WASMCodeGenerator::startLabel):
 126 (JSC::WASMCodeGenerator::endLabel):
 127 (JSC::WASMCodeGenerator::breakLabelStatement):
 128 (JSC::WASMCodeGenerator::continueLabelStatement):
 129 (JSC::WASMCodeGenerator::callDoubleFunction):
 130 (JSC::WASMCodeGenerator::allocateSpaceOnStack):
 131 (JSC::WASMCodeGenerator::deallocateSpaceOnStack):
 132 (JSC::WASMCodeGenerator::localAddress):
 133 (JSC::WASMCodeGenerator::temporaryAddress):
 134 (JSC::WASMCodeGenerator::emitNakedCall):
 135 * wasm/WASMConstants.h: Added.
 136 (JSC::operator&):
 137 * wasm/WASMFormat.h: Renamed from Source/JavaScriptCore/wasm/WASMMagicNumber.h.
 138 * wasm/WASMFunctionParser.cpp: Added.
 139 (JSC::WASMFunctionParser::checkSyntax):
 140 (JSC::WASMFunctionParser::generateCode):
 141 (JSC::WASMFunctionParser::parseFunction):
 142 (JSC::WASMFunctionParser::initializeLocalTypes):
 143 (JSC::WASMFunctionParser::parseLocalVariables):
 144 (JSC::WASMFunctionParser::parseStatement):
 145 (JSC::WASMFunctionParser::parseSetLocalStatement):
 146 (JSC::WASMFunctionParser::parseSetGlobalStatement):
 147 (JSC::WASMFunctionParser::parseStoreStatement):
 148 (JSC::WASMFunctionParser::parseCallInternalStatement):
 149 (JSC::WASMFunctionParser::parseCallIndirectStatement):
 150 (JSC::WASMFunctionParser::parseCallImportStatement):
 151 (JSC::WASMFunctionParser::parseReturnStatement):
 152 (JSC::WASMFunctionParser::parseStatementList):
 153 (JSC::WASMFunctionParser::parseBlockStatement):
 154 (JSC::WASMFunctionParser::parseIfStatement):
 155 (JSC::WASMFunctionParser::parseIfElseStatement):
 156 (JSC::WASMFunctionParser::parseWhileStatement):
 157 (JSC::WASMFunctionParser::parseDoStatement):
 158 (JSC::WASMFunctionParser::parseLabelStatement):
 159 (JSC::WASMFunctionParser::parseBreakStatement):
 160 (JSC::WASMFunctionParser::parseBreakLabelStatement):
 161 (JSC::WASMFunctionParser::parseContinueStatement):
 162 (JSC::WASMFunctionParser::parseContinueLabelStatement):
 163 (JSC::WASMFunctionParser::parseSwitchStatement):
 164 (JSC::WASMFunctionParser::parseExpression):
 165 (JSC::WASMFunctionParser::parseExpressionI32):
 166 (JSC::WASMFunctionParser::parseLiteralPoolExpressionI32):
 167 (JSC::WASMFunctionParser::parseLiteralImmediateExpressionI32):
 168 (JSC::WASMFunctionParser::parseGetLocalExpressionI32):
 169 (JSC::WASMFunctionParser::parseGetGlobalExpressionI32):
 170 (JSC::WASMFunctionParser::parseSetLocalExpressionI32):
 171 (JSC::WASMFunctionParser::parseSetGlobalExpressionI32):
 172 (JSC::WASMFunctionParser::parseLoadExpressionI32):
 173 (JSC::WASMFunctionParser::parseStoreExpressionI32):
 174 (JSC::WASMFunctionParser::parseCallInternalExpressionI32):
 175 (JSC::WASMFunctionParser::parseCallIndirectExpressionI32):
 176 (JSC::WASMFunctionParser::parseCallImportExpressionI32):
 177 (JSC::WASMFunctionParser::parseConditionalExpressionI32):
 178 (JSC::WASMFunctionParser::parseCommaExpressionI32):
 179 (JSC::WASMFunctionParser::parseFromF64ExpressionI32):
 180 (JSC::WASMFunctionParser::parseUnaryExpressionI32):
 181 (JSC::WASMFunctionParser::parseBinaryExpressionI32):
 182 (JSC::WASMFunctionParser::parseRelationalI32ExpressionI32):
 183 (JSC::WASMFunctionParser::parseRelationalF64ExpressionI32):
 184 (JSC::WASMFunctionParser::parseExpressionF32):
 185 (JSC::WASMFunctionParser::parseLiteralPoolExpressionF32):
 186 (JSC::WASMFunctionParser::parseLiteralImmediateExpressionF32):
 187 (JSC::WASMFunctionParser::parseGetLocalExpressionF32):
 188 (JSC::WASMFunctionParser::parseGetGlobalExpressionF32):
 189 (JSC::WASMFunctionParser::parseSetLocalExpressionF32):
 190 (JSC::WASMFunctionParser::parseSetGlobalExpressionF32):
 191 (JSC::WASMFunctionParser::parseLoadExpressionF32):
 192 (JSC::WASMFunctionParser::parseLoadWithOffsetExpressionF32):
 193 (JSC::WASMFunctionParser::parseStoreExpressionF32):
 194 (JSC::WASMFunctionParser::parseStoreWithOffsetExpressionF32):
 195 (JSC::WASMFunctionParser::parseFromF64ExpressionF32):
 196 (JSC::WASMFunctionParser::parseExpressionF64):
 197 (JSC::WASMFunctionParser::parseLiteralPoolExpressionF64):
 198 (JSC::WASMFunctionParser::parseLiteralImmediateExpressionF64):
 199 (JSC::WASMFunctionParser::parseGetLocalExpressionF64):
 200 (JSC::WASMFunctionParser::parseGetGlobalExpressionF64):
 201 (JSC::WASMFunctionParser::parseSetLocalExpressionF64):
 202 (JSC::WASMFunctionParser::parseSetGlobalExpressionF64):
 203 (JSC::WASMFunctionParser::parseLoadExpressionF64):
 204 (JSC::WASMFunctionParser::parseLoadWithOffsetExpressionF64):
 205 (JSC::WASMFunctionParser::parseStoreExpressionF64):
 206 (JSC::WASMFunctionParser::parseStoreWithOffsetExpressionF64):
 207 (JSC::WASMFunctionParser::parseCallInternalExpressionF64):
 208 (JSC::WASMFunctionParser::parseCallIndirectExpressionF64):
 209 (JSC::WASMFunctionParser::parseCallImportExpressionF64):
 210 (JSC::WASMFunctionParser::parseConditionalExpressionF64):
 211 (JSC::WASMFunctionParser::parseCommaExpressionF64):
 212 (JSC::WASMFunctionParser::parseFromS32ExpressionF64):
 213 (JSC::WASMFunctionParser::parseFromU32ExpressionF64):
 214 (JSC::WASMFunctionParser::parseUnaryExpressionF64):
 215 (JSC::WASMFunctionParser::parseBinaryExpressionF64):
 216 (JSC::WASMFunctionParser::parseExpressionVoid):
 217 (JSC::WASMFunctionParser::parseCallInternalExpressionVoid):
 218 (JSC::WASMFunctionParser::parseCallIndirectExpressionVoid):
 219 (JSC::WASMFunctionParser::parseCallImportExpressionVoid):
 220 (JSC::WASMFunctionParser::parseMemoryAddress):
 221 (JSC::WASMFunctionParser::parseLoad):
 222 (JSC::WASMFunctionParser::parseStore):
 223 (JSC::WASMFunctionParser::parseCallArguments):
 224 (JSC::WASMFunctionParser::parseCallInternal):
 225 (JSC::WASMFunctionParser::parseCallIndirect):
 226 (JSC::WASMFunctionParser::parseCallImport):
 227 * wasm/WASMFunctionParser.h: Added.
 228 (JSC::WASMFunctionParser::WASMFunctionParser):
 229 * wasm/WASMModuleParser.cpp:
 230 (JSC::WASMModuleParser::parse):
 231 (JSC::WASMModuleParser::parseModule):
 232 (JSC::WASMModuleParser::parseConstantPoolSection):
 233 (JSC::WASMModuleParser::parseSignatureSection):
 234 (JSC::WASMModuleParser::parseFunctionImportSection):
 235 (JSC::WASMModuleParser::parseGlobalSection):
 236 (JSC::WASMModuleParser::parseFunctionDeclarationSection):
 237 (JSC::WASMModuleParser::parseFunctionPointerTableSection):
 238 (JSC::WASMModuleParser::parseFunctionDefinitionSection):
 239 (JSC::WASMModuleParser::parseExportSection):
 240 (JSC::WASMModuleParser::parseFunctionDefinition):
 241 (JSC::parseWebAssembly):
 242 (JSC::WASMModuleParser::WASMModuleParser): Deleted.
 243 * wasm/WASMModuleParser.h:
 244 (JSC::WASMModuleParser::WASMModuleParser):
 245 * wasm/WASMReader.cpp:
 246 (JSC::WASMReader::readUInt32):
 247 (JSC::WASMReader::readCompactUInt32):
 248 (JSC::WASMReader::readCompactInt32):
 249 (JSC::WASMReader::readString):
 250 (JSC::WASMReader::readType):
 251 (JSC::WASMReader::readExpressionType):
 252 (JSC::WASMReader::readExportFormat):
 253 (JSC::WASMReader::readSwitchCase):
 254 (JSC::WASMReader::readByte):
 255 (JSC::WASMReader::readUnsignedInt32):
 256 (JSC::WASMReader::ifI32Literal):
 257 * wasm/WASMReader.h:
 258 (JSC::WASMReader::index):
 259 (JSC::WASMReader::setIndex):
 260 (JSC::WASMReader::readOpExpressionVoid):
 261 (JSC::WASMReader::readByte):
 262 (JSC::WASMReader::readCode):
 263 * wasm/WASMSyntaxChecker.h: Added.
 264 (JSC::WASMSyntaxChecker::MemoryAddress::MemoryAddress):
 265 (JSC::WASMSyntaxChecker::WASMSyntaxChecker):
 266 (JSC::WASMSyntaxChecker::startFunction):
 267 (JSC::WASMSyntaxChecker::endFunction):
 268 (JSC::WASMSyntaxChecker::setLocal):
 269 (JSC::WASMSyntaxChecker::returnStatement):
 270 (JSC::WASMSyntaxChecker::createLiteralPoolExpressionI32):
 271 (JSC::WASMSyntaxChecker::createLiteralPoolExpressionF32):
 272 (JSC::WASMSyntaxChecker::createLiteralPoolExpressionF64):
 273 (JSC::WASMSyntaxChecker::createLiteralImmediateExpressionI32):
 274 (JSC::WASMSyntaxChecker::createLiteralImmediateExpressionF32):
 275 (JSC::WASMSyntaxChecker::createLiteralImmediateExpressionF64):
 276 (JSC::WASMSyntaxChecker::createGetLocalExpressionI32):
 277 (JSC::WASMSyntaxChecker::createGetLocalExpressionF32):
 278 (JSC::WASMSyntaxChecker::createGetLocalExpressionF64):
 279 (JSC::WASMSyntaxChecker::createSetLocalExpressionI32):
 280 (JSC::WASMSyntaxChecker::createSetLocalExpressionF32):
 281 (JSC::WASMSyntaxChecker::createSetLocalExpressionF64):
 282 (JSC::WASMSyntaxChecker::createGetGlobalExpressionI32):
 283 (JSC::WASMSyntaxChecker::createGetGlobalExpressionF32):
 284 (JSC::WASMSyntaxChecker::createGetGlobalExpressionF64):
 285 (JSC::WASMSyntaxChecker::createSetGlobal):
 286 (JSC::WASMSyntaxChecker::createLoad):
 287 (JSC::WASMSyntaxChecker::createStore):
 288 (JSC::WASMSyntaxChecker::createCallInternal):
 289 (JSC::WASMSyntaxChecker::createCallIndirect):
 290 (JSC::WASMSyntaxChecker::createCallImport):
 291 (JSC::WASMSyntaxChecker::createFromF64ExpressionI32):
 292 (JSC::WASMSyntaxChecker::createFromF64ExpressionF32):
 293 (JSC::WASMSyntaxChecker::createFromS32ExpressionF64):
 294 (JSC::WASMSyntaxChecker::createFromU32ExpressionF64):
 295 (JSC::WASMSyntaxChecker::createUnaryExpressionI32):
 296 (JSC::WASMSyntaxChecker::createUnaryExpressionF64):
 297 (JSC::WASMSyntaxChecker::createBinaryExpressionI32):
 298 (JSC::WASMSyntaxChecker::createRelationalI32ExpressionI32):
 299 (JSC::WASMSyntaxChecker::createRelationalF64ExpressionI32):
 300 (JSC::WASMSyntaxChecker::createBinaryExpressionF64):
 301 (JSC::WASMSyntaxChecker::jitJump):
 302 (JSC::WASMSyntaxChecker::jitLinkJump):
 303 (JSC::WASMSyntaxChecker::jitLinkJumpToLabel):
 304 (JSC::WASMSyntaxChecker::jitLabel):
 305 (JSC::WASMSyntaxChecker::jitBranchIfZero):
 306 (JSC::WASMSyntaxChecker::jitBranchIfNonZero):
 307 (JSC::WASMSyntaxChecker::generateSwitchTable):
 308 (JSC::WASMSyntaxChecker::pop):
 309 (JSC::WASMSyntaxChecker::maxStackTop):
 310 (JSC::WASMSyntaxChecker::startLoop):
 311 (JSC::WASMSyntaxChecker::endLoop):
 312 (JSC::WASMSyntaxChecker::startSwitch):
 313 (JSC::WASMSyntaxChecker::endSwitch):
 314 (JSC::WASMSyntaxChecker::linkBreak):
 315 (JSC::WASMSyntaxChecker::linkContinue):
 316 (JSC::WASMSyntaxChecker::breakStatement):
 317 (JSC::WASMSyntaxChecker::continueStatement):
 318 (JSC::WASMSyntaxChecker::startLabel):
 319 (JSC::WASMSyntaxChecker::endLabel):
 320 (JSC::WASMSyntaxChecker::breakLabelStatement):
 321 (JSC::WASMSyntaxChecker::continueLabelStatement):
 322 (JSC::WASMSyntaxChecker::recordStackTop):
 323
13242015-08-04 Brent Fulgham <bfulgham@apple.com>
2325
3326 [Win] Update Apple Windows build for VS2015

Source/JavaScriptCore/API/JSScriptRef.cpp

@@public:
4646 return WTF::adoptRef(*new OpaqueJSScript(vm, url, startingLineNumber, source));
4747 }
4848
 49#if ENABLE(WEBASSEMBLY)
 50 virtual bool isStringSource() const override
 51 {
 52 return true;
 53 }
 54#endif
 55
4956 virtual const String& source() const override
5057 {
5158 return m_source;

Source/JavaScriptCore/CMakeLists.txt

@@set(JavaScriptCore_SOURCES
416416 tools/JSDollarVMPrototype.cpp
417417
418418 wasm/JSWASMModule.cpp
 419 wasm/WASMFunctionParser.cpp
419420 wasm/WASMModuleParser.cpp
420421 wasm/WASMReader.cpp
421422

Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

10351035 7B39F76E1B62DE3200360FB4 /* WASMModuleParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B39F76A1B62DE2200360FB4 /* WASMModuleParser.h */; settings = {ATTRIBUTES = (Private, ); }; };
10361036 7B39F7701B62DE3200360FB4 /* WASMReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B39F76C1B62DE2200360FB4 /* WASMReader.h */; settings = {ATTRIBUTES = (Private, ); }; };
10371037 7B39F7721B63574D00360FB4 /* WASMReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7B39F7711B63574B00360FB4 /* WASMReader.cpp */; };
1038  7B7A5E271B68288C0027CAD0 /* WASMMagicNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B7A5E261B6828840027CAD0 /* WASMMagicNumber.h */; settings = {ATTRIBUTES = (Private, ); }; };
10391038 7B98D1361B60CD5F0023B1A4 /* JSWASMModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7B98D1341B60CD5A0023B1A4 /* JSWASMModule.cpp */; };
10401039 7B98D1371B60CD620023B1A4 /* JSWASMModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B98D1351B60CD5A0023B1A4 /* JSWASMModule.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1040 7BDEC83C1B7071E000BC218C /* WASMCodeGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDEC8361B7071DA00BC218C /* WASMCodeGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1041 7BDEC83D1B7071E500BC218C /* WASMConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDEC8371B7071DA00BC218C /* WASMConstants.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1042 7BDEC83E1B7071EA00BC218C /* WASMFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDEC8381B7071DA00BC218C /* WASMFormat.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1043 7BDEC83F1B7071F000BC218C /* WASMFunctionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7BDEC8391B7071DA00BC218C /* WASMFunctionParser.cpp */; };
 1044 7BDEC8401B7071F300BC218C /* WASMFunctionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDEC83A1B7071DA00BC218C /* WASMFunctionParser.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1045 7BDEC8411B7071F700BC218C /* WASMSyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDEC83B1B7071DA00BC218C /* WASMSyntaxChecker.h */; settings = {ATTRIBUTES = (Private, ); }; };
10411046 7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */; };
10421047 7C008CDB187124BB00955C24 /* JSPromiseDeferred.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */; settings = {ATTRIBUTES = (Private, ); }; };
10431048 7C008CE7187631B600955C24 /* Microtask.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C008CE5187631B600955C24 /* Microtask.h */; settings = {ATTRIBUTES = (Private, ); }; };

28202825 7B39F76A1B62DE2200360FB4 /* WASMModuleParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMModuleParser.h; sourceTree = "<group>"; };
28212826 7B39F76C1B62DE2200360FB4 /* WASMReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMReader.h; sourceTree = "<group>"; };
28222827 7B39F7711B63574B00360FB4 /* WASMReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMReader.cpp; sourceTree = "<group>"; };
2823  7B7A5E261B6828840027CAD0 /* WASMMagicNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMMagicNumber.h; sourceTree = "<group>"; };
28242828 7B98D1341B60CD5A0023B1A4 /* JSWASMModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWASMModule.cpp; sourceTree = "<group>"; };
28252829 7B98D1351B60CD5A0023B1A4 /* JSWASMModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWASMModule.h; sourceTree = "<group>"; };
 2830 7BDEC8361B7071DA00BC218C /* WASMCodeGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMCodeGenerator.h; sourceTree = "<group>"; };
 2831 7BDEC8371B7071DA00BC218C /* WASMConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMConstants.h; sourceTree = "<group>"; };
 2832 7BDEC8381B7071DA00BC218C /* WASMFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMFormat.h; sourceTree = "<group>"; };
 2833 7BDEC8391B7071DA00BC218C /* WASMFunctionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMFunctionParser.cpp; sourceTree = "<group>"; };
 2834 7BDEC83A1B7071DA00BC218C /* WASMFunctionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMFunctionParser.h; sourceTree = "<group>"; };
 2835 7BDEC83B1B7071DA00BC218C /* WASMSyntaxChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMSyntaxChecker.h; sourceTree = "<group>"; };
28262836 7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseDeferred.cpp; sourceTree = "<group>"; };
28272837 7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseDeferred.h; sourceTree = "<group>"; };
28282838 7C008CE5187631B600955C24 /* Microtask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Microtask.h; sourceTree = "<group>"; };

43854395 7B98D1331B60CD1E0023B1A4 /* wasm */ = {
43864396 isa = PBXGroup;
43874397 children = (
 4398 7BDEC8361B7071DA00BC218C /* WASMCodeGenerator.h */,
 4399 7BDEC8371B7071DA00BC218C /* WASMConstants.h */,
 4400 7BDEC8381B7071DA00BC218C /* WASMFormat.h */,
 4401 7BDEC8391B7071DA00BC218C /* WASMFunctionParser.cpp */,
 4402 7BDEC83A1B7071DA00BC218C /* WASMFunctionParser.h */,
 4403 7BDEC83B1B7071DA00BC218C /* WASMSyntaxChecker.h */,
43884404 7B98D1341B60CD5A0023B1A4 /* JSWASMModule.cpp */,
43894405 7B98D1351B60CD5A0023B1A4 /* JSWASMModule.h */,
4390  7B7A5E261B6828840027CAD0 /* WASMMagicNumber.h */,
43914406 7B39F7691B62DE2200360FB4 /* WASMModuleParser.cpp */,
43924407 7B39F76A1B62DE2200360FB4 /* WASMModuleParser.h */,
43934408 7B39F7711B63574B00360FB4 /* WASMReader.cpp */,

57635778 files = (
57645779 0FFA549816B8835300B3A982 /* A64DOpcode.h in Headers */,
57655780 860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */,
 5781 7BDEC83D1B7071E500BC218C /* WASMConstants.h in Headers */,
57665782 0FE050291AA9095600D33B33 /* ScopedArgumentsTable.h in Headers */,
57675783 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */,
57685784 2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */,

59305946 41359CF30FDD89AD00206180 /* DateConversion.h in Headers */,
59315947 BC1166020E1997B4008066DD /* DateInstance.h in Headers */,
59325948 0F64B27A1A7957B2006E4E66 /* CallEdge.h in Headers */,
 5949 7BDEC83E1B7071EA00BC218C /* WASMFormat.h in Headers */,
59335950 14A1563210966365006FA260 /* DateInstanceCache.h in Headers */,
59345951 BCD2034C0E17135E002C7E82 /* DatePrototype.h in Headers */,
59355952 BCD203E80E1718F4002C7E82 /* DatePrototype.lut.h in Headers */,

62266243 0F392C8A1B46188400844728 /* DFGOSRExitFuzz.h in Headers */,
62276244 A5840E29187CA5E600843B10 /* inline-and-minify-stylesheets-and-scripts.py in Headers */,
62286245 0F24E55617F0B71C00ABB217 /* InlineCallFrameSet.h in Headers */,
 6246 7BDEC8411B7071F700BC218C /* WASMSyntaxChecker.h in Headers */,
62296247 99E45A2718A1B2590026D88F /* InputCursor.h in Headers */,
62306248 0F952ABD1B487A7700C367C5 /* TrackedReferences.h in Headers */,
62316249 A593CF7F1840362C00BFCE27 /* InspectorAgentBase.h in Headers */,

64806498 BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */,
64816499 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */,
64826500 0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */,
 6501 7BDEC8401B7071F300BC218C /* WASMFunctionParser.h in Headers */,
64836502 7C008CE7187631B600955C24 /* Microtask.h in Headers */,
64846503 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */,
64856504 BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */,

65506569 BC18C4540E16F5CD00B34460 /* PropertyNameArray.h in Headers */,
65516570 0FF7168C15A3B235008F5DAA /* PropertyOffset.h in Headers */,
65526571 A785F6BC18C553FE00F10626 /* SpillRegistersMode.h in Headers */,
6553  7B7A5E271B68288C0027CAD0 /* WASMMagicNumber.h in Headers */,
65546572 BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */,
65556573 0FB7F39C15ED8E4600F167B2 /* PropertyStorage.h in Headers */,
65566574 0F6FC751196110A800E1D02D /* ComplexGetStatus.h in Headers */,

66876705 A7A8AF4017ADB5F3005AB174 /* Uint8ClampedArray.h in Headers */,
66886706 0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */,
66896707 A7B601821639FD2A00372BA3 /* UnlinkedCodeBlock.h in Headers */,
 6708 7BDEC83C1B7071E000BC218C /* WASMCodeGenerator.h in Headers */,
66906709 0F2E892C16D028AD009E4FD2 /* UnusedPointer.h in Headers */,
66916710 A1587D6E1B4DC14100D69849 /* IntlDateTimeFormat.h in Headers */,
66926711 7B39F7701B62DE3200360FB4 /* WASMReader.h in Headers */,

72077226 9E729408190F021E001A91B5 /* InitializeLLVMPOSIX.cpp in Sources */,
72087227 9E729407190F01A5001A91B5 /* InitializeThreading.cpp in Sources */,
72097228 0FFA549716B8835000B3A982 /* A64DOpcode.cpp in Sources */,
 7229 7BDEC83F1B7071F000BC218C /* WASMFunctionParser.cpp in Sources */,
72107230 0FE050151AA9091100D33B33 /* DirectArgumentsOffset.cpp in Sources */,
72117231 0F55F0F414D1063900AC7649 /* AbstractPC.cpp in Sources */,
72127232 147F39BD107EC37600427A48 /* ArgList.cpp in Sources */,

Source/JavaScriptCore/assembler/X86Assembler.h

@@private:
311311 GROUP3_OP_TEST = 0,
312312 GROUP3_OP_NOT = 2,
313313 GROUP3_OP_NEG = 3,
 314 GROUP3_OP_DIV = 6,
314315 GROUP3_OP_IDIV = 7,
315316
316317 GROUP5_OP_CALLN = 2,

@@public:
932933 m_formatter.immediate32(value);
933934 }
934935
 936 void divl_r(RegisterID dst)
 937 {
 938 m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_DIV, dst);
 939 }
 940
935941 void idivl_r(RegisterID dst)
936942 {
937943 m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst);

Source/JavaScriptCore/bytecode/CodeBlock.cpp

@@CString CodeBlock::sourceCodeForTools() const
119119
120120 SourceProvider* provider = source();
121121 FunctionExecutable* executable = jsCast<FunctionExecutable*>(ownerExecutable());
 122#if ENABLE(WEBASSEMBLY)
 123 if (executable->isWebAssemblyFunction())
 124 return "function [webassembly]";
 125#endif
122126 UnlinkedFunctionExecutable* unlinked = executable->unlinkedExecutable();
123127 unsigned unlinkedStartOffset = unlinked->startOffset();
124128 unsigned linkedStartOffset = executable->source().startOffset();

@@CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
17361740 m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
17371741
17381742 ASSERT(m_heap->isDeferred());
1739  ASSERT(m_scopeRegister.isLocal());
1740 
17411743 ASSERT(m_source);
17421744 setNumParameters(unlinkedCodeBlock->numParameters());
17431745
 1746#if ENABLE(WEBASSEMBLY)
 1747 if (ownerExecutable->isWebAssemblyFunction()) {
 1748 m_heap->m_codeBlocks.add(this);
 1749 m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock));
 1750 return;
 1751 }
 1752#endif
 1753
 1754 ASSERT(m_scopeRegister.isLocal());
 1755
17441756 if (vm()->typeProfiler() || vm()->controlFlowProfiler())
17451757 vm()->functionHasExecutedCache()->removeUnexecutedRange(m_ownerExecutable->sourceID(), m_ownerExecutable->typeProfilingStartOffset(), m_ownerExecutable->typeProfilingEndOffset());
17461758

Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp

3434#include "FunctionOverrides.h"
3535#include "JSString.h"
3636#include "JSCInlines.h"
 37#include "JSWASMModule.h"
3738#include "Parser.h"
3839#include "SourceProvider.h"
3940#include "Structure.h"

@@static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(
5758 CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode,
5859 UnlinkedFunctionKind functionKind, ParserError& error)
5960{
 61#if ENABLE(WEBASSEMBLY)
 62 if (executable->isWebAssemblyFunction()) {
 63 UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(false, false, false, false, false, executable->constructorKind()));
 64 result->setNumParameters(1); // FIXME: Hacky.
 65 return result;
 66 }
 67#endif
6068 JSParserBuiltinMode builtinMode = executable->isBuiltinFunction() ? JSParserBuiltinMode::Builtin : JSParserBuiltinMode::NotBuiltin;
6169 JSParserStrictMode strictMode = executable->isInStrictContext() ? JSParserStrictMode::Strict : JSParserStrictMode::NotStrict;
6270 std::unique_ptr<FunctionNode> function = parse<FunctionNode>(

@@UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* struct
104112 , m_constructAbility(static_cast<unsigned>(constructAbility))
105113 , m_constructorKind(static_cast<unsigned>(node->constructorKind()))
106114 , m_functionMode(node->functionMode())
 115#if ENABLE(WEBASSEMBLY)
 116 , m_isWebAssemblyFunction(false)
 117#endif
107118{
108119 ASSERT(m_constructorKind == static_cast<unsigned>(node->constructorKind()));
109120 m_parentScopeTDZVariables.swap(parentScopeTDZVariables);
110121}
111122
 123#if ENABLE(WEBASSEMBLY)
 124UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, unsigned startOffset, unsigned sourceLength, JSWASMModule* module, unsigned functionIndex, unsigned stackHeight)
 125 : Base(*vm, structure)
 126 , m_name(Identifier::fromString(vm, "[webassembly]")) // FIXME:
 127 , m_inferredName(Identifier::fromString(vm, "[webassembly]")) // FIXME:
 128 , m_firstLineOffset(0)
 129 , m_lineCount(1)
 130 , m_unlinkedFunctionNameStart(0)
 131 , m_unlinkedBodyStartColumn(0)
 132 , m_unlinkedBodyEndColumn(0)
 133 , m_startOffset(startOffset)
 134 , m_sourceLength(sourceLength)
 135 , m_parametersStartOffset(0)
 136 , m_typeProfilingStartOffset(0)
 137 , m_typeProfilingEndOffset(0)
 138 , m_parameterCount(1) // FIXME:
 139 , m_features(0)
 140 , m_isInStrictContext(false) // FIXME:
 141 , m_hasCapturedVariables(false)
 142 , m_isBuiltinFunction(false)
 143 , m_constructAbility(static_cast<unsigned>(ConstructAbility::CannotConstruct))
 144 , m_constructorKind(static_cast<unsigned>(ConstructorKind::None))
 145 , m_functionMode(FunctionMode::FunctionExpression)
 146 , m_isWebAssemblyFunction(true)
 147 , m_webAssemblyModule(*vm, this, module)
 148 , m_webAssemblyFunctionIndex(functionIndex)
 149 , m_webAssemblyStackHeight(stackHeight)
 150{
 151}
 152#endif
 153
112154void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
113155{
114156 UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell);

@@void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visito
117159 visitor.append(&thisObject->m_codeBlockForCall);
118160 visitor.append(&thisObject->m_codeBlockForConstruct);
119161 visitor.append(&thisObject->m_nameValue);
 162#if ENABLE(WEBASSEMBLY)
 163 if (thisObject->m_isWebAssemblyFunction)
 164 visitor.append(&thisObject->m_webAssemblyModule);
 165#endif
120166}
121167
122168FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& ownerSource, int overrideLineNumber)

Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h

@@class Debugger;
5151class FunctionBodyNode;
5252class FunctionExecutable;
5353class JSScope;
 54#if ENABLE(WEBASSEMBLY)
 55class JSWASMModule;
 56#endif
5457class ParserError;
5558class ScriptExecutable;
5659class SourceCode;

@@public:
116119 return instance;
117120 }
118121
 122#if ENABLE(WEBASSEMBLY)
 123 static UnlinkedFunctionExecutable* create(VM* vm, unsigned startOffset, unsigned sourceLength, JSWASMModule* module, unsigned functionIndex, unsigned stackHeight)
 124 {
 125 UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap))
 126 UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), startOffset, sourceLength, module, functionIndex, stackHeight);
 127 instance->finishCreation(*vm);
 128 return instance;
 129 }
 130#endif
 131
119132 const Identifier& name() const { return m_name; }
120133 const Identifier& inferredName() const { return m_inferredName; }
121134 JSString* nameValue() const { return m_nameValue.get(); }

@@public:
166179 ConstructAbility constructAbility() const { return static_cast<ConstructAbility>(m_constructAbility); }
167180 bool isClassConstructorFunction() const { return constructorKind() != ConstructorKind::None; }
168181 const VariableEnvironment* parentScopeTDZVariables() const { return &m_parentScopeTDZVariables; }
 182#if ENABLE(WEBASSEMBLY)
 183 bool isWebAssemblyFunction() const { return m_isWebAssemblyFunction; }
 184 JSWASMModule* webAssemblyModule() const { return m_webAssemblyModule.get(); }
 185 unsigned webAssemblyFunctionIndex() const { return m_webAssemblyFunctionIndex; }
 186 unsigned webAssemblyStackHeight() const { return m_webAssemblyStackHeight; }
 187#endif
169188
170189private:
171190 UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr<SourceProvider>&& sourceOverride, FunctionBodyNode*, UnlinkedFunctionKind, ConstructAbility, VariableEnvironment&);
 191#if ENABLE(WEBASSEMBLY)
 192 UnlinkedFunctionExecutable(VM*, Structure*, unsigned startOffset, unsigned sourceLength, JSWASMModule*, unsigned functionIndex, unsigned stackHeight);
 193#endif
172194 WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
173195 WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
174196

@@private:
198220 unsigned m_constructAbility: 1;
199221 unsigned m_constructorKind : 2;
200222 unsigned m_functionMode : 1; // FunctionMode
 223#if ENABLE(WEBASSEMBLY)
 224 unsigned m_isWebAssemblyFunction : 1;
 225 WriteBarrier<JSWASMModule> m_webAssemblyModule;
 226 unsigned m_webAssemblyFunctionIndex;
 227 unsigned m_webAssemblyStackHeight;
 228#endif
201229
202230protected:
203231 void finishCreation(VM& vm)

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

@@bool ByteCodeParser::attemptToInlineCall(Node* callTargetNode, int resultOperand
14601460 if (!inliningBalance)
14611461 return false;
14621462
 1463#if ENABLE(WEBASSEMBLY)
 1464 if (ExecutableBase* executable = callee.executable()) {
 1465 if (executable->isWebAssemblyFunction())
 1466 return false;
 1467 }
 1468#endif
 1469
14631470 bool didInsertChecks = false;
14641471 auto insertChecksWithAccounting = [&] () {
14651472 insertChecks(nullptr);

Source/JavaScriptCore/interpreter/StackVisitor.cpp

@@void StackVisitor::readNonInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOri
124124 m_frame.m_codeBlock = callFrame->codeBlock();
125125 m_frame.m_bytecodeOffset = !m_frame.codeBlock() ? 0
126126 : codeOrigin ? codeOrigin->bytecodeIndex
 127#if ENABLE(WEBASSEMBLY)
 128 : callFrame->codeBlock()->ownerExecutable()->isWebAssemblyFunction() ? 0
 129#endif
127130 : callFrame->locationAsBytecodeOffset();
128131#if ENABLE(DFG_JIT)
129132 m_frame.m_inlineCallFrame = 0;

Source/JavaScriptCore/jit/JITDisassembler.cpp

@@JITDisassembler::~JITDisassembler()
5151void JITDisassembler::dump(PrintStream& out, LinkBuffer& linkBuffer)
5252{
5353 dumpHeader(out, linkBuffer);
54  dumpDisassembly(out, linkBuffer, m_startOfCode, m_labelForBytecodeIndexInMainPath[0]);
55 
56  dumpForInstructions(out, linkBuffer, " ", m_labelForBytecodeIndexInMainPath, firstSlowLabel());
57  out.print(" (End Of Main Path)\n");
58  dumpForInstructions(out, linkBuffer, " (S) ", m_labelForBytecodeIndexInSlowPath, m_endOfSlowPath);
59  out.print(" (End Of Slow Path)\n");
6054
61  dumpDisassembly(out, linkBuffer, m_endOfSlowPath, m_endOfCode);
 55 if (!m_labelForBytecodeIndexInMainPath.isEmpty()) {
 56 dumpDisassembly(out, linkBuffer, m_startOfCode, m_labelForBytecodeIndexInMainPath[0]);
 57
 58 dumpForInstructions(out, linkBuffer, " ", m_labelForBytecodeIndexInMainPath, firstSlowLabel());
 59 out.print(" (End Of Main Path)\n");
 60 dumpForInstructions(out, linkBuffer, " (S) ", m_labelForBytecodeIndexInSlowPath, m_endOfSlowPath);
 61 out.print(" (End Of Slow Path)\n");
 62
 63 dumpDisassembly(out, linkBuffer, m_endOfSlowPath, m_endOfCode);
 64 } else
 65 dumpDisassembly(out, linkBuffer, m_startOfCode, m_endOfCode);
6266}
6367
6468void JITDisassembler::dump(LinkBuffer& linkBuffer)

Source/JavaScriptCore/jsc.cpp

@@protected:
662662 addFunction(vm, "hasBasicBlockExecuted", functionHasBasicBlockExecuted, 2);
663663
664664 addFunction(vm, "enableExceptionFuzz", functionEnableExceptionFuzz, 0);
 665
 666#if ENABLE(WEBASSEMBLY)
 667 addFunction(vm, "loadWebAssembly", functionLoadWebAssembly, 3);
 668#endif
665669
666670#if ENABLE(WEBASSEMBLY)
667671 addFunction(vm, "loadWebAssembly", functionLoadWebAssembly, 1);

@@EncodedJSValue JSC_HOST_CALL functionLoadWebAssembly(ExecState* exec)
12071211 return JSValue::encode(exec->vm().throwException(exec, createError(exec, ASCIILiteral("Could not open file."))));
12081212 RefPtr<WebAssemblySourceProvider> sourceProvider = WebAssemblySourceProvider::create(reinterpret_cast<Vector<uint8_t>&>(buffer), fileName);
12091213 SourceCode source(sourceProvider);
 1214
 1215 JSValue envValue = exec->argument(1);
 1216 RELEASE_ASSERT(envValue.isObject());
 1217 JSObject* env = envValue.getObject();
 1218
 1219 JSValue arrayBufferValue = exec->argument(2);
 1220 JSArrayBuffer* arrayBuffer = jsDynamicCast<JSArrayBuffer*>(arrayBufferValue);
 1221 RELEASE_ASSERT(arrayBuffer);
 1222
12101223 String errorMessage;
1211  JSWASMModule* module = parseWebAssembly(exec, source, errorMessage);
 1224 JSWASMModule* module = parseWebAssembly(exec, source, env, arrayBuffer, errorMessage);
12121225 if (!module)
12131226 return JSValue::encode(exec->vm().throwException(exec, createSyntaxError(exec, errorMessage)));
12141227 return JSValue::encode(module);

Source/JavaScriptCore/parser/SourceCode.cpp

@@CString SourceCode::toUTF8() const
3636 if (!m_provider)
3737 return CString("", 0);
3838
 39#if ENABLE(WEBASSEMBLY)
 40 if (!m_provider->isStringSource()) // FIXME: hacky
 41 return CString("", 0);
 42#endif
 43
3944 return m_provider->source().impl()->utf8ForRange(m_startChar, m_endChar - m_startChar);
4045}
4146

Source/JavaScriptCore/parser/SourceProvider.h

@@namespace JSC {
4343
4444 JS_EXPORT_PRIVATE virtual ~SourceProvider();
4545
 46#if ENABLE(WEBASSEMBLY)
 47 virtual bool isStringSource() const = 0;
 48#endif
4649 virtual const String& source() const = 0;
4750 String getRange(int start, int end) const
4851 {

@@namespace JSC {
7982 return adoptRef(*new StringSourceProvider(source, url, startPosition));
8083 }
8184
 85#if ENABLE(WEBASSEMBLY)
 86 virtual bool isStringSource() const override
 87 {
 88 return true;
 89 }
 90#endif
 91
8292 virtual const String& source() const override
8393 {
8494 return m_source;

@@namespace JSC {
102112 return adoptRef(*new WebAssemblySourceProvider(data, url));
103113 }
104114
 115 virtual bool isStringSource() const override
 116 {
 117 return false;
 118 }
 119
105120 virtual const String& source() const override
106121 {
107122 return m_source;

Source/JavaScriptCore/runtime/Executable.cpp

3232#include "JIT.h"
3333#include "JSCInlines.h"
3434#include "JSFunctionNameScope.h"
 35#include "JSWASMModule.h"
3536#include "LLIntEntrypoint.h"
3637#include "Parser.h"
3738#include "ProfilerDatabase.h"
3839#include "TypeProfiler.h"
 40#include "WASMFunctionParser.h"
3941#include <wtf/CommaPrinter.h>
4042#include <wtf/Vector.h>
4143#include <wtf/text/StringBuilder.h>

@@void ExecutableBase::clearCode()
6365 m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
6466}
6567
 68#if ENABLE(WEBASSEMBLY)
 69bool ExecutableBase::isWebAssemblyFunction() const
 70{
 71 return isFunctionExecutable() && jsCast<const FunctionExecutable*>(this)->isWebAssemblyFunction();
 72}
 73#endif
 74
6675#if ENABLE(DFG_JIT)
6776Intrinsic ExecutableBase::intrinsic() const
6877{

@@RefPtr<CodeBlock> ScriptExecutable::newCodeBlockFor(
247256 return nullptr;
248257 }
249258
 259#if ENABLE(WEBASSEMBLY)
 260 if (executable->isWebAssemblyFunction()) {
 261 SourceProvider* provider = executable->source().provider();
 262 unsigned sourceOffset = executable->source().startOffset();
 263 unsigned startColumn = executable->source().startColumn();
 264
 265 RefPtr<CodeBlock> codeBlock = adoptRef(new FunctionCodeBlock(executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn));
 266 WASMFunctionParser::generateCode(vm, codeBlock.get(), executable->m_unlinkedExecutable->webAssemblyModule(), executable->source(), executable->m_unlinkedExecutable->webAssemblyFunctionIndex(), executable->m_unlinkedExecutable->startOffset(), executable->m_unlinkedExecutable->webAssemblyStackHeight());
 267 codeBlock->capabilityLevel();
 268 return codeBlock;
 269 }
 270#endif
 271
250272 // Parsing reveals whether our function uses features that require a separate function name object in the scope chain.
251273 // Be sure to add this scope before linking the bytecode because this scope will change the resolution depth of non-local variables.
252274 if (functionNameIsInScope(executable->name(), executable->functionMode())

@@JSObject* ScriptExecutable::prepareForExecutionImpl(
333355 return exception;
334356 }
335357
336  if (Options::validateBytecode())
337  codeBlock->validate();
 358#if ENABLE(WEBASSEMBLY)
 359 if (!isWebAssemblyFunction()) {
 360#endif
 361 if (Options::validateBytecode())
 362 codeBlock->validate();
338363
339  if (Options::useLLInt())
340  setupLLInt(vm, codeBlock.get());
341  else
342  setupJIT(vm, codeBlock.get());
 364 if (Options::useLLInt())
 365 setupLLInt(vm, codeBlock.get());
 366 else
 367 setupJIT(vm, codeBlock.get());
 368#if ENABLE(WEBASSEMBLY)
 369 }
 370#endif
343371
344372 installCode(codeBlock.get());
345373 return 0;

Source/JavaScriptCore/runtime/Executable.h

@@public:
9090
9191 CodeBlockHash hashFor(CodeSpecializationKind) const;
9292
93  bool isEvalExecutable()
 93 bool isEvalExecutable() const
9494 {
9595 return type() == EvalExecutableType;
9696 }
97  bool isFunctionExecutable()
 97 bool isFunctionExecutable() const
9898 {
9999 return type() == FunctionExecutableType;
100100 }
101  bool isProgramExecutable()
 101 bool isProgramExecutable() const
102102 {
103103 return type() == ProgramExecutableType;
104104 }

@@public:
109109 return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
110110 }
111111
 112#if ENABLE(WEBASSEMBLY)
 113 bool isWebAssemblyFunction() const;
 114#endif
 115
112116 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
113117
114118 void clearCode();

@@public:
562566
563567 static void destroy(JSCell*);
564568
565  UnlinkedFunctionExecutable* unlinkedExecutable()
 569 UnlinkedFunctionExecutable* unlinkedExecutable() const
566570 {
567571 return m_unlinkedExecutable.get();
568572 }

@@public:
631635 FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
632636 bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
633637 ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
 638#if ENABLE(WEBASSEMBLY)
 639 bool isWebAssemblyFunction() const { return m_unlinkedExecutable->isWebAssemblyFunction(); }
 640#endif
634641 bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
635642 const Identifier& name() { return m_unlinkedExecutable->name(); }
636643 const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }

Source/JavaScriptCore/wasm/JSWASMModule.cpp

2828
2929#if ENABLE(WEBASSEMBLY)
3030
 31#include "JSArrayBuffer.h"
 32#include "JSCellInlines.h"
3133#include "JSFunction.h"
 34#include "JSGlobalObject.h"
 35#include "Reject.h"
3236#include "SlotVisitorInlines.h"
3337
3438namespace JSC {
3539
3640const ClassInfo JSWASMModule::s_info = { "WASMModule", &Base::s_info, 0, CREATE_METHOD_TABLE(JSWASMModule) };
3741
38 void JSWASMModule::visitChildren(JSCell* cell, SlotVisitor& visitor)
 42JSWASMModule::JSWASMModule(VM& vm, Structure* structure, JSArrayBuffer* arrayBuffer)
 43 : Base(vm, structure)
 44 , m_arrayBuffer(vm, this, arrayBuffer)
 45{
 46}
 47
 48JSFunction* JSWASMModule::function(size_t functionIndex) const
 49{
 50 return m_functions[functionIndex].get();
 51}
 52
 53// const void* JSWASMModule::arrayBufferData() const
 54// {
 55// return m_arrayBuffer->impl()->data();
 56// }
 57
 58void JSWASMModule::destroy(JSCell* cell)
3959{
4060 JSWASMModule* thisObject = jsCast<JSWASMModule*>(cell);
 61 thisObject->JSWASMModule::~JSWASMModule();
 62}
 63
 64void JSWASMModule::visitChildren(JSCell* cell, SlotVisitor& visitor)
 65{
 66 JSWASMModule* thisObject = static_cast<JSWASMModule*>(cell);
4167 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
4268 Base::visitChildren(thisObject, visitor);
4369 for (auto function : thisObject->m_functions)
4470 visitor.append(&function);
 71 for (auto importedFunction : thisObject->m_importedFunctions)
 72 visitor.append(&importedFunction);
 73 visitor.append(&thisObject->m_arrayBuffer);
4574}
4675
4776} // namespace JSC

Source/JavaScriptCore/wasm/JSWASMModule.h

2929#if ENABLE(WEBASSEMBLY)
3030
3131#include "JSDestructibleObject.h"
 32#include "WASMFormat.h"
3233
3334namespace JSC {
3435
3536class JSWASMModule : public JSDestructibleObject {
3637public:
 38 struct GlobalData {
 39 GlobalData()
 40 : data(nullptr)
 41 {
 42 }
 43 ~GlobalData()
 44 {
 45 if (data != nullptr)
 46 fastFree(data);
 47 }
 48 void* data;
 49 };
 50
3751 typedef JSDestructibleObject Base;
3852
39  static JSWASMModule* create(VM& vm, Structure* structure)
 53 static JSWASMModule* create(VM& vm, Structure* structure, JSArrayBuffer* arrayBuffer)
4054 {
41  JSWASMModule* module = new (NotNull, allocateCell<JSWASMModule>(vm.heap)) JSWASMModule(vm, structure);
 55 JSWASMModule* module = new (NotNull, allocateCell<JSWASMModule>(vm.heap)) JSWASMModule(vm, structure, arrayBuffer);
4256 module->finishCreation(vm);
4357 return module;
4458 }

@@public:
5064 return Structure::create(vm, globalObject, jsNull(), TypeInfo(ObjectType, StructureFlags), info());
5165 }
5266
 67 Vector<uint32_t>& i32Constants() { return m_i32Constants; }
 68 Vector<float>& f32Constants() { return m_f32Constants; }
 69 Vector<double>& f64Constants() { return m_f64Constants; }
 70 Vector<WASMSignature>& signatures() { return m_signatures; }
 71 Vector<WASMFunctionImport>& functionImports() { return m_functionImports; }
 72 Vector<WASMFunctionImportSignature>& functionImportSignatures() { return m_functionImportSignatures; }
 73 Vector<WASMType>& globalVariableTypes() { return m_globalVariableTypes; }
 74 GlobalData& globalData() { return m_globalData; }
 75 Vector<const void*>& globalVariableAddresses() { return m_globalVariableAddresses; }
 76 Vector<WASMFunctionDeclaration>& functionDeclarations() { return m_functionDeclarations; }
 77 Vector<WASMFunctionPointerTable>& functionPointerTables() { return m_functionPointerTables; }
 78
 79 const Vector<WASMSignature>& signatures() const { return m_signatures; }
 80 const Vector<WASMFunctionImportSignature>& functionImportSignatures() const { return m_functionImportSignatures; }
 81 const Vector<uint32_t>& i32Constants() const { return m_i32Constants; }
 82 const Vector<float>& f32Constants() const { return m_f32Constants; }
 83 const Vector<double>& f64Constants() const { return m_f64Constants; }
 84 const Vector<WASMType>& globalVariableTypes() const { return m_globalVariableTypes; }
 85 const Vector<const void*>& globalVariableAddresses() const { return m_globalVariableAddresses; }
 86 const Vector<WASMFunctionDeclaration>& functionDeclarations() const { return m_functionDeclarations; }
 87 const Vector<WASMFunctionPointerTable>& functionPointerTables() const { return m_functionPointerTables; }
 88
 89 Vector<WriteBarrier<JSFunction>>& functions() { return m_functions; }
 90 Vector<WriteBarrier<JSFunction>>& importedFunctions() { return m_importedFunctions; }
 91 JSFunction* function(size_t functionIndex) const;
 92 const JSArrayBuffer* arrayBuffer() const { return m_arrayBuffer.get(); }
 93
 94 static void destroy(JSCell*);
5395 static void visitChildren(JSCell*, SlotVisitor&);
5496
5597private:
56  JSWASMModule(VM& vm, Structure* structure)
57  : Base(vm, structure)
58  {
59  }
 98 JSWASMModule(VM&, Structure*, JSArrayBuffer*);
 99
 100 Vector<uint32_t> m_i32Constants;
 101 Vector<float> m_f32Constants;
 102 Vector<double> m_f64Constants;
 103 Vector<WASMSignature> m_signatures;
 104 Vector<WASMFunctionImport> m_functionImports;
 105 Vector<WASMFunctionImportSignature> m_functionImportSignatures;
 106 Vector<WASMType> m_globalVariableTypes;
 107 GlobalData m_globalData;
 108 Vector<const void*> m_globalVariableAddresses;
 109 Vector<WASMFunctionDeclaration> m_functionDeclarations;
 110 Vector<WASMFunctionPointerTable> m_functionPointerTables;
60111
61112 Vector<WriteBarrier<JSFunction>> m_functions;
 113 Vector<WriteBarrier<JSFunction>> m_importedFunctions;
 114 WriteBarrier<JSArrayBuffer> m_arrayBuffer;
62115};
63116
64117} // namespace JSC

Source/JavaScriptCore/wasm/WASMCodeGenerator.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef WASMCodeGenerator_h
 27#define WASMCodeGenerator_h
 28
 29#if ENABLE(WEBASSEMBLY)
 30
 31#include "CCallHelpers.h"
 32#include "JIT.h"
 33#include "JITDisassembler.h"
 34#include "JSArrayBuffer.h"
 35#include "JSCJSValueInlines.h"
 36#include "JSWASMModule.h"
 37#include "LinkBuffer.h"
 38#include "MaxFrameExtentForSlowPathCall.h"
 39#include "Register.h"
 40
 41namespace JSC {
 42
 43class JSWASMModule;
 44
 45static EncodedJSValue JSC_HOST_CALL getInternalFunction(ExecState*, JSWASMModule* module, uint32_t functionIndex)
 46{
 47 return JSValue::encode(module->function(functionIndex));
 48}
 49
 50static EncodedJSValue JSC_HOST_CALL getImportedFunction(ExecState*, JSWASMModule* module, uint32_t funcImportIndex)
 51{
 52 return JSValue::encode(module->importedFunctions()[funcImportIndex].get());
 53}
 54
 55// static const void* JSC_HOST_CALL getArrayBufferData(JSWASMModule* module)
 56// {
 57// return module->arrayBufferData();
 58// }
 59
 60// FIXME: Hacky. Do this properly.
 61// static void JSC_HOST_CALL throwOutOfBoundsException(ExecState*) {
 62// fprintf(stderr, "Out-of-bounds access.");
 63// double f = 42.0;
 64// if (f == 42.0)
 65// exit(1);
 66// return;
 67// }
 68
 69class JumpScope {
 70public:
 71 void jump(MacroAssembler* macroAssembler)
 72 {
 73 if (m_label.isSet())
 74 macroAssembler->jump(m_label);
 75 else
 76 m_jumpList.append(macroAssembler->jump());
 77 }
 78
 79 void link(MacroAssembler* macroAssembler)
 80 {
 81 ASSERT(!m_label.isSet());
 82 m_label = macroAssembler->label();
 83 m_jumpList.link(macroAssembler);
 84 }
 85
 86private:
 87 MacroAssembler::Label m_label;
 88 MacroAssembler::JumpList m_jumpList;
 89};
 90
 91class WASMCodeGenerator : private CCallHelpers {
 92public:
 93 typedef int Expression;
 94 typedef int Statement;
 95 typedef int ExpressionList;
 96 typedef Jump Jump; // FIXME: Bad name.
 97 typedef Label Label;
 98 struct MemoryAddress {
 99 MemoryAddress(void*) { }
 100 MemoryAddress(bool hasImmediateIndex, uint32_t immediateIndex, Expression, uint32_t offset)
 101 : hasImmediateIndex(hasImmediateIndex)
 102 , immediateIndex(immediateIndex)
 103 , offset(offset)
 104 {
 105 }
 106 bool hasImmediateIndex;
 107 uint32_t immediateIndex;
 108 uint32_t offset;
 109 };
 110
 111 WASMCodeGenerator(VM* vm, CodeBlock* codeBlock, const JSWASMModule* module, unsigned stackHeight)
 112 : CCallHelpers(vm, codeBlock)
 113 , m_module(module)
 114 , m_stackHeight(stackHeight)
 115 {
 116 m_sp = 0;
 117 }
 118
 119 void startFunction(const WASMSignature& signature, uint32_t numberOfI32Vars, uint32_t numberOfF32Vars, uint32_t numberOfF64Vars)
 120 {
 121 if (Options::showDisassembly())
 122 m_disassembler = std::make_unique<JITDisassembler>(m_codeBlock);
 123
 124 if (m_disassembler)
 125 m_disassembler->setStartOfCode(label());
 126
 127 //FIXME
 128 m_stackHeight = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_stackHeight + signature.arguments.size() + numberOfI32Vars + numberOfF32Vars + numberOfF64Vars);
 129
 130 emitFunctionPrologue();
 131 emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
 132
 133 m_beginLabel = label();
 134
 135 allocateSpaceOnStack();
 136
 137 size_t argumentCount = signature.arguments.size();
 138 for (size_t argIndex = 0; argIndex < argumentCount; ++argIndex) {
 139 WASMType type = signature.arguments[argIndex];
 140 Address address(GPRInfo::callFrameRegister, (argIndex + 1 + CallFrame::thisArgumentOffset()) * 8);
 141 switch (type) {
 142 case WASMType::I32:
 143 load32(address, GPRInfo::regT0);
 144 store32(GPRInfo::regT0, localAddress(argIndex));
 145 break;
 146 case WASMType::F64:
 147 load64(address, GPRInfo::regT0);
 148 unboxDoubleWithoutAssertions(GPRInfo::regT0, FPRInfo::fpRegT0);
 149 storeDouble(FPRInfo::fpRegT0, localAddress(argIndex));
 150 break;
 151 default:
 152 RELEASE_ASSERT_NOT_REACHED();
 153 }
 154 }
 155
 156 size_t localIndex = argumentCount;
 157 for (uint32_t i = 0; i < numberOfI32Vars; ++i)
 158 store32(TrustedImm32(0), localAddress(localIndex++));
 159 for (uint32_t i = 0; i < numberOfF32Vars; ++i)
 160 store32(TrustedImm32(0), localAddress(localIndex++));
 161 for (uint32_t i = 0; i < numberOfF64Vars; ++i)
 162 store64(TrustedImm64(0), localAddress(localIndex++));
 163
 164 m_numberOfLocals = argumentCount + numberOfI32Vars + numberOfF32Vars + numberOfF64Vars;
 165 }
 166
 167 void endFunction()
 168 {
 169 ASSERT(!m_sp);
 170
 171 // FIXME: Skip if last stmt is a return statement. Make sure to not fall through the arity check.
 172 move(TrustedImm64(JSValue::encode(jsUndefined())), GPRInfo::regT0); // FIXME: Should we return undefined?
 173
 174 deallocateSpaceOnStack();
 175 emitFunctionEpilogue();
 176 ret();
 177
 178 // m_outOfBoundsJumpList.link(this);
 179 // setupArgumentsExecState();
 180 // move(TrustedImmPtr(bitwise_cast<void*>(throwOutOfBoundsException)), GPRInfo::nonArgGPR0);
 181 // call(GPRInfo::nonArgGPR0);
 182
 183 // TODO: Implement arity check
 184 // FIXME: Hacky!
 185 Label arityCheck = label();
 186 store8(TrustedImm32(0), &m_codeBlock->m_shouldAlwaysBeInlined);
 187 emitFunctionPrologue();
 188 emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
 189 jump(m_beginLabel);
 190
 191 if (m_disassembler)
 192 m_disassembler->setEndOfCode(label());
 193
 194 LinkBuffer patchBuffer(*m_vm, *this, 0, JITCompilationMustSucceed);
 195
 196 for (auto iter = m_calls.begin(); iter != m_calls.end(); ++iter)
 197 patchBuffer.link(iter->first, FunctionPtr(iter->second));
 198
 199 for (unsigned i = 0; i < m_callCompilationInfo.size(); ++i) {
 200 CallCompilationInfo& compilationInfo = m_callCompilationInfo[i];
 201 CallLinkInfo& info = *compilationInfo.callLinkInfo;
 202 info.setCallLocations(patchBuffer.locationOfNearCall(compilationInfo.callReturnLocation),
 203 patchBuffer.locationOf(compilationInfo.hotPathBegin),
 204 patchBuffer.locationOfNearCall(compilationInfo.hotPathOther));
 205 }
 206
 207 if (Options::showDisassembly()) {
 208 m_disassembler->dump(patchBuffer);
 209 patchBuffer.didAlreadyDisassemble();
 210 }
 211
 212 MacroAssemblerCodePtr withArityCheck = patchBuffer.locationOf(arityCheck);
 213 CodeRef result = FINALIZE_CODE(patchBuffer, ("Baseline JIT code for WebAssembly"));
 214 m_codeBlock->setJITCode(adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT)));
 215 }
 216
 217 Expression createFromF64ExpressionI32(Expression)
 218 {
 219 loadDouble(temporaryAddress(m_sp - 1), FPRInfo::fpRegT0);
 220 truncateDoubleToInt32(FPRInfo::fpRegT0, GPRInfo::regT0);
 221 store32(GPRInfo::regT0, temporaryAddress(m_sp - 1));
 222 return 1;
 223 }
 224
 225 Expression createFromF64ExpressionF32(Expression)
 226 {
 227 loadDouble(temporaryAddress(m_sp - 1), FPRInfo::fpRegT0);
 228 convertDoubleToFloat(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
 229 storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_sp - 1)); //FIXME: use storeFloat??
 230 return 1;
 231 }
 232
 233 Expression createFromS32ExpressionF64(Expression)
 234 {
 235 convertInt32ToDouble(temporaryAddress(m_sp - 1), FPRInfo::fpRegT0);
 236 storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_sp - 1));
 237 return 1;
 238 }
 239
 240 Expression createFromU32ExpressionF64(Expression)
 241 {
 242 load32(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 243 convertInt64ToDouble(GPRInfo::regT0, FPRInfo::fpRegT0);
 244 storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_sp - 1));
 245 return 1;
 246 }
 247
 248 Expression createUnaryExpressionI32(Expression, WASMOpExpressionI32 op)
 249 {
 250 load32(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 251 switch (op) {
 252 case WASMOpExpressionI32::Neg:
 253 neg32(GPRInfo::regT0);
 254 break;
 255 case WASMOpExpressionI32::BitNot:
 256 xor32(TrustedImm32(-1), GPRInfo::regT0);
 257 break;
 258 case WASMOpExpressionI32::Clz:
 259 countLeadingZeros32(GPRInfo::regT0, GPRInfo::regT0);
 260 break;
 261 case WASMOpExpressionI32::LogicNot: {
 262 // FIXME: seems very inefficient
 263 Jump zero = branchTest32(Zero, GPRInfo::regT0);
 264 move(TrustedImm32(0), GPRInfo::regT0); // FIXME: Use xor32?
 265 Jump end = jump();
 266 zero.link(this);
 267 move(TrustedImm32(1), GPRInfo::regT0);
 268 end.link(this);
 269 break;
 270 }
 271 case WASMOpExpressionI32::Abs: {
 272 Jump end = branchTest32(PositiveOrZero, GPRInfo::regT0);
 273 neg32(GPRInfo::regT0);
 274 end.link(this);
 275 break;
 276 }
 277 default:
 278 ASSERT_NOT_REACHED();
 279 }
 280 store32(GPRInfo::regT0, temporaryAddress(m_sp - 1));
 281 return 1;
 282 }
 283
 284 Expression createUnaryExpressionF64(Expression, WASMOpExpressionF64 op)
 285 {
 286 loadDouble(temporaryAddress(m_sp - 1), FPRInfo::fpRegT0);
 287 switch (op) {
 288 case WASMOpExpressionF64::Neg:
 289 negateDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 290 break;
 291 case WASMOpExpressionF64::Abs:
 292 absDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 293 break;
 294 case WASMOpExpressionF64::Ceil:
 295 callDoubleFunction(ceil, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 296 break;
 297 case WASMOpExpressionF64::Floor:
 298 callDoubleFunction(floor, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 299 break;
 300 case WASMOpExpressionF64::Sqrt:
 301 sqrtDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 302 break;
 303 case WASMOpExpressionF64::Cos:
 304 callDoubleFunction(cos, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 305 break;
 306 case WASMOpExpressionF64::Sin:
 307 callDoubleFunction(sin, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 308 break;
 309 case WASMOpExpressionF64::Tan:
 310 callDoubleFunction(tan, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 311 break;
 312 case WASMOpExpressionF64::ACos:
 313 callDoubleFunction(acos, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 314 break;
 315 case WASMOpExpressionF64::ASin:
 316 callDoubleFunction(asin, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 317 break;
 318 case WASMOpExpressionF64::ATan:
 319 callDoubleFunction(atan, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 320 break;
 321 case WASMOpExpressionF64::Exp:
 322 callDoubleFunction(exp, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 323 break;
 324 case WASMOpExpressionF64::Ln:
 325 callDoubleFunction(log, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 326 break;
 327 default:
 328 ASSERT_NOT_REACHED();
 329 }
 330 storeDouble(FPRInfo::fpRegT1, temporaryAddress(m_sp - 1));
 331 return 1;
 332 }
 333
 334 Expression createBinaryExpressionI32(Expression, Expression, WASMOpExpressionI32 op)
 335 {
 336 load32(temporaryAddress(m_sp - 2), GPRInfo::regT0);
 337 load32(temporaryAddress(m_sp - 1), GPRInfo::regT1);
 338 switch (op) {
 339 case WASMOpExpressionI32::Add:
 340 add32(GPRInfo::regT1, GPRInfo::regT0);
 341 break;
 342 case WASMOpExpressionI32::Sub:
 343 sub32(GPRInfo::regT1, GPRInfo::regT0);
 344 break;
 345 case WASMOpExpressionI32::Mul:
 346 mul32(GPRInfo::regT1, GPRInfo::regT0);
 347 break;
 348 case WASMOpExpressionI32::SDiv:
 349#if CPU(X86) || CPU(X86_64)
 350 // Make sure registers are correct for x86 IDIV instructions.
 351 // ASSERT(regT0 == X86Registers::eax);
 352 // ASSERT(regT1 == X86Registers::edx);
 353 // ASSERT(regT2 == X86Registers::ecx);
 354 // ASSERT(regT3 == X86Registers::ebx);
 355
 356 move(GPRInfo::regT1, GPRInfo::regT2);
 357 m_assembler.cdq();
 358 m_assembler.idivl_r(GPRInfo::regT2);
 359#else
 360#error "WebAssembly not supported on this platform."
 361#endif
 362 break;
 363 case WASMOpExpressionI32::UDiv:
 364#if CPU(X86) || CPU(X86_64)
 365 move(GPRInfo::regT1, GPRInfo::regT2);
 366 xor32(GPRInfo::regT1, GPRInfo::regT1);
 367 m_assembler.divl_r(GPRInfo::regT2);
 368#else
 369#error "WebAssembly not supported on this platform."
 370#endif
 371 break;
 372 case WASMOpExpressionI32::SMod:
 373#if CPU(X86) || CPU(X86_64)
 374 move(GPRInfo::regT1, GPRInfo::regT2);
 375 m_assembler.cdq();
 376 m_assembler.idivl_r(GPRInfo::regT2);
 377 move(GPRInfo::regT1, GPRInfo::regT0);
 378#else
 379#error "WebAssembly not supported on this platform."
 380#endif
 381 break;
 382 case WASMOpExpressionI32::UMod:
 383#if CPU(X86) || CPU(X86_64)
 384 move(GPRInfo::regT1, GPRInfo::regT2);
 385 xor32(GPRInfo::regT1, GPRInfo::regT1);
 386 m_assembler.divl_r(GPRInfo::regT2);
 387 move(GPRInfo::regT1, GPRInfo::regT0);
 388#else
 389#error "WebAssembly not supported on this platform."
 390#endif
 391 break;
 392 case WASMOpExpressionI32::BitOr:
 393 or32(GPRInfo::regT1, GPRInfo::regT0);
 394 break;
 395 case WASMOpExpressionI32::BitAnd:
 396 and32(GPRInfo::regT1, GPRInfo::regT0);
 397 break;
 398 case WASMOpExpressionI32::BitXor:
 399 xor32(GPRInfo::regT1, GPRInfo::regT0);
 400 break;
 401 case WASMOpExpressionI32::LeftShift:
 402 lshift32(GPRInfo::regT1, GPRInfo::regT0);
 403 break;
 404 case WASMOpExpressionI32::ArithmeticRightShift:
 405 rshift32(GPRInfo::regT1, GPRInfo::regT0);
 406 break;
 407 case WASMOpExpressionI32::LogicalRightShift:
 408 urshift32(GPRInfo::regT1, GPRInfo::regT0);
 409 break;
 410 default:
 411 ASSERT_NOT_REACHED();
 412 }
 413 store32(GPRInfo::regT0, temporaryAddress(m_sp - 2));
 414 m_sp--;
 415 return 1;
 416 }
 417
 418 Expression createBinaryExpressionF64(Expression, Expression, WASMOpExpressionF64 op)
 419 {
 420 loadDouble(temporaryAddress(m_sp - 2), FPRInfo::fpRegT0);
 421 loadDouble(temporaryAddress(m_sp - 1), FPRInfo::fpRegT1);
 422 switch (op) {
 423 case WASMOpExpressionF64::Add:
 424 addDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
 425 break;
 426 case WASMOpExpressionF64::Sub:
 427 subDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
 428 break;
 429 case WASMOpExpressionF64::Mul:
 430 mulDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
 431 break;
 432 case WASMOpExpressionF64::Div:
 433 divDouble(FPRInfo::fpRegT1, FPRInfo::fpRegT0);
 434 break;
 435 case WASMOpExpressionF64::ATan2:
 436 callDoubleFunction(atan2, FPRInfo::fpRegT0, FPRInfo::fpRegT1, FPRInfo::fpRegT0);
 437 break;
 438 case WASMOpExpressionF64::Pow:
 439 callDoubleFunction(pow, FPRInfo::fpRegT0, FPRInfo::fpRegT1, FPRInfo::fpRegT0);
 440 break;
 441 default:
 442 ASSERT_NOT_REACHED();
 443 }
 444 storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_sp - 2));
 445 m_sp--;
 446 return 1;
 447 }
 448
 449 int createRelationalI32ExpressionI32(Expression, Expression, WASMOpExpressionI32 op)
 450 {
 451 load32(temporaryAddress(m_sp - 2), GPRInfo::regT0);
 452 load32(temporaryAddress(m_sp - 1), GPRInfo::regT1);
 453 RelationalCondition condition;
 454 switch (op) {
 455 case WASMOpExpressionI32::EqualI32:
 456 condition = Equal;
 457 break;
 458 case WASMOpExpressionI32::NotEqualI32:
 459 condition = NotEqual;
 460 break;
 461 case WASMOpExpressionI32::SLessThanI32:
 462 condition = LessThan;
 463 break;
 464 case WASMOpExpressionI32::ULessThanI32:
 465 condition = Below;
 466 break;
 467 case WASMOpExpressionI32::SLessThanOrEqualI32:
 468 condition = LessThanOrEqual;
 469 break;
 470 case WASMOpExpressionI32::ULessThanOrEqualI32:
 471 condition = BelowOrEqual;
 472 break;
 473 case WASMOpExpressionI32::SGreaterThanI32:
 474 condition = GreaterThan;
 475 break;
 476 case WASMOpExpressionI32::UGreaterThanI32:
 477 condition = Above;
 478 break;
 479 case WASMOpExpressionI32::SGreaterThanOrEqualI32:
 480 condition = GreaterThanOrEqual;
 481 break;
 482 case WASMOpExpressionI32::UGreaterThanOrEqualI32:
 483 condition = AboveOrEqual;
 484 break;
 485 default:
 486 ASSERT_NOT_REACHED();
 487 }
 488 compare32(condition, GPRInfo::regT0, GPRInfo::regT1, GPRInfo::regT0);
 489 store32(GPRInfo::regT0, temporaryAddress(m_sp - 2));
 490 m_sp--;
 491 return 1;
 492 }
 493
 494 int createRelationalF64ExpressionI32(Expression, Expression, WASMOpExpressionI32 op)
 495 {
 496 loadDouble(temporaryAddress(m_sp - 2), FPRInfo::fpRegT0);
 497 loadDouble(temporaryAddress(m_sp - 1), FPRInfo::fpRegT1);
 498 DoubleCondition condition;
 499 switch (op) {
 500 case WASMOpExpressionI32::EqualF64:
 501 condition = DoubleEqual;
 502 break;
 503 case WASMOpExpressionI32::NotEqualF64:
 504 condition = DoubleNotEqual;
 505 break;
 506 case WASMOpExpressionI32::LessThanF64:
 507 condition = DoubleLessThan;
 508 break;
 509 case WASMOpExpressionI32::LessThanOrEqualF64:
 510 condition = DoubleLessThanOrEqual;
 511 break;
 512 case WASMOpExpressionI32::GreaterThanF64:
 513 condition = DoubleGreaterThan;
 514 break;
 515 case WASMOpExpressionI32::GreaterThanOrEqualF64:
 516 condition = DoubleGreaterThanOrEqual;
 517 break;
 518 default:
 519 ASSERT_NOT_REACHED();
 520 }
 521 Jump trueCase = branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
 522 store32(TrustedImm32(0), temporaryAddress(m_sp - 2));
 523 Jump end = jump();
 524 trueCase.link(this);
 525 store32(TrustedImm32(1), temporaryAddress(m_sp - 2));
 526 end.link(this);
 527 m_sp--;
 528 return 1;
 529 }
 530
 531 Expression createLiteralPoolExpressionI32(uint32_t constantIndex)
 532 {
 533 store32(Imm32(m_module->i32Constants()[constantIndex]), temporaryAddress(m_sp));
 534 m_sp++;
 535 return 1;
 536 }
 537
 538 Expression createLiteralPoolExpressionF32(uint32_t constantIndex)
 539 {
 540 store32(Imm32(bitwise_cast<int32_t>(m_module->f32Constants()[constantIndex])), temporaryAddress(m_sp));
 541 m_sp++;
 542 return 1;
 543 }
 544
 545 Expression createLiteralPoolExpressionF64(uint32_t constantIndex)
 546 {
 547 store64(Imm64(bitwise_cast<int64_t>(m_module->f64Constants()[constantIndex])), temporaryAddress(m_sp));
 548 m_sp++;
 549 return 1;
 550 }
 551
 552 Expression createLiteralImmediateExpressionI32(uint32_t immediate)
 553 {
 554 store32(Imm32(immediate), temporaryAddress(m_sp));
 555 m_sp++;
 556 return 1;
 557 }
 558
 559 Expression createLiteralImmediateExpressionF32(float immediate)
 560 {
 561 store32(Imm32(bitwise_cast<int32_t>(immediate)), temporaryAddress(m_sp));
 562 m_sp++;
 563 return 1;
 564 }
 565
 566 Expression createLiteralImmediateExpressionF64(double immediate)
 567 {
 568 store64(Imm64(bitwise_cast<int64_t>(immediate)), temporaryAddress(m_sp));
 569 m_sp++;
 570 return 1;
 571 }
 572
 573 Expression createGetLocalExpressionI32(uint32_t localIndex)
 574 {
 575 load32(localAddress(localIndex), GPRInfo::regT0);
 576 store32(GPRInfo::regT0, temporaryAddress(m_sp));
 577 m_sp++;
 578 return 1;
 579 }
 580
 581 Expression createGetLocalExpressionF32(uint32_t localIndex)
 582 {
 583 load32(localAddress(localIndex), GPRInfo::regT0);
 584 store32(GPRInfo::regT0, temporaryAddress(m_sp));
 585 m_sp++;
 586 return 1;
 587 }
 588
 589 Expression createGetLocalExpressionF64(uint32_t localIndex)
 590 {
 591 // FIXME: Use loadDouble/storeDouble?
 592 load64(localAddress(localIndex), GPRInfo::regT0);
 593 store64(GPRInfo::regT0, temporaryAddress(m_sp));
 594 m_sp++;
 595 return 1;
 596 }
 597
 598 void setLocal(uint32_t localIndex, Expression, WASMType type)
 599 {
 600 switch (type) {
 601 case WASMType::I32:
 602 case WASMType::F32:
 603 load32(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 604 store32(GPRInfo::regT0, localAddress(localIndex));
 605 break;
 606 case WASMType::F64:
 607 load64(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 608 store64(GPRInfo::regT0, localAddress(localIndex));
 609 break;
 610 default:
 611 ASSERT_NOT_REACHED();
 612 }
 613 m_sp--;
 614 }
 615
 616 Expression createSetLocalExpressionI32(uint32_t localIndex, Expression)
 617 {
 618 load32(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 619 store32(GPRInfo::regT0, localAddress(localIndex));
 620 return 1;
 621 }
 622
 623 Expression createSetLocalExpressionF32(uint32_t localIndex, Expression)
 624 {
 625 load32(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 626 store32(GPRInfo::regT0, localAddress(localIndex));
 627 return 1;
 628 }
 629
 630 Expression createSetLocalExpressionF64(uint32_t localIndex, Expression)
 631 {
 632 load64(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 633 store64(GPRInfo::regT0, localAddress(localIndex));
 634 return 1;
 635 }
 636
 637 Expression createGetGlobalExpressionI32(uint32_t globalIndex)
 638 {
 639 move(TrustedImmPtr(m_module->globalVariableAddresses()[globalIndex]), GPRInfo::regT0);
 640 load32(GPRInfo::regT0, GPRInfo::regT0);
 641 store32(GPRInfo::regT0, temporaryAddress(m_sp));
 642 m_sp++;
 643 return 1;
 644 }
 645
 646 Expression createGetGlobalExpressionF32(uint32_t globalIndex)
 647 {
 648 move(TrustedImmPtr(m_module->globalVariableAddresses()[globalIndex]), GPRInfo::regT0);
 649 load32(GPRInfo::regT0, GPRInfo::regT0);
 650 store32(GPRInfo::regT0, temporaryAddress(m_sp));
 651 m_sp++;
 652 return 1;
 653 }
 654
 655 Expression createGetGlobalExpressionF64(uint32_t globalIndex)
 656 {
 657 move(TrustedImmPtr(m_module->globalVariableAddresses()[globalIndex]), GPRInfo::regT0);
 658 load64(GPRInfo::regT0, GPRInfo::regT0);
 659 store64(GPRInfo::regT0, temporaryAddress(m_sp));
 660 m_sp++;
 661 return 1;
 662 }
 663
 664 Expression createSetGlobal(uint32_t globalIndex, Expression, WASMType type, bool isExpression)
 665 {
 666 move(TrustedImmPtr(m_module->globalVariableAddresses()[globalIndex]), GPRInfo::regT0);
 667 switch (type) {
 668 case WASMType::I32:
 669 case WASMType::F32:
 670 load32(temporaryAddress(m_sp - 1), GPRInfo::regT1);
 671 store32(GPRInfo::regT1, GPRInfo::regT0);
 672 break;
 673 case WASMType::F64:
 674 load64(temporaryAddress(m_sp - 1), GPRInfo::regT1);
 675 store64(GPRInfo::regT1, GPRInfo::regT0);
 676 break;
 677 default:
 678 ASSERT_NOT_REACHED();
 679 }
 680 if (!isExpression)
 681 m_sp--;
 682 return 1;
 683 }
 684
 685 void boxArgumentsAndAdjustStackPointer(const Vector<WASMType>& arguments)
 686 {
 687 size_t argumentCount = arguments.size();
 688
 689 int newSP = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), m_numberOfLocals + m_sp + argumentCount) - m_numberOfLocals;
 690
 691 for (size_t i = 0; i < argumentCount; ++i) {
 692 switch (arguments[i]) {
 693 case WASMType::I32:
 694 load32(temporaryAddress(m_sp - argumentCount + i), GPRInfo::regT0);
 695 or64(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
 696 store64(GPRInfo::regT0, temporaryAddress(newSP - i - 1));
 697 break;
 698 case WASMType::F32:
 699 loadDouble(temporaryAddress(m_sp - argumentCount + i), FPRInfo::fpRegT0); //FIXME: use loadFloat
 700 convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
 701 boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
 702 store64(GPRInfo::regT0, temporaryAddress(newSP - i - 1));
 703 break;
 704 case WASMType::F64:
 705 loadDouble(temporaryAddress(m_sp - argumentCount + i), FPRInfo::fpRegT0);
 706 boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
 707 store64(GPRInfo::regT0, temporaryAddress(newSP - i - 1));
 708 break;
 709 default:
 710 ASSERT_NOT_REACHED();
 711 }
 712 }
 713
 714 store64(TrustedImm64(JSValue::encode(jsUndefined())), temporaryAddress(newSP));
 715
 716 addPtr(TrustedImm32(-(newSP + m_numberOfLocals + 3) * 8 - 8), GPRInfo::callFrameRegister, stackPointerRegister); // FIXME: hacky
 717
 718 store32(TrustedImm32(argumentCount + 1), Address(stackPointerRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)));
 719 }
 720
 721 void callAndUnboxResult(const Vector<WASMType>& arguments, WASMExpressionType returnType)
 722 {
 723 size_t argumentCount = arguments.size();
 724
 725 move(GPRInfo::returnValueGPR, GPRInfo::regT0); // regT0 holds callee.
 726 store64(GPRInfo::regT0, Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) - sizeof(CallerFrameAndPC)));
 727
 728 DataLabelPtr addressOfLinkedFunctionCheck;
 729 Jump slowCase = branchPtrWithPatch(NotEqual, GPRInfo::regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(0));
 730
 731 CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
 732 // info->setUpCall(CallLinkInfo::callTypeFor(opcodeID), CodeOrigin(m_bytecodeOffset), regT0);
 733 info->setCalleeGPR(GPRInfo::regT0);
 734 m_callCompilationInfo.append(CallCompilationInfo());
 735 m_callCompilationInfo.last().hotPathBegin = addressOfLinkedFunctionCheck;
 736 m_callCompilationInfo.last().callLinkInfo = info;
 737 m_callCompilationInfo.last().hotPathOther = nearCall();
 738
 739 Jump end = jump();
 740
 741 // --------------
 742
 743 slowCase.link(this);
 744 move(TrustedImmPtr(info), GPRInfo::regT2);
 745 m_callCompilationInfo.last().callReturnLocation = emitNakedCall(m_vm->getCTIStub(linkCallThunkGenerator).code());
 746
 747 // --------------
 748
 749 end.link(this);
 750
 751 m_sp -= argumentCount;
 752
 753 addPtr(TrustedImm32(-m_stackHeight * 8), GPRInfo::callFrameRegister, stackPointerRegister); // FIXME: hacky
 754
 755 switch (returnType) {
 756 case WASMExpressionType::I32:
 757 store32(GPRInfo::returnValueGPR, temporaryAddress(m_sp));
 758 m_sp++;
 759 break;
 760 case WASMExpressionType::F64:
 761 unboxDoubleWithoutAssertions(GPRInfo::returnValueGPR, FPRInfo::fpRegT0);
 762 storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_sp));
 763 m_sp++;
 764 break;
 765 case WASMExpressionType::Void:
 766 break;
 767 default:
 768 ASSERT_NOT_REACHED();
 769 }
 770 }
 771
 772 Expression createCallInternal(uint32_t functionIndex, const WASMSignature& signature, WASMExpressionType returnType)
 773 {
 774 const Vector<WASMType>& arguments = signature.arguments;
 775
 776 boxArgumentsAndAdjustStackPointer(arguments);
 777
 778 if (maxFrameExtentForSlowPathCall)
 779 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
 780 setupArgumentsWithExecState(TrustedImmPtr(m_module), TrustedImm32(functionIndex));
 781 move(TrustedImmPtr(bitwise_cast<void*>(getInternalFunction)), GPRInfo::nonArgGPR0);
 782 call(GPRInfo::nonArgGPR0);
 783 if (maxFrameExtentForSlowPathCall)
 784 addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
 785
 786 // FIXME: Not working.
 787 // JSFunction* function = m_module->function(functionIndex);
 788 // move(TrustedImmPtr(function), GPRInfo::regT0);
 789
 790 callAndUnboxResult(arguments, returnType);
 791 return 1;
 792 }
 793
 794 Expression createCallIndirect(uint32_t functionPointerTableIndex, Expression, const WASMSignature& signature, WASMExpressionType returnType)
 795 {
 796 const Vector<WASMType>& arguments = signature.arguments;
 797
 798 Address offsetAddress = temporaryAddress(m_sp - arguments.size() - 1);
 799
 800 boxArgumentsAndAdjustStackPointer(arguments);
 801
 802 const WASMFunctionPointerTable& functionPointerTable = m_module->functionPointerTables()[functionPointerTableIndex];
 803 const Vector<uint32_t>& elements = functionPointerTable.elements;
 804 const uint32_t* elementData = elements.data();
 805
 806 move(TrustedImmPtr(elementData), GPRInfo::regT0);
 807 load32(offsetAddress, GPRInfo::regT1);
 808 and32(TrustedImm32(elements.size() - 1), GPRInfo::regT1);
 809 BaseIndex address = BaseIndex(GPRInfo::regT0, GPRInfo::regT1, TimesFour);
 810 load32(address, GPRInfo::regT0);
 811
 812 if (maxFrameExtentForSlowPathCall)
 813 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
 814 setupArgumentsWithExecState(TrustedImmPtr(m_module), GPRInfo::regT0);
 815 move(TrustedImmPtr(bitwise_cast<void*>(getInternalFunction)), GPRInfo::nonArgGPR0);
 816 call(GPRInfo::nonArgGPR0);
 817 if (maxFrameExtentForSlowPathCall)
 818 addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
 819
 820 m_sp--;
 821
 822 callAndUnboxResult(arguments, returnType);
 823 return 1;
 824 }
 825
 826 Expression createCallImport(uint32_t functionImportSignatureIndex, const WASMSignature& signature, WASMExpressionType returnType)
 827 {
 828 const Vector<WASMType>& arguments = signature.arguments;
 829
 830 boxArgumentsAndAdjustStackPointer(arguments);
 831
 832 const WASMFunctionImportSignature& functionImportSignature = m_module->functionImportSignatures()[functionImportSignatureIndex];
 833 uint32_t functionImportIndex = functionImportSignature.functionImportIndex;
 834
 835 if (maxFrameExtentForSlowPathCall)
 836 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
 837 setupArgumentsWithExecState(TrustedImmPtr(m_module), TrustedImm32(functionImportIndex));
 838 move(TrustedImmPtr(bitwise_cast<void*>(getImportedFunction)), GPRInfo::nonArgGPR0);
 839 call(GPRInfo::nonArgGPR0);
 840 if (maxFrameExtentForSlowPathCall)
 841 addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
 842
 843 callAndUnboxResult(arguments, returnType);
 844 return 1;
 845 }
 846
 847 Expression createLoad(const MemoryAddress& memoryAddress, WASMExpressionType expressionType, WASMMemoryType memoryType, bool signExtended)
 848 {
 849 /*
 850 if (maxFrameExtentForSlowPathCall)
 851 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
 852 setupArguments(TrustedImmPtr(m_module));
 853 move(TrustedImmPtr(bitwise_cast<void*>(getArrayBufferData)), GPRInfo::nonArgGPR0);
 854 call(GPRInfo::nonArgGPR0);
 855 if (maxFrameExtentForSlowPathCall)
 856 addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
 857 */
 858
 859 // FIXME: Safe?
 860 const void* arrayBufferData = m_module->arrayBuffer()->impl()->data();
 861 move(TrustedImmPtr(arrayBufferData), GPRInfo::regT0);
 862
 863 if (memoryAddress.hasImmediateIndex)
 864 move(Imm32(memoryAddress.immediateIndex), GPRInfo::regT1);
 865 else {
 866 load32(temporaryAddress(m_sp - 1), GPRInfo::regT1);
 867 m_sp--;
 868 }
 869 // FIXME: Check for out-of-bounds access.
 870 BaseIndex address = BaseIndex(GPRInfo::regT0, GPRInfo::regT1, TimesOne, memoryAddress.offset);
 871
 872 // FIXME: Check bounds.
 873 switch (expressionType) {
 874 case WASMExpressionType::I32:
 875 switch (memoryType) {
 876 case WASMMemoryType::I8:
 877 if (signExtended)
 878 load8SignedExtendTo32(address, GPRInfo::regT2);
 879 else
 880 load8(address, GPRInfo::regT2);
 881 break;
 882 case WASMMemoryType::I16:
 883 if (signExtended)
 884 load16SignedExtendTo32(address, GPRInfo::regT2);
 885 else
 886 load16(address, GPRInfo::regT2);
 887 break;
 888 case WASMMemoryType::I32:
 889 load32(address, GPRInfo::regT2);
 890 break;
 891 default:
 892 ASSERT_NOT_REACHED();
 893 }
 894 store32(GPRInfo::regT2, temporaryAddress(m_sp));
 895 break;
 896 case WASMExpressionType::F64:
 897 ASSERT(memoryType == WASMMemoryType::F64);
 898 loadDouble(address, FPRInfo::fpRegT0);
 899 storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_sp));
 900 break;
 901 default:
 902 ASSERT_NOT_REACHED();
 903 }
 904 m_sp++;
 905 return 1;
 906 }
 907
 908 Expression createStore(const MemoryAddress& memoryAddress, WASMExpressionType expressionType, WASMMemoryType memoryType, Expression, bool isExpression)
 909 {
 910 /*
 911 if (maxFrameExtentForSlowPathCall)
 912 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
 913 setupArguments(TrustedImmPtr(m_module));
 914 move(TrustedImmPtr(bitwise_cast<void*>(getArrayBufferData)), GPRInfo::nonArgGPR0);
 915 call(GPRInfo::nonArgGPR0);
 916 if (maxFrameExtentForSlowPathCall)
 917 addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
 918 */
 919
 920 // FIXME: Safe?
 921 const void* arrayBufferData = m_module->arrayBuffer()->impl()->data();
 922 move(TrustedImmPtr(arrayBufferData), GPRInfo::regT0);
 923
 924 if (memoryAddress.hasImmediateIndex)
 925 move(Imm32(memoryAddress.immediateIndex), GPRInfo::regT1);
 926 else
 927 load32(temporaryAddress(m_sp - 2), GPRInfo::regT1);
 928 // FIXME: Check for out-of-bounds access.
 929 BaseIndex address = BaseIndex(GPRInfo::regT0, GPRInfo::regT1, TimesOne, memoryAddress.offset);
 930
 931 // FIXME: Check bounds.
 932 switch (expressionType) {
 933 case WASMExpressionType::I32:
 934 load32(temporaryAddress(m_sp - 1), GPRInfo::regT2);
 935 switch (memoryType) {
 936 case WASMMemoryType::I8:
 937 store8(GPRInfo::regT2, address);
 938 break;
 939 case WASMMemoryType::I16:
 940 store16(GPRInfo::regT2, address);
 941 break;
 942 case WASMMemoryType::I32:
 943 store32(GPRInfo::regT2, address);
 944 break;
 945 default:
 946 ASSERT_NOT_REACHED();
 947 }
 948 break;
 949 case WASMExpressionType::F64:
 950 ASSERT(memoryType == WASMMemoryType::F64);
 951 loadDouble(temporaryAddress(m_sp - 1), FPRInfo::fpRegT0);
 952 storeDouble(FPRInfo::fpRegT0, address);
 953 break;
 954 default:
 955 ASSERT_NOT_REACHED();
 956 }
 957
 958 m_sp--;
 959 if (!memoryAddress.hasImmediateIndex)
 960 m_sp--;
 961
 962 if (isExpression) {
 963 // TODO: If hasImmediateIndex is true, then the result is already on the top of the stack.
 964 switch (expressionType) {
 965 case WASMExpressionType::I32:
 966 store32(GPRInfo::regT2, temporaryAddress(m_sp));
 967 break;
 968 case WASMExpressionType::F64:
 969 storeDouble(FPRInfo::fpRegT0, temporaryAddress(m_sp));
 970 break;
 971 default:
 972 ASSERT_NOT_REACHED();
 973 }
 974 m_sp++;
 975 }
 976 return 1;
 977 }
 978
 979 void returnStatement(Expression, WASMExpressionType returnType)
 980 {
 981 switch (returnType) {
 982 case WASMExpressionType::I32:
 983 load32(temporaryAddress(m_sp - 1), GPRInfo::returnValueGPR);
 984 or64(GPRInfo::tagTypeNumberRegister, GPRInfo::returnValueGPR);
 985 m_sp--;
 986 break;
 987 case WASMExpressionType::F32:
 988 loadDouble(temporaryAddress(m_sp - 1), FPRInfo::fpRegT0); // FIXME: This loads 64 bits!
 989 convertFloatToDouble(FPRInfo::fpRegT0, FPRInfo::fpRegT0);
 990 boxDouble(FPRInfo::fpRegT0, GPRInfo::returnValueGPR);
 991 m_sp--;
 992 break;
 993 case WASMExpressionType::F64:
 994 loadDouble(temporaryAddress(m_sp - 1), FPRInfo::fpRegT0);
 995 boxDouble(FPRInfo::fpRegT0, GPRInfo::returnValueGPR);
 996 m_sp--;
 997 break;
 998 case WASMExpressionType::Void:
 999 break;
 1000 default:
 1001 ASSERT_NOT_REACHED();
 1002 }
 1003
 1004 deallocateSpaceOnStack();
 1005 emitFunctionEpilogue();
 1006 ret();
 1007 }
 1008
 1009 //FIXME: Rename these
 1010 Jump jitJump()
 1011 {
 1012 return jump();
 1013 }
 1014
 1015 void jitJump(Label label)
 1016 {
 1017 jump(label);
 1018 }
 1019
 1020 Label jitLabel()
 1021 {
 1022 return label();
 1023 }
 1024
 1025 Jump jitBranchIfZero(Expression)
 1026 {
 1027 load32(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 1028 Jump jump = branchTest32(Zero, GPRInfo::regT0);
 1029 m_sp--;
 1030 return jump;
 1031 }
 1032
 1033 Jump jitBranchIfNonZero(Expression)
 1034 {
 1035 load32(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 1036 Jump jump = branchTest32(NonZero, GPRInfo::regT0);
 1037 m_sp--;
 1038 return jump;
 1039 }
 1040
 1041 void generateSwitchTable(Expression, const Vector<int32_t>& cases, bool hasDefault, const Vector<Label>& labels)
 1042 {
 1043 load32(temporaryAddress(m_sp - 1), GPRInfo::regT0);
 1044 for (size_t i = 0; i < cases.size(); ++i) {
 1045 Jump jmp = branch32(Equal, GPRInfo::regT0, Imm32(cases[i]));
 1046 jmp.linkTo(labels[i], this);
 1047 }
 1048 if (hasDefault) {
 1049 ASSERT(labels.size() == cases.size() + 1);
 1050 jump(labels.last());
 1051 }
 1052 m_sp--;
 1053 }
 1054
 1055 void jitLinkJump(Jump jump)
 1056 {
 1057 jump.link(this);
 1058 }
 1059
 1060 void jitLinkJumpToLabel(Jump jump, Label label)
 1061 {
 1062 jump.linkTo(label, this);
 1063 }
 1064
 1065 void pop() // FIXME: This seems hacky.
 1066 {
 1067 m_sp--;
 1068 }
 1069
 1070 void startLoop()
 1071 {
 1072 m_breakScopes.append(JumpScope());
 1073 m_continueScopes.append(JumpScope());
 1074 }
 1075
 1076 void endLoop()
 1077 {
 1078 m_breakScopes.removeLast();
 1079 m_continueScopes.removeLast();
 1080 }
 1081
 1082 void startSwitch()
 1083 {
 1084 m_breakScopes.append(JumpScope());
 1085 }
 1086
 1087 void endSwitch()
 1088 {
 1089 m_breakScopes.removeLast();
 1090 }
 1091
 1092 void linkBreak()
 1093 {
 1094 m_breakScopes.last().link(this);
 1095 }
 1096
 1097 void linkContinue()
 1098 {
 1099 m_continueScopes.last().link(this);
 1100 }
 1101
 1102 void breakStatement()
 1103 {
 1104 m_breakScopes.last().jump(this);
 1105 }
 1106
 1107 void continueStatement()
 1108 {
 1109 m_continueScopes.last().jump(this);
 1110 }
 1111
 1112 void startLabel()
 1113 {
 1114 m_breakLabelScopes.append(JumpScope());
 1115 m_continueLabelScopes.append(JumpScope());
 1116
 1117 m_continueLabelScopes.last().link(this);
 1118 }
 1119
 1120 void endLabel()
 1121 {
 1122 m_breakLabelScopes.last().link(this);
 1123
 1124 m_breakLabelScopes.removeLast();
 1125 m_continueLabelScopes.removeLast();
 1126 }
 1127
 1128 void breakLabelStatement(uint32_t labelIndex)
 1129 {
 1130 ASSERT(labelIndex < m_breakLabelScopes.size());
 1131 m_breakLabelScopes[labelIndex].jump(this);
 1132 }
 1133
 1134 void continueLabelStatement(uint32_t labelIndex)
 1135 {
 1136 ASSERT(labelIndex < m_continueLabelScopes.size());
 1137 m_continueLabelScopes[labelIndex].jump(this);
 1138 }
 1139
 1140private:
 1141 void callDoubleFunction(double (*function)(double), FPRegisterID src, FPRegisterID dst)
 1142 {
 1143 if (maxFrameExtentForSlowPathCall)
 1144 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
 1145 setupArguments(src);
 1146 move(TrustedImmPtr(bitwise_cast<void*>(function)), GPRInfo::nonArgGPR0);
 1147 call(GPRInfo::nonArgGPR0);
 1148 if (maxFrameExtentForSlowPathCall)
 1149 addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
 1150
 1151 // FIXME: only works on x86
 1152 moveDouble(FPRInfo::returnValueFPR, dst);
 1153 }
 1154
 1155 void callDoubleFunction(double (*function)(double, double), FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
 1156 {
 1157 if (maxFrameExtentForSlowPathCall)
 1158 addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister);
 1159 setupArguments(src1, src2);
 1160 move(TrustedImmPtr(bitwise_cast<void*>(function)), GPRInfo::nonArgGPR0);
 1161 call(GPRInfo::nonArgGPR0);
 1162 if (maxFrameExtentForSlowPathCall)
 1163 addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
 1164
 1165 // FIXME: only works on x86
 1166 moveDouble(FPRInfo::returnValueFPR, dst);
 1167 }
 1168
 1169 void allocateSpaceOnStack()
 1170 {
 1171 // TODO: Check for stack overflow.
 1172 addPtr(TrustedImm32(-m_stackHeight * 8), stackPointerRegister);
 1173 }
 1174
 1175 void deallocateSpaceOnStack()
 1176 {
 1177 addPtr(TrustedImm32(m_stackHeight * 8), stackPointerRegister);
 1178 }
 1179
 1180 Address localAddress(int i) const // FIXME: Is this correct?
 1181 {
 1182 return Address(GPRInfo::callFrameRegister, -i * 8 - 8);
 1183 }
 1184
 1185 Address temporaryAddress(int i) const // FIXME: Is this correct?
 1186 {
 1187 return Address(GPRInfo::callFrameRegister, -(i + m_numberOfLocals) * 8 - 8);
 1188 }
 1189
 1190 Call emitNakedCall(CodePtr function)
 1191 {
 1192 Call nakedCall = nearCall();
 1193 m_calls.append(std::make_pair(nakedCall, function.executableAddress()));
 1194 return nakedCall;
 1195 }
 1196
 1197 const JSWASMModule* m_module;
 1198 int m_stackHeight;
 1199
 1200 int m_sp; // FIXME: Rename
 1201
 1202 uint32_t m_numberOfLocals; // ??
 1203
 1204 Label m_beginLabel;
 1205 // JumpList m_outOfBoundsJumpList;
 1206
 1207 Vector<JumpScope> m_breakScopes;
 1208 Vector<JumpScope> m_continueScopes;
 1209 Vector<JumpScope> m_breakLabelScopes;
 1210 Vector<JumpScope> m_continueLabelScopes;
 1211
 1212 std::unique_ptr<JITDisassembler> m_disassembler;
 1213 Vector<std::pair<Call, void*>> m_calls;
 1214 Vector<CallCompilationInfo> m_callCompilationInfo;
 1215};
 1216
 1217} // namespace JSC
 1218
 1219#endif // ENABLE(WEBASSEMBLY)
 1220
 1221#endif // WASMCodeGenerator_h

Source/JavaScriptCore/wasm/WASMConstants.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26/*
 27 Licensed under the Apache License, Version 2.0 (the "License");
 28 you may not use this file except in compliance with the License.
 29 You may obtain a copy of the License at
 30
 31 http://www.apache.org/licenses/LICENSE-2.0
 32
 33 Unless required by applicable law or agreed to in writing, software
 34 distributed under the License is distributed on an "AS IS" BASIS,
 35 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 36 See the License for the specific language governing permissions and
 37 limitations under the License.
 38*/
 39
 40#ifndef WASMConstants_h
 41#define WASMConstants_h
 42
 43#if ENABLE(WEBASSEMBLY)
 44
 45#include <wtf/Vector.h>
 46
 47namespace JSC {
 48
 49static const uint32_t wasmMagicNumber = 0x6d736177;
 50
 51enum class WASMOpStatement : uint8_t {
 52 SetLocal,
 53 SetGlobal,
 54 I32Store8,
 55 I32StoreOffset8,
 56 I32Store16,
 57 I32StoreOffset16,
 58 I32Store32,
 59 I32StoreOffset32,
 60 F32Store,
 61 F32StoreOffset,
 62 F64Store,
 63 F64StoreOffset,
 64 CallInternal,
 65 CallIndirect,
 66 CallImport,
 67 Return,
 68 Block,
 69 IfThen,
 70 IfElse,
 71 While,
 72 Do,
 73 Label,
 74 Break,
 75 BreakLabel,
 76 Continue,
 77 ContinueLabel,
 78 Switch,
 79
 80 Bad
 81};
 82
 83enum class WASMOpStatementWithImmediate : uint8_t {
 84 SetLocal,
 85 SetGlobal,
 86
 87 Bad
 88};
 89
 90enum class WASMSwitchCase : uint8_t {
 91 Case0,
 92 Case1,
 93 CaseN,
 94 Default0,
 95 Default1,
 96 DefaultN,
 97 NumberOfSwitchCases
 98};
 99
 100enum class WASMOpExpressionI32 : uint8_t {
 101 LitPool,
 102 LitImm,
 103 GetLocal,
 104 GetGlobal,
 105 SetLocal,
 106 SetGlobal,
 107 SLoad8,
 108 SLoadOffset8,
 109 ULoad8,
 110 ULoadOffset8,
 111 SLoad16,
 112 SLoadOffset16,
 113 ULoad16,
 114 ULoadOffset16,
 115 Load32,
 116 LoadOffset32,
 117 Store8,
 118 StoreOffset8,
 119 Store16,
 120 StoreOffset16,
 121 Store32,
 122 StoreOffset32,
 123 CallInternal,
 124 CallIndirect,
 125 CallImport,
 126 Conditional,
 127 Comma,
 128 FromF32,
 129 FromF64,
 130 Neg,
 131 Add,
 132 Sub,
 133 Mul,
 134 SDiv,
 135 UDiv,
 136 SMod,
 137 UMod,
 138 BitNot,
 139 BitOr,
 140 BitAnd,
 141 BitXor,
 142 LeftShift,
 143 ArithmeticRightShift,
 144 LogicalRightShift,
 145 Clz,
 146 LogicNot,
 147 EqualI32,
 148 EqualF32,
 149 EqualF64,
 150 NotEqualI32,
 151 NotEqualF32,
 152 NotEqualF64,
 153 SLessThanI32,
 154 ULessThanI32,
 155 LessThanF32,
 156 LessThanF64,
 157 SLessThanOrEqualI32,
 158 ULessThanOrEqualI32,
 159 LessThanOrEqualF32,
 160 LessThanOrEqualF64,
 161 SGreaterThanI32,
 162 UGreaterThanI32,
 163 GreaterThanF32,
 164 GreaterThanF64,
 165 SGreaterThanOrEqualI32,
 166 UGreaterThanOrEqualI32,
 167 GreaterThanOrEqualF32,
 168 GreaterThanOrEqualF64,
 169 SMin,
 170 UMin,
 171 SMax,
 172 UMax,
 173 Abs,
 174
 175 Bad
 176};
 177
 178enum class WASMOpExpressionI32WithImmediate : uint8_t {
 179 LitPool,
 180 LitImm,
 181 GetLocal,
 182
 183 Bad
 184};
 185
 186enum class WASMOpExpressionF32 : uint8_t {
 187 LitPool,
 188 LitImm,
 189 GetLocal,
 190 GetGlobal,
 191 SetLocal,
 192 SetGlobal,
 193 Load,
 194 LoadOffset,
 195 Store,
 196 StoreOffset,
 197 CallInternal,
 198 CallIndirect,
 199 Conditional,
 200 Comma,
 201 FromS32,
 202 FromU32,
 203 FromF64,
 204 Neg,
 205 Add,
 206 Sub,
 207 Mul,
 208 Div,
 209 Abs,
 210 Ceil,
 211 Floor,
 212 Sqrt,
 213
 214 Bad
 215};
 216
 217enum class WASMOpExpressionF32WithImmediate : uint8_t {
 218 LitPool,
 219 GetLocal,
 220
 221 Bad
 222};
 223
 224enum class WASMOpExpressionF64 : uint8_t {
 225 LitPool,
 226 LitImm,
 227 GetLocal,
 228 GetGlobal,
 229 SetLocal,
 230 SetGlobal,
 231 Load,
 232 LoadOffset,
 233 Store,
 234 StoreOffset,
 235 CallInternal,
 236 CallIndirect,
 237 CallImport,
 238 Conditional,
 239 Comma,
 240 FromS32,
 241 FromU32,
 242 FromF32,
 243 Neg,
 244 Add,
 245 Sub,
 246 Mul,
 247 Div,
 248 Mod,
 249 Min,
 250 Max,
 251 Abs,
 252 Ceil,
 253 Floor,
 254 Sqrt,
 255 Cos,
 256 Sin,
 257 Tan,
 258 ACos,
 259 ASin,
 260 ATan,
 261 ATan2,
 262 Exp,
 263 Ln,
 264 Pow,
 265
 266 Bad
 267};
 268
 269enum class WASMOpExpressionF64WithImmediate : uint8_t {
 270 LitPool,
 271 GetLocal,
 272
 273 Bad
 274};
 275
 276enum class WASMOpExpressionVoid : uint8_t {
 277 CallInternal,
 278 CallIndirect,
 279 CallImport,
 280
 281 Bad
 282};
 283
 284enum class WASMVarTypes : uint8_t {
 285 I32 = 0x1,
 286 F32 = 0x2,
 287 F64 = 0x4,
 288};
 289
 290inline bool operator&(WASMVarTypes lhs, WASMVarTypes rhs) { return bool(uint8_t(lhs) & uint8_t(rhs)); }
 291
 292enum class WASMVarTypesWithImmediate : uint8_t {
 293 OnlyI32
 294};
 295
 296enum class WASMExportFormat : uint8_t {
 297 Default,
 298 Record,
 299 NumberOfExportFormats
 300};
 301
 302static const uint8_t hasImmediateFlag = 0x80;
 303static_assert(uint8_t(WASMOpExpressionI32::Bad) <= hasImmediateFlag, "MSB reserved to distinguish WASMOpExpressionI32 from WASMOpExpressionI32WithImmediate");
 304static_assert(uint8_t(WASMOpExpressionF32::Bad) <= hasImmediateFlag, "MSB reserved to distinguish WASMOpExpressionF32 from WASMOpExpressionF32WithImmediate");
 305static_assert(uint8_t(WASMOpExpressionF64::Bad) <= hasImmediateFlag, "MSB reserved to distinguish WASMOpExpressionF64 from WASMOpExpressionF64WithImmediate");
 306
 307static const unsigned opWithImmediateBits = 2;
 308static const uint32_t opWithImmediateLimit = 1 << opWithImmediateBits;
 309static_assert(uint8_t(WASMOpExpressionI32WithImmediate::Bad) <= opWithImmediateLimit, "WASMOpExpressionI32WithImmediate op fits");
 310static_assert(uint8_t(WASMOpExpressionF32WithImmediate::Bad) <= opWithImmediateLimit, "WASMOpExpressionF32WithImmediate op fits");
 311static_assert(uint8_t(WASMOpExpressionF64WithImmediate::Bad) <= opWithImmediateLimit, "WASMOpExpressionF64WithImmediate op fits");
 312
 313static const unsigned immediateBits = 5;
 314static const uint32_t immediateLimit = 1 << immediateBits;
 315static_assert((1 + opWithImmediateBits + immediateBits) == 8, "Bits of immediate op should add up to a byte");
 316
 317} // namespace JSC
 318
 319#endif // ENABLE(WEBASSEMBLY)
 320
 321#endif // WASMConstants_h

Source/JavaScriptCore/wasm/WASMFormat.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef WASMFormat_h
 27#define WASMFormat_h
 28
 29#if ENABLE(WEBASSEMBLY)
 30
 31#include <wtf/Vector.h>
 32#include <wtf/text/WTFString.h>
 33
 34namespace JSC {
 35
 36enum class WASMType : uint8_t {
 37 I32,
 38 F32,
 39 F64,
 40 NumberOfTypes
 41};
 42
 43enum class WASMExpressionType : uint8_t {
 44 I32,
 45 F32,
 46 F64,
 47 Void,
 48 NumberOfExpressionTypes
 49};
 50
 51enum class WASMMemoryType : uint8_t {
 52 I8,
 53 I16,
 54 I32,
 55 F32,
 56 F64
 57};
 58
 59struct WASMSignature {
 60 WASMExpressionType returnType;
 61 Vector<WASMType> arguments;
 62};
 63
 64struct WASMFunctionImport {
 65 String functionName;
 66};
 67
 68struct WASMFunctionImportSignature {
 69 uint32_t signatureIndex;
 70 uint32_t functionImportIndex;
 71};
 72
 73struct WASMFunctionDeclaration {
 74 uint32_t signatureIndex;
 75};
 76
 77struct WASMFunctionPointerTable {
 78 uint32_t signatureIndex;
 79 Vector<uint32_t> elements;
 80};
 81
 82} // namespace JSC
 83
 84#endif // ENABLE(WEBASSEMBLY)
 85
 86#endif // WASMFormat_h

Source/JavaScriptCore/wasm/WASMFunctionParser.cpp

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "WASMFunctionParser.h"
 28
 29#if ENABLE(WEBASSEMBLY)
 30
 31#include "JSWASMModule.h"
 32#include "WASMCodeGenerator.h"
 33#include "WASMConstants.h"
 34#include "WASMSyntaxChecker.h"
 35
 36#define UNUSED 1 // FIXME: Should depend on the context!
 37
 38#define PROPAGATE_ERROR() do { if (!m_errorMessage.isNull()) return 0; } while (0)
 39#define FAIL_WITH_MESSAGE(errorMessage) do { m_errorMessage = errorMessage; return 0; } while (0)
 40#define READ_UINT32_OR_FAIL(x, errorMessage) do { if (!m_reader.readUInt32(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 41#define READ_FLOAT_OR_FAIL(x, errorMessage) do { if (!m_reader.readFloat(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 42#define READ_DOUBLE_OR_FAIL(x, errorMessage) do { if (!m_reader.readDouble(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 43#define READ_STRING_OR_FAIL(x, errorMessage) do { if (!m_reader.readString(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 44#define READ_COMPACT_UINT32_OR_FAIL(x, errorMessage) do { if (!m_reader.readCompactUInt32(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 45#define READ_COMPACT_INT32_OR_FAIL(x, errorMessage) do { if (!m_reader.readCompactInt32(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 46#define READ_EXPRESSION_TYPE_OR_FAIL(x, errorMessage) do { if (!m_reader.readExpressionType(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 47#define READ_SWITCH_CASE_OR_FAIL(x, errorMessage) do { if (!m_reader.readSwitchCase(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 48#define FAIL_IF_FALSE(condition, errorMessage) do {\
 49 if (!(condition))\
 50 FAIL_WITH_MESSAGE(errorMessage);\
 51} while (0)
 52
 53namespace JSC {
 54
 55bool WASMFunctionParser::checkSyntax(const JSWASMModule* module, const SourceCode& source, size_t functionIndex, unsigned startOffsetInSource, unsigned& endOffsetInSource, unsigned& stackHeight, String& errorMessage)
 56{
 57 WASMFunctionParser parser(module, source);
 58 WASMSyntaxChecker syntaxChecker;
 59 parser.parseFunction(syntaxChecker, functionIndex, startOffsetInSource);
 60 if (!parser.m_errorMessage.isNull()) {
 61 errorMessage = parser.m_errorMessage;
 62 return false;
 63 }
 64 endOffsetInSource = parser.m_reader.index();
 65 stackHeight = syntaxChecker.maxStackTop();
 66 return true;
 67}
 68
 69void WASMFunctionParser::generateCode(VM* vm, CodeBlock* codeBlock, const JSWASMModule* module, const SourceCode& source, size_t functionIndex, unsigned startOffsetInSource, unsigned stackHeight)
 70{
 71 WASMFunctionParser parser(module, source);
 72 WASMCodeGenerator codeGenerator(vm, codeBlock, module, stackHeight);
 73 parser.parseFunction(codeGenerator, functionIndex, startOffsetInSource);
 74}
 75
 76template <class Context>
 77bool WASMFunctionParser::parseFunction(Context& context, size_t functionIndex, unsigned startOffsetInSource)
 78{
 79 m_reader.setIndex(startOffsetInSource);
 80
 81 const WASMSignature& signature = m_module->signatures()[m_module->functionDeclarations()[functionIndex].signatureIndex];
 82
 83 m_returnType = signature.returnType;
 84
 85 parseLocalVariables();
 86 PROPAGATE_ERROR();
 87
 88 initializeLocalTypes(signature);
 89 context.startFunction(signature, m_numberOfI32Vars, m_numberOfF32Vars, m_numberOfF64Vars);
 90
 91 parseStatementList(context);
 92 PROPAGATE_ERROR();
 93
 94 context.endFunction();
 95
 96 return true;
 97}
 98
 99void WASMFunctionParser::initializeLocalTypes(const WASMSignature& signature)
 100{
 101 const Vector<WASMType>& arguments = signature.arguments;
 102 for (size_t argIndex = 0; argIndex < arguments.size(); ++argIndex)
 103 m_localTypes.append(arguments[argIndex]);
 104
 105 for (uint32_t i = 0; i < m_numberOfI32Vars; ++i)
 106 m_localTypes.append(WASMType::I32);
 107 for (uint32_t i = 0; i < m_numberOfF32Vars; ++i)
 108 m_localTypes.append(WASMType::F32);
 109 for (uint32_t i = 0; i < m_numberOfF64Vars; ++i)
 110 m_localTypes.append(WASMType::F64);
 111}
 112
 113bool WASMFunctionParser::parseLocalVariables()
 114{
 115 m_numberOfI32Vars = 0;
 116 m_numberOfF32Vars = 0;
 117 m_numberOfF64Vars = 0;
 118
 119 WASMVarTypes varTypes;
 120 WASMVarTypesWithImmediate varTypesWithImmediate;
 121 uint8_t immediate;
 122 if (m_reader.readCode(&varTypes, &varTypesWithImmediate, &immediate)) {
 123 if (varTypes & WASMVarTypes::I32)
 124 READ_COMPACT_UINT32_OR_FAIL(m_numberOfI32Vars, "Cannot read the number of int32 local variables.");
 125 if (varTypes & WASMVarTypes::F32)
 126 READ_COMPACT_UINT32_OR_FAIL(m_numberOfF32Vars, "Cannot read the number of float32 local variables.");
 127 if (varTypes & WASMVarTypes::F64)
 128 READ_COMPACT_UINT32_OR_FAIL(m_numberOfF64Vars, "Cannot read the number of float64 local variables.");
 129 } else
 130 m_numberOfI32Vars = immediate;
 131 return true;
 132}
 133
 134template <class Context>
 135ContextStatement WASMFunctionParser::parseStatement(Context& context)
 136{
 137 WASMOpStatement op;
 138 WASMOpStatementWithImmediate opWithImmediate;
 139 uint8_t immediate;
 140 if (m_reader.readCode(&op, &opWithImmediate, &immediate)) {
 141 switch (op) {
 142 case WASMOpStatement::SetLocal:
 143 parseSetLocalStatement(context);
 144 break;
 145 case WASMOpStatement::SetGlobal:
 146 parseSetGlobalStatement(context);
 147 break;
 148 case WASMOpStatement::I32Store8:
 149 case WASMOpStatement::I32StoreOffset8:
 150 case WASMOpStatement::I32Store16:
 151 case WASMOpStatement::I32StoreOffset16:
 152 case WASMOpStatement::I32Store32:
 153 case WASMOpStatement::I32StoreOffset32:
 154 case WASMOpStatement::F32Store:
 155 case WASMOpStatement::F32StoreOffset:
 156 case WASMOpStatement::F64Store:
 157 case WASMOpStatement::F64StoreOffset:
 158 parseStoreStatement(context, op);
 159 break;
 160 case WASMOpStatement::CallInternal:
 161 parseCallInternalStatement(context);
 162 break;
 163 case WASMOpStatement::CallIndirect:
 164 parseCallIndirectStatement(context);
 165 break;
 166 case WASMOpStatement::CallImport:
 167 parseCallImportStatement(context);
 168 break;
 169 case WASMOpStatement::Return:
 170 parseReturnStatement(context);
 171 break;
 172 case WASMOpStatement::Block:
 173 parseBlockStatement(context);
 174 break;
 175 case WASMOpStatement::IfThen:
 176 parseIfStatement(context);
 177 break;
 178 case WASMOpStatement::IfElse:
 179 parseIfElseStatement(context);
 180 break;
 181 case WASMOpStatement::While:
 182 parseWhileStatement(context);
 183 break;
 184 case WASMOpStatement::Do:
 185 parseDoStatement(context);
 186 break;
 187 case WASMOpStatement::Label:
 188 parseLabelStatement(context);
 189 break;
 190 case WASMOpStatement::Break:
 191 parseBreakStatement(context);
 192 break;
 193 case WASMOpStatement::BreakLabel:
 194 parseBreakLabelStatement(context);
 195 break;
 196 case WASMOpStatement::Continue:
 197 parseContinueStatement(context);
 198 break;
 199 case WASMOpStatement::ContinueLabel:
 200 parseContinueLabelStatement(context);
 201 break;
 202 case WASMOpStatement::Switch:
 203 parseSwitchStatement(context);
 204 break;
 205 default:
 206 printf("op = %d\n", (int)op);
 207 RELEASE_ASSERT_NOT_REACHED();
 208 }
 209 } else {
 210 switch (opWithImmediate) {
 211 case WASMOpStatementWithImmediate::SetLocal:
 212 parseSetLocalStatement(context, immediate);
 213 break;
 214 case WASMOpStatementWithImmediate::SetGlobal:
 215 parseSetGlobalStatement(context, immediate);
 216 break;
 217 default:
 218 ASSERT_NOT_REACHED();
 219 }
 220 }
 221 return UNUSED;
 222}
 223
 224template <class Context>
 225ContextStatement WASMFunctionParser::parseSetLocalStatement(Context& context, uint32_t localIndex)
 226{
 227 FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local variable index is incorrect.");
 228 WASMType type = m_localTypes[localIndex];
 229 ContextExpression expression = parseExpression(context, WASMExpressionType(type));
 230 context.setLocal(localIndex, expression, type);
 231 return UNUSED;
 232}
 233
 234template <class Context>
 235ContextStatement WASMFunctionParser::parseSetLocalStatement(Context& context)
 236{
 237 uint32_t localIndex;
 238 READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index.");
 239 parseSetLocalStatement(context, localIndex);
 240 return UNUSED;
 241}
 242
 243template <class Context>
 244ContextStatement WASMFunctionParser::parseSetGlobalStatement(Context& context, uint32_t globalIndex)
 245{
 246 FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect.");
 247 WASMType type = m_module->globalVariableTypes()[globalIndex];
 248 ContextExpression expression = parseExpression(context, WASMExpressionType(type));
 249 PROPAGATE_ERROR();
 250 context.createSetGlobal(globalIndex, expression, type, false);
 251 return UNUSED;
 252}
 253
 254template <class Context>
 255ContextStatement WASMFunctionParser::parseSetGlobalStatement(Context& context)
 256{
 257 uint32_t globalIndex;
 258 READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index.");
 259 parseSetGlobalStatement(context, globalIndex);
 260 return UNUSED;
 261}
 262
 263template <class Context>
 264ContextStatement WASMFunctionParser::parseStoreStatement(Context& context, WASMOpStatement op)
 265{
 266 WASMExpressionType expressionType;
 267 WASMMemoryType memoryType;
 268 bool hasOffset;
 269 switch (op) {
 270 case WASMOpStatement::I32Store8:
 271 expressionType = WASMExpressionType::I32;
 272 memoryType = WASMMemoryType::I8;
 273 hasOffset = false;
 274 break;
 275 case WASMOpStatement::I32StoreOffset8:
 276 expressionType = WASMExpressionType::I32;
 277 memoryType = WASMMemoryType::I8;
 278 hasOffset = true;
 279 break;
 280 case WASMOpStatement::I32Store16:
 281 expressionType = WASMExpressionType::I32;
 282 memoryType = WASMMemoryType::I16;
 283 hasOffset = false;
 284 break;
 285 case WASMOpStatement::I32StoreOffset16:
 286 expressionType = WASMExpressionType::I32;
 287 memoryType = WASMMemoryType::I16;
 288 hasOffset = true;
 289 break;
 290 case WASMOpStatement::I32Store32:
 291 expressionType = WASMExpressionType::I32;
 292 memoryType = WASMMemoryType::I32;
 293 hasOffset = false;
 294 break;
 295 case WASMOpStatement::I32StoreOffset32:
 296 expressionType = WASMExpressionType::I32;
 297 memoryType = WASMMemoryType::I32;
 298 hasOffset = true;
 299 break;
 300 case WASMOpStatement::F32Store:
 301 expressionType = WASMExpressionType::F32;
 302 memoryType = WASMMemoryType::F32;
 303 hasOffset = false;
 304 break;
 305 case WASMOpStatement::F32StoreOffset:
 306 expressionType = WASMExpressionType::F32;
 307 memoryType = WASMMemoryType::F32;
 308 hasOffset = true;
 309 break;
 310 case WASMOpStatement::F64Store:
 311 expressionType = WASMExpressionType::F64;
 312 memoryType = WASMMemoryType::F64;
 313 hasOffset = false;
 314 break;
 315 case WASMOpStatement::F64StoreOffset:
 316 expressionType = WASMExpressionType::F64;
 317 memoryType = WASMMemoryType::F64;
 318 hasOffset = true;
 319 break;
 320 default:
 321 ASSERT_NOT_REACHED();
 322 }
 323
 324 parseStore(context, hasOffset, expressionType, memoryType, false);
 325 return UNUSED;
 326}
 327
 328template <class Context>
 329ContextStatement WASMFunctionParser::parseCallInternalStatement(Context& context)
 330{
 331 parseCallInternal(context, false, WASMExpressionType::Void);
 332 return UNUSED;
 333}
 334
 335template <class Context>
 336ContextStatement WASMFunctionParser::parseCallIndirectStatement(Context& context)
 337{
 338 parseCallIndirect(context, false, WASMExpressionType::Void);
 339 return UNUSED;
 340}
 341
 342template <class Context>
 343ContextStatement WASMFunctionParser::parseCallImportStatement(Context& context)
 344{
 345 parseCallImport(context, false, WASMExpressionType::Void);
 346 return UNUSED;
 347}
 348
 349template <class Context>
 350ContextStatement WASMFunctionParser::parseReturnStatement(Context& context)
 351{
 352 ContextExpression expression;
 353 if (m_returnType != WASMExpressionType::Void) {
 354 expression = parseExpression(context, m_returnType);
 355 PROPAGATE_ERROR();
 356 } else
 357 expression = 0;
 358 context.returnStatement(expression, m_returnType);
 359 return UNUSED;
 360}
 361
 362template <class Context>
 363ContextStatement WASMFunctionParser::parseStatementList(Context& context)
 364{
 365 uint32_t numberOfStatements;
 366 READ_COMPACT_UINT32_OR_FAIL(numberOfStatements, "Cannot read the number of statements.");
 367 for (uint32_t i = 0; i < numberOfStatements; ++i) {
 368 parseStatement(context);
 369 PROPAGATE_ERROR();
 370 }
 371 return UNUSED;
 372}
 373
 374template <class Context>
 375ContextStatement WASMFunctionParser::parseBlockStatement(Context& context)
 376{
 377 parseStatementList(context);
 378 return UNUSED;
 379}
 380
 381template <class Context>
 382ContextStatement WASMFunctionParser::parseIfStatement(Context& context)
 383{
 384 ContextExpression condition = parseExpressionI32(context);
 385 PROPAGATE_ERROR();
 386 ContextJump end = context.jitBranchIfZero(condition);
 387 parseStatement(context);
 388 PROPAGATE_ERROR();
 389 context.jitLinkJump(end);
 390 return UNUSED;
 391}
 392
 393template <class Context>
 394ContextStatement WASMFunctionParser::parseIfElseStatement(Context& context)
 395{
 396 ContextExpression condition = parseExpressionI32(context);
 397 PROPAGATE_ERROR();
 398 ContextJump elseJump = context.jitBranchIfZero(condition);
 399 parseStatement(context);
 400 PROPAGATE_ERROR();
 401 ContextJump end = context.jitJump();
 402 context.jitLinkJump(elseJump);
 403 parseStatement(context);
 404 PROPAGATE_ERROR();
 405 context.jitLinkJump(end);
 406 return UNUSED;
 407}
 408
 409template <class Context>
 410ContextStatement WASMFunctionParser::parseWhileStatement(Context& context)
 411{
 412 context.startLoop();
 413 context.linkContinue();
 414
 415 ContextLabel start = context.jitLabel();
 416 ContextExpression condition = parseExpressionI32(context);
 417 PROPAGATE_ERROR();
 418 ContextJump jumpToEnd = context.jitBranchIfZero(condition);
 419
 420 m_breakScopeDepth++;
 421 m_continueScopeDepth++;
 422 parseStatement(context);
 423 PROPAGATE_ERROR();
 424 m_continueScopeDepth--;
 425 m_breakScopeDepth--;
 426
 427 context.jitJump(start);
 428 context.jitLinkJump(jumpToEnd);
 429
 430 context.linkBreak();
 431 context.endLoop();
 432 return UNUSED;
 433}
 434
 435template <class Context>
 436ContextStatement WASMFunctionParser::parseDoStatement(Context& context)
 437{
 438 context.startLoop();
 439
 440 ContextLabel start = context.jitLabel();
 441
 442 m_breakScopeDepth++;
 443 m_continueScopeDepth++;
 444 parseStatement(context);
 445 PROPAGATE_ERROR();
 446 m_continueScopeDepth--;
 447 m_breakScopeDepth--;
 448
 449 context.linkContinue();
 450
 451 ContextExpression condition = parseExpressionI32(context);
 452 PROPAGATE_ERROR();
 453 ContextJump jumpToStart = context.jitBranchIfNonZero(condition);
 454 context.jitLinkJumpToLabel(jumpToStart, start);
 455
 456 context.linkBreak();
 457 context.endLoop();
 458 return UNUSED;
 459}
 460
 461template <class Context>
 462ContextStatement WASMFunctionParser::parseLabelStatement(Context& context)
 463{
 464 context.startLabel();
 465 m_labelDepth++;
 466 parseStatement(context);
 467 m_labelDepth--;
 468 context.endLabel();
 469 return UNUSED;
 470}
 471
 472template <class Context>
 473ContextStatement WASMFunctionParser::parseBreakStatement(Context& context)
 474{
 475 FAIL_IF_FALSE(m_breakScopeDepth, "'break' is only valid inside a switch or loop statement.");
 476 context.breakStatement();
 477 return UNUSED;
 478}
 479
 480template <class Context>
 481ContextStatement WASMFunctionParser::parseBreakLabelStatement(Context& context)
 482{
 483 uint32_t labelIndex;
 484 READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index.");
 485 FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect.");
 486 context.breakLabelStatement(labelIndex);
 487 return UNUSED;
 488}
 489
 490template <class Context>
 491ContextStatement WASMFunctionParser::parseContinueStatement(Context& context)
 492{
 493 FAIL_IF_FALSE(m_continueScopeDepth, "'continue' is only valid inside a loop statement.");
 494 context.continueStatement();
 495 return UNUSED;
 496}
 497
 498template <class Context>
 499ContextStatement WASMFunctionParser::parseContinueLabelStatement(Context& context)
 500{
 501 uint32_t labelIndex;
 502 READ_COMPACT_UINT32_OR_FAIL(labelIndex, "Cannot read the label index.");
 503 FAIL_IF_FALSE(labelIndex < m_labelDepth, "The label index is incorrect.");
 504 context.continueLabelStatement(labelIndex);
 505 return UNUSED;
 506}
 507
 508template <class Context>
 509ContextStatement WASMFunctionParser::parseSwitchStatement(Context& context)
 510{
 511 context.startSwitch();
 512
 513 uint32_t numberOfCases;
 514 READ_COMPACT_UINT32_OR_FAIL(numberOfCases, "Cannot read the number of cases.");
 515 ContextExpression test = parseExpressionI32(context);
 516 PROPAGATE_ERROR();
 517
 518 ContextJump table = context.jitJump();
 519
 520 Vector<int32_t> cases;
 521 bool hasDefault = false;
 522 Vector<ContextLabel> labels; // TODO: use ContextLabelList
 523 cases.reserveInitialCapacity(numberOfCases);
 524 labels.reserveInitialCapacity(numberOfCases);
 525
 526 m_breakScopeDepth++;
 527 for (uint32_t i = 0; i < numberOfCases; ++i) {
 528 WASMSwitchCase switchCase;
 529 READ_SWITCH_CASE_OR_FAIL(switchCase, "Cannot read the switch case.");
 530 switch (switchCase) {
 531 case WASMSwitchCase::Case0:
 532 case WASMSwitchCase::Case1:
 533 case WASMSwitchCase::CaseN: {
 534 uint32_t value;
 535 READ_COMPACT_INT32_OR_FAIL(value, "Cannot read the value of the switch case.");
 536 cases.append(value);
 537 labels.append(context.jitLabel());
 538 if (switchCase == WASMSwitchCase::Case1) {
 539 parseStatement(context);
 540 PROPAGATE_ERROR();
 541 } else if (switchCase == WASMSwitchCase::CaseN) {
 542 parseStatementList(context);
 543 PROPAGATE_ERROR();
 544 }
 545 break;
 546 }
 547 case WASMSwitchCase::Default0:
 548 case WASMSwitchCase::Default1:
 549 case WASMSwitchCase::DefaultN: {
 550 FAIL_IF_FALSE(i == numberOfCases - 1, "The default case must be the last case.");
 551 labels.append(context.jitLabel());
 552 hasDefault = true;
 553 if (switchCase == WASMSwitchCase::Default1) {
 554 parseStatement(context);
 555 PROPAGATE_ERROR();
 556 } else if (switchCase == WASMSwitchCase::DefaultN) {
 557 parseStatementList(context);
 558 PROPAGATE_ERROR();
 559 }
 560 break;
 561 }
 562 default:
 563 ASSERT_NOT_REACHED();
 564 }
 565 }
 566 m_breakScopeDepth--;
 567
 568 ContextJump end = context.jitJump();
 569 context.jitLinkJump(table);
 570
 571 context.generateSwitchTable(test, cases, hasDefault, labels);
 572
 573 context.jitLinkJump(end);
 574
 575 context.linkBreak();
 576 context.endSwitch();
 577 return UNUSED;
 578}
 579
 580template <class Context>
 581ContextExpression WASMFunctionParser::parseExpression(Context& context, WASMExpressionType expressionType)
 582{
 583 switch (expressionType) {
 584 case WASMExpressionType::I32:
 585 return parseExpressionI32(context);
 586 case WASMExpressionType::F32:
 587 return parseExpressionF32(context);
 588 case WASMExpressionType::F64:
 589 return parseExpressionF64(context);
 590 case WASMExpressionType::Void:
 591 return parseExpressionVoid(context);
 592 default:
 593 ASSERT_NOT_REACHED();
 594 }
 595}
 596
 597template <class Context>
 598ContextExpression WASMFunctionParser::parseExpressionI32(Context& context)
 599{
 600 WASMOpExpressionI32 op;
 601 WASMOpExpressionI32WithImmediate opWithImmediate;
 602 uint8_t immediate;
 603
 604 if (m_reader.readCode(&op, &opWithImmediate, &immediate)) {
 605 switch (op) {
 606 case WASMOpExpressionI32::LitPool:
 607 return parseLiteralPoolExpressionI32(context);
 608 case WASMOpExpressionI32::LitImm:
 609 return parseLiteralImmediateExpressionI32(context);
 610 case WASMOpExpressionI32::GetLocal:
 611 return parseGetLocalExpressionI32(context);
 612 case WASMOpExpressionI32::GetGlobal:
 613 return parseGetGlobalExpressionI32(context);
 614 case WASMOpExpressionI32::SetLocal:
 615 return parseSetLocalExpressionI32(context);
 616 case WASMOpExpressionI32::SetGlobal:
 617 return parseSetGlobalExpressionI32(context);
 618 case WASMOpExpressionI32::SLoad8:
 619 case WASMOpExpressionI32::SLoadOffset8:
 620 case WASMOpExpressionI32::ULoad8:
 621 case WASMOpExpressionI32::ULoadOffset8:
 622 case WASMOpExpressionI32::SLoad16:
 623 case WASMOpExpressionI32::SLoadOffset16:
 624 case WASMOpExpressionI32::ULoad16:
 625 case WASMOpExpressionI32::ULoadOffset16:
 626 case WASMOpExpressionI32::Load32:
 627 case WASMOpExpressionI32::LoadOffset32:
 628 return parseLoadExpressionI32(context, op);
 629 case WASMOpExpressionI32::Store8:
 630 case WASMOpExpressionI32::StoreOffset8:
 631 case WASMOpExpressionI32::Store16:
 632 case WASMOpExpressionI32::StoreOffset16:
 633 case WASMOpExpressionI32::Store32:
 634 case WASMOpExpressionI32::StoreOffset32:
 635 return parseStoreExpressionI32(context, op);
 636 case WASMOpExpressionI32::CallInternal:
 637 return parseCallInternalExpressionI32(context);
 638 case WASMOpExpressionI32::CallIndirect:
 639 return parseCallIndirectExpressionI32(context);
 640 case WASMOpExpressionI32::CallImport:
 641 return parseCallImportExpressionI32(context);
 642 case WASMOpExpressionI32::Conditional:
 643 return parseConditionalExpressionI32(context);
 644 case WASMOpExpressionI32::Comma:
 645 return parseCommaExpressionI32(context);
 646 case WASMOpExpressionI32::FromF64:
 647 return parseFromF64ExpressionI32(context);
 648 case WASMOpExpressionI32::Neg:
 649 case WASMOpExpressionI32::BitNot:
 650 case WASMOpExpressionI32::Clz:
 651 case WASMOpExpressionI32::LogicNot:
 652 case WASMOpExpressionI32::Abs:
 653 return parseUnaryExpressionI32(context, op);
 654 case WASMOpExpressionI32::Add:
 655 case WASMOpExpressionI32::Sub:
 656 case WASMOpExpressionI32::Mul:
 657 case WASMOpExpressionI32::SDiv:
 658 case WASMOpExpressionI32::UDiv:
 659 case WASMOpExpressionI32::SMod:
 660 case WASMOpExpressionI32::UMod:
 661 case WASMOpExpressionI32::BitOr:
 662 case WASMOpExpressionI32::BitAnd:
 663 case WASMOpExpressionI32::BitXor:
 664 case WASMOpExpressionI32::LeftShift:
 665 case WASMOpExpressionI32::ArithmeticRightShift:
 666 case WASMOpExpressionI32::LogicalRightShift:
 667 return parseBinaryExpressionI32(context, op);
 668 case WASMOpExpressionI32::EqualI32:
 669 case WASMOpExpressionI32::NotEqualI32:
 670 case WASMOpExpressionI32::SLessThanI32:
 671 case WASMOpExpressionI32::ULessThanI32:
 672 case WASMOpExpressionI32::SLessThanOrEqualI32:
 673 case WASMOpExpressionI32::ULessThanOrEqualI32:
 674 case WASMOpExpressionI32::SGreaterThanI32:
 675 case WASMOpExpressionI32::UGreaterThanI32:
 676 case WASMOpExpressionI32::SGreaterThanOrEqualI32:
 677 case WASMOpExpressionI32::UGreaterThanOrEqualI32:
 678 return parseRelationalI32ExpressionI32(context, op);
 679 case WASMOpExpressionI32::EqualF64:
 680 case WASMOpExpressionI32::NotEqualF64:
 681 case WASMOpExpressionI32::LessThanF64:
 682 case WASMOpExpressionI32::LessThanOrEqualF64:
 683 case WASMOpExpressionI32::GreaterThanF64:
 684 case WASMOpExpressionI32::GreaterThanOrEqualF64:
 685 return parseRelationalF64ExpressionI32(context, op);
 686 case WASMOpExpressionI32::SMin:
 687 case WASMOpExpressionI32::UMin:
 688 case WASMOpExpressionI32::SMax:
 689 case WASMOpExpressionI32::UMax:
 690 // return parseMinOrMaxExpressionI32(context, op);
 691 default:
 692 FAIL_WITH_MESSAGE("Unsupported instruction.");
 693 }
 694 } else {
 695 switch (opWithImmediate) {
 696 case WASMOpExpressionI32WithImmediate::LitPool:
 697 return parseLiteralPoolExpressionI32(context, immediate);
 698 case WASMOpExpressionI32WithImmediate::LitImm:
 699 return parseLiteralImmediateExpressionI32(context, immediate);
 700 case WASMOpExpressionI32WithImmediate::GetLocal:
 701 return parseGetLocalExpressionI32(context, immediate);
 702 default:
 703 FAIL_WITH_MESSAGE("Unsupported instruction.");
 704 }
 705 }
 706}
 707
 708template <class Context>
 709ContextExpression WASMFunctionParser::parseLiteralPoolExpressionI32(Context& context, uint32_t constantIndex)
 710{
 711 FAIL_IF_FALSE(constantIndex < m_module->i32Constants().size(), "The constant index is incorrect.");
 712 return context.createLiteralPoolExpressionI32(constantIndex);
 713}
 714
 715template <class Context>
 716ContextExpression WASMFunctionParser::parseLiteralPoolExpressionI32(Context& context)
 717{
 718 uint32_t constantIndex;
 719 READ_COMPACT_UINT32_OR_FAIL(constantIndex, "Cannot read the constant index.");
 720 return parseLiteralPoolExpressionI32(context, constantIndex);
 721}
 722
 723template <class Context>
 724ContextExpression WASMFunctionParser::parseLiteralImmediateExpressionI32(Context& context, uint32_t immediate)
 725{
 726 return context.createLiteralImmediateExpressionI32(immediate);
 727}
 728
 729template <class Context>
 730ContextExpression WASMFunctionParser::parseLiteralImmediateExpressionI32(Context& context)
 731{
 732 uint32_t immediate;
 733 READ_COMPACT_UINT32_OR_FAIL(immediate, "Cannot read the immediate.");
 734 return context.createLiteralImmediateExpressionI32(immediate);
 735}
 736
 737template <class Context>
 738ContextExpression WASMFunctionParser::parseGetLocalExpressionI32(Context& context, uint32_t localIndex)
 739{
 740 FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local variable index is incorrect.");
 741 FAIL_IF_FALSE(m_localTypes[localIndex] == WASMType::I32, "Expected a local variable of type int32.");
 742 return context.createGetLocalExpressionI32(localIndex);
 743}
 744
 745template <class Context>
 746ContextExpression WASMFunctionParser::parseGetLocalExpressionI32(Context& context)
 747{
 748 uint32_t localIndex;
 749 READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index.");
 750 return parseGetLocalExpressionI32(context, localIndex);
 751}
 752
 753template <class Context>
 754ContextExpression WASMFunctionParser::parseGetGlobalExpressionI32(Context& context)
 755{
 756 uint32_t globalIndex;
 757 READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index.");
 758 FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect.");
 759 FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == WASMType::I32, "Expected a global variable of type int32.");
 760 return context.createGetGlobalExpressionI32(globalIndex);
 761}
 762
 763template <class Context>
 764ContextExpression WASMFunctionParser::parseSetLocalExpressionI32(Context& context)
 765{
 766 uint32_t localIndex;
 767 READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index.");
 768 FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local variable index is incorrect.");
 769 FAIL_IF_FALSE(m_localTypes[localIndex] == WASMType::I32, "Expected a local variable of type int32.");
 770 ContextExpression expression = parseExpressionI32(context);
 771 PROPAGATE_ERROR();
 772 return context.createSetLocalExpressionI32(localIndex, expression);
 773}
 774
 775template <class Context>
 776ContextExpression WASMFunctionParser::parseSetGlobalExpressionI32(Context& context)
 777{
 778 uint32_t globalIndex;
 779 READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index.");
 780 FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect.");
 781 FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == WASMType::I32, "Expected a global variable of type int32.");
 782 ContextExpression expression = parseExpressionI32(context);
 783 PROPAGATE_ERROR();
 784 return context.createSetGlobal(globalIndex, expression, WASMType::I32, true);
 785}
 786
 787template <class Context>
 788ContextExpression WASMFunctionParser::parseLoadExpressionI32(Context& context, WASMOpExpressionI32 op)
 789{
 790 WASMMemoryType memoryType;
 791 bool hasOffset;
 792 bool signExtended = false;
 793 switch (op) {
 794 case WASMOpExpressionI32::SLoad8:
 795 memoryType = WASMMemoryType::I8;
 796 hasOffset = false;
 797 signExtended = true;
 798 break;
 799 case WASMOpExpressionI32::SLoadOffset8:
 800 memoryType = WASMMemoryType::I8;
 801 hasOffset = true;
 802 signExtended = true;
 803 break;
 804 case WASMOpExpressionI32::ULoad8:
 805 memoryType = WASMMemoryType::I8;
 806 hasOffset = false;
 807 signExtended = false;
 808 break;
 809 case WASMOpExpressionI32::ULoadOffset8:
 810 memoryType = WASMMemoryType::I8;
 811 hasOffset = true;
 812 signExtended = false;
 813 break;
 814 case WASMOpExpressionI32::SLoad16:
 815 memoryType = WASMMemoryType::I16;
 816 hasOffset = false;
 817 signExtended = true;
 818 break;
 819 case WASMOpExpressionI32::SLoadOffset16:
 820 memoryType = WASMMemoryType::I16;
 821 hasOffset = true;
 822 signExtended = true;
 823 break;
 824 case WASMOpExpressionI32::ULoad16:
 825 memoryType = WASMMemoryType::I16;
 826 hasOffset = false;
 827 signExtended = false;
 828 break;
 829 case WASMOpExpressionI32::ULoadOffset16:
 830 memoryType = WASMMemoryType::I16;
 831 hasOffset = true;
 832 signExtended = false;
 833 break;
 834 case WASMOpExpressionI32::Load32:
 835 memoryType = WASMMemoryType::I32;
 836 hasOffset = false;
 837 break;
 838 case WASMOpExpressionI32::LoadOffset32:
 839 memoryType = WASMMemoryType::I32;
 840 hasOffset = true;
 841 break;
 842 default:
 843 ASSERT_NOT_REACHED();
 844 }
 845 return parseLoad(context, hasOffset, WASMExpressionType::I32, memoryType, signExtended);
 846}
 847
 848template <class Context>
 849ContextExpression WASMFunctionParser::parseStoreExpressionI32(Context& context, WASMOpExpressionI32 op)
 850{
 851 WASMMemoryType memoryType;
 852 bool hasOffset;
 853 switch (op) {
 854 case WASMOpExpressionI32::Store8:
 855 memoryType = WASMMemoryType::I8;
 856 hasOffset = false;
 857 break;
 858 case WASMOpExpressionI32::StoreOffset8:
 859 memoryType = WASMMemoryType::I8;
 860 hasOffset = true;
 861 break;
 862 case WASMOpExpressionI32::Store16:
 863 memoryType = WASMMemoryType::I16;
 864 hasOffset = false;
 865 break;
 866 case WASMOpExpressionI32::StoreOffset16:
 867 memoryType = WASMMemoryType::I16;
 868 hasOffset = true;
 869 break;
 870 case WASMOpExpressionI32::Store32:
 871 memoryType = WASMMemoryType::I32;
 872 hasOffset = false;
 873 break;
 874 case WASMOpExpressionI32::StoreOffset32:
 875 memoryType = WASMMemoryType::I32;
 876 hasOffset = true;
 877 break;
 878 default:
 879 ASSERT_NOT_REACHED();
 880 }
 881 return parseStore(context, hasOffset, WASMExpressionType::I32, memoryType, true);
 882}
 883
 884template <class Context>
 885ContextExpression WASMFunctionParser::parseCallInternalExpressionI32(Context& context)
 886{
 887 return parseCallInternal(context, true, WASMExpressionType::I32);
 888}
 889
 890template <class Context>
 891ContextExpression WASMFunctionParser::parseCallIndirectExpressionI32(Context& context)
 892{
 893 return parseCallIndirect(context, true, WASMExpressionType::I32);
 894}
 895
 896template <class Context>
 897ContextExpression WASMFunctionParser::parseCallImportExpressionI32(Context& context)
 898{
 899 return parseCallImport(context, true, WASMExpressionType::I32);
 900}
 901
 902template <class Context>
 903ContextExpression WASMFunctionParser::parseConditionalExpressionI32(Context& context)
 904{
 905 ContextExpression expression = parseExpressionI32(context);
 906 PROPAGATE_ERROR();
 907 ContextJump els = context.jitBranchIfZero(expression);
 908 parseExpressionI32(context);
 909 PROPAGATE_ERROR();
 910 ContextJump end = context.jitJump();
 911 context.jitLinkJump(els);
 912 context.pop();
 913 parseExpressionI32(context);
 914 PROPAGATE_ERROR();
 915 context.jitLinkJump(end);
 916 return UNUSED;
 917}
 918
 919template <class Context>
 920ContextExpression WASMFunctionParser::parseCommaExpressionI32(Context& context)
 921{
 922
 923 WASMExpressionType expressionType;
 924 READ_EXPRESSION_TYPE_OR_FAIL(expressionType, "Cannot read the expression type.");
 925 parseExpression(context, expressionType);
 926 PROPAGATE_ERROR();
 927 if (expressionType != WASMExpressionType::Void)
 928 context.pop();
 929 parseExpressionI32(context);
 930 return UNUSED;
 931}
 932
 933template <class Context>
 934ContextExpression WASMFunctionParser::parseFromF64ExpressionI32(Context& context)
 935{
 936 ContextExpression expression = parseExpressionF64(context);
 937 PROPAGATE_ERROR();
 938 return context.createFromF64ExpressionI32(expression);
 939}
 940
 941template <class Context>
 942ContextExpression WASMFunctionParser::parseUnaryExpressionI32(Context& context, WASMOpExpressionI32 op)
 943{
 944 ContextExpression expression = parseExpressionI32(context);
 945 PROPAGATE_ERROR();
 946 return context.createUnaryExpressionI32(expression, op);
 947}
 948
 949template <class Context>
 950ContextExpression WASMFunctionParser::parseBinaryExpressionI32(Context& context, WASMOpExpressionI32 op)
 951{
 952 ContextExpression expression1 = parseExpressionI32(context);
 953 PROPAGATE_ERROR();
 954 ContextExpression expression2 = parseExpressionI32(context);
 955 PROPAGATE_ERROR();
 956 return context.createBinaryExpressionI32(expression1, expression2, op);
 957}
 958
 959template <class Context>
 960ContextExpression WASMFunctionParser::parseRelationalI32ExpressionI32(Context& context, WASMOpExpressionI32 op)
 961{
 962 ContextExpression expression1 = parseExpressionI32(context);
 963 PROPAGATE_ERROR();
 964 ContextExpression expression2 = parseExpressionI32(context);
 965 PROPAGATE_ERROR();
 966 return context.createRelationalI32ExpressionI32(expression1, expression2, op);
 967}
 968
 969template <class Context>
 970ContextExpression WASMFunctionParser::parseRelationalF64ExpressionI32(Context& context, WASMOpExpressionI32 op)
 971{
 972 ContextExpression expression1 = parseExpressionF64(context);
 973 PROPAGATE_ERROR();
 974 ContextExpression expression2 = parseExpressionF64(context);
 975 PROPAGATE_ERROR();
 976 return context.createRelationalF64ExpressionI32(expression1, expression2, op);
 977}
 978
 979// template <class Context>
 980// ContextExpression WASMFunctionParser::parseMinOrMaxExpressionI32(Context& context, WASMOpExpressionI32 op)
 981// {
 982// uint32_t numberOfArguments;
 983// READ_COMPACT_UINT32_OR_FAIL(numberOfArguments, "Cannot read the number of arguments to min/max.");
 984// FAIL_IF_FALSE(numberOfArguments > 0, "The number of arguments must be greater than 0.");
 985// for (uint32_t i = 0; i < numberOfArguments; ++i) {
 986// }
 987// ContextExpression expression = parseExpressionI32(context);
 988// PROPAGATE_ERROR();
 989// }
 990
 991template <class Context>
 992ContextExpression WASMFunctionParser::parseExpressionF32(Context& context)
 993{
 994 WASMOpExpressionF32 op;
 995 WASMOpExpressionF32WithImmediate opWithImmediate;
 996 uint8_t immediate;
 997
 998 if (m_reader.readCode(&op, &opWithImmediate, &immediate)) {
 999 switch (op) {
 1000 case WASMOpExpressionF32::LitPool:
 1001 return parseLiteralPoolExpressionF32(context);
 1002 case WASMOpExpressionF32::LitImm:
 1003 return parseLiteralImmediateExpressionF32(context);
 1004 case WASMOpExpressionF32::GetLocal:
 1005 return parseGetLocalExpressionF32(context);
 1006 case WASMOpExpressionF32::GetGlobal:
 1007 return parseGetGlobalExpressionF32(context);
 1008 case WASMOpExpressionF32::SetLocal:
 1009 return parseSetLocalExpressionF32(context);
 1010 case WASMOpExpressionF32::SetGlobal:
 1011 return parseSetGlobalExpressionF32(context);
 1012 case WASMOpExpressionF32::Load:
 1013 case WASMOpExpressionF32::LoadOffset:
 1014 case WASMOpExpressionF32::Store:
 1015 case WASMOpExpressionF32::StoreOffset:
 1016 case WASMOpExpressionF32::CallInternal:
 1017 case WASMOpExpressionF32::CallIndirect:
 1018 case WASMOpExpressionF32::Conditional:
 1019 case WASMOpExpressionF32::Comma:
 1020 case WASMOpExpressionF32::FromS32:
 1021 case WASMOpExpressionF32::FromU32:
 1022 printf("op2 = %d\n", (int)op);
 1023 RELEASE_ASSERT_NOT_REACHED();
 1024 case WASMOpExpressionF32::FromF64:
 1025 return parseFromF64ExpressionF32(context);
 1026 case WASMOpExpressionF32::Neg:
 1027 case WASMOpExpressionF32::Add:
 1028 case WASMOpExpressionF32::Sub:
 1029 case WASMOpExpressionF32::Mul:
 1030 case WASMOpExpressionF32::Div:
 1031 case WASMOpExpressionF32::Abs:
 1032 case WASMOpExpressionF32::Ceil:
 1033 case WASMOpExpressionF32::Floor:
 1034 case WASMOpExpressionF32::Sqrt:
 1035 default:
 1036 printf("op3 = %d\n", (int)op);
 1037 RELEASE_ASSERT_NOT_REACHED();
 1038 }
 1039 } else {
 1040 switch (opWithImmediate) {
 1041 case WASMOpExpressionF32WithImmediate::LitPool:
 1042 return parseLiteralPoolExpressionF32(context, immediate);
 1043 case WASMOpExpressionF32WithImmediate::GetLocal:
 1044 return parseGetLocalExpressionF32(context, immediate);
 1045 default:
 1046 ASSERT_NOT_REACHED();
 1047 }
 1048 }
 1049}
 1050
 1051template <class Context>
 1052ContextExpression WASMFunctionParser::parseLiteralPoolExpressionF32(Context& context, uint32_t constantIndex)
 1053{
 1054 FAIL_IF_FALSE(constantIndex < m_module->f32Constants().size(), "The constant index is incorrect.");
 1055 return context.createLiteralPoolExpressionF32(constantIndex);
 1056}
 1057
 1058template <class Context>
 1059ContextExpression WASMFunctionParser::parseLiteralPoolExpressionF32(Context& context)
 1060{
 1061 uint32_t constantIndex;
 1062 READ_COMPACT_UINT32_OR_FAIL(constantIndex, "Cannot read the constant index.");
 1063 return parseLiteralPoolExpressionF32(context, constantIndex);
 1064}
 1065
 1066template <class Context>
 1067ContextExpression WASMFunctionParser::parseLiteralImmediateExpressionF32(Context& context)
 1068{
 1069 float immediate;
 1070 READ_FLOAT_OR_FAIL(immediate, "Cannot read the immediate.");
 1071 return context.createLiteralImmediateExpressionF32(immediate);
 1072}
 1073
 1074template <class Context>
 1075ContextExpression WASMFunctionParser::parseGetLocalExpressionF32(Context& context, uint32_t localIndex)
 1076{
 1077 FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local variable index is incorrect.");
 1078 FAIL_IF_FALSE(m_localTypes[localIndex] == WASMType::F32, "Expected a local variable of type float64.");
 1079 return context.createGetLocalExpressionF32(localIndex);
 1080}
 1081
 1082template <class Context>
 1083ContextExpression WASMFunctionParser::parseGetLocalExpressionF32(Context& context)
 1084{
 1085 uint32_t localIndex;
 1086 READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index.");
 1087 return parseGetLocalExpressionF32(context, localIndex);
 1088}
 1089
 1090template <class Context>
 1091ContextExpression WASMFunctionParser::parseGetGlobalExpressionF32(Context& context)
 1092{
 1093 uint32_t globalIndex;
 1094 READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index.");
 1095 FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect.");
 1096 FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == WASMType::F32, "Expected a global variable of type float32.");
 1097 return context.createGetGlobalExpressionF32(globalIndex);
 1098}
 1099
 1100template <class Context>
 1101ContextExpression WASMFunctionParser::parseSetLocalExpressionF32(Context& context)
 1102{
 1103 uint32_t localIndex;
 1104 READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index.");
 1105 FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local variable index is incorrect.");
 1106 FAIL_IF_FALSE(m_localTypes[localIndex] == WASMType::F32, "Expected a local variable of type float32.");
 1107 ContextExpression expression = parseExpressionF32(context);
 1108 PROPAGATE_ERROR();
 1109 return context.createSetLocalExpressionF32(localIndex, expression);
 1110}
 1111
 1112template <class Context>
 1113ContextExpression WASMFunctionParser::parseSetGlobalExpressionF32(Context& context)
 1114{
 1115 uint32_t globalIndex;
 1116 READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index.");
 1117 FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect.");
 1118 FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == WASMType::F32, "Expected a global variable of type float32.");
 1119 ContextExpression expression = parseExpressionF32(context);
 1120 PROPAGATE_ERROR();
 1121 return context.createSetGlobal(globalIndex, expression, WASMType::F32, true);
 1122}
 1123
 1124template <class Context>
 1125ContextExpression WASMFunctionParser::parseLoadExpressionF32(Context& context)
 1126{
 1127 return parseLoad(context, false, WASMExpressionType::F32, WASMMemoryType::F32, false);
 1128}
 1129
 1130template <class Context>
 1131ContextExpression WASMFunctionParser::parseLoadWithOffsetExpressionF32(Context& context)
 1132{
 1133 return parseLoad(context, true, WASMExpressionType::F32, WASMMemoryType::F32, false);
 1134}
 1135
 1136template <class Context>
 1137ContextExpression WASMFunctionParser::parseStoreExpressionF32(Context& context)
 1138{
 1139 return parseStore(context, false, WASMExpressionType::F32, WASMMemoryType::F32, true);
 1140}
 1141
 1142template <class Context>
 1143ContextExpression WASMFunctionParser::parseStoreWithOffsetExpressionF32(Context& context)
 1144{
 1145 return parseStore(context, true, WASMExpressionType::F32, WASMMemoryType::F32, true);
 1146}
 1147
 1148template <class Context>
 1149ContextExpression WASMFunctionParser::parseFromF64ExpressionF32(Context& context)
 1150{
 1151 ContextExpression expression = parseExpressionF64(context);
 1152 PROPAGATE_ERROR();
 1153 return context.createFromF64ExpressionF32(expression);
 1154}
 1155
 1156template <class Context>
 1157ContextExpression WASMFunctionParser::parseExpressionF64(Context& context)
 1158{
 1159 WASMOpExpressionF64 op;
 1160 WASMOpExpressionF64WithImmediate opWithImmediate;
 1161 uint8_t immediate;
 1162
 1163 if (m_reader.readCode(&op, &opWithImmediate, &immediate)) {
 1164 switch (op) {
 1165 case WASMOpExpressionF64::LitPool:
 1166 return parseLiteralPoolExpressionF64(context);
 1167 case WASMOpExpressionF64::LitImm:
 1168 return parseLiteralImmediateExpressionF64(context);
 1169 case WASMOpExpressionF64::GetLocal:
 1170 return parseGetLocalExpressionF64(context);
 1171 case WASMOpExpressionF64::GetGlobal:
 1172 return parseGetGlobalExpressionF64(context);
 1173 case WASMOpExpressionF64::SetLocal:
 1174 return parseSetLocalExpressionF64(context);
 1175 case WASMOpExpressionF64::SetGlobal:
 1176 return parseSetGlobalExpressionF64(context);
 1177 case WASMOpExpressionF64::Load:
 1178 return parseLoadExpressionF64(context);
 1179 case WASMOpExpressionF64::LoadOffset:
 1180 return parseLoadWithOffsetExpressionF64(context);
 1181 case WASMOpExpressionF64::Store:
 1182 return parseStoreExpressionF64(context);
 1183 case WASMOpExpressionF64::StoreOffset:
 1184 return parseStoreWithOffsetExpressionF64(context);
 1185 case WASMOpExpressionF64::CallInternal:
 1186 return parseCallInternalExpressionF64(context);
 1187 case WASMOpExpressionF64::CallIndirect:
 1188 return parseCallIndirectExpressionF64(context);
 1189 case WASMOpExpressionF64::CallImport:
 1190 return parseCallImportExpressionF64(context);
 1191 case WASMOpExpressionF64::Conditional:
 1192 return parseConditionalExpressionF64(context);
 1193 case WASMOpExpressionF64::Comma:
 1194 return parseCommaExpressionF64(context);
 1195 case WASMOpExpressionF64::FromS32:
 1196 return parseFromS32ExpressionF64(context);
 1197 case WASMOpExpressionF64::FromU32:
 1198 return parseFromU32ExpressionF64(context);
 1199 case WASMOpExpressionF64::Neg:
 1200 case WASMOpExpressionF64::Abs:
 1201 case WASMOpExpressionF64::Ceil:
 1202 case WASMOpExpressionF64::Floor:
 1203 case WASMOpExpressionF64::Sqrt:
 1204 case WASMOpExpressionF64::Cos:
 1205 case WASMOpExpressionF64::Sin:
 1206 case WASMOpExpressionF64::Tan:
 1207 case WASMOpExpressionF64::ACos:
 1208 case WASMOpExpressionF64::ASin:
 1209 case WASMOpExpressionF64::ATan:
 1210 case WASMOpExpressionF64::Exp:
 1211 case WASMOpExpressionF64::Ln:
 1212 return parseUnaryExpressionF64(context, op);
 1213 case WASMOpExpressionF64::Add:
 1214 case WASMOpExpressionF64::Sub:
 1215 case WASMOpExpressionF64::Mul:
 1216 case WASMOpExpressionF64::Div:
 1217 case WASMOpExpressionF64::ATan2:
 1218 case WASMOpExpressionF64::Pow:
 1219 return parseBinaryExpressionF64(context, op);
 1220 default:
 1221 FAIL_WITH_MESSAGE("Unsupported instruction.");
 1222 }
 1223 } else {
 1224 switch (opWithImmediate) {
 1225 case WASMOpExpressionF64WithImmediate::LitPool:
 1226 return parseLiteralPoolExpressionF64(context, immediate);
 1227 case WASMOpExpressionF64WithImmediate::GetLocal:
 1228 return parseGetLocalExpressionF64(context, immediate);
 1229 default:
 1230 FAIL_WITH_MESSAGE("Unsupported instruction.");
 1231 }
 1232 }
 1233}
 1234
 1235template <class Context>
 1236ContextExpression WASMFunctionParser::parseLiteralPoolExpressionF64(Context& context, uint32_t constantIndex)
 1237{
 1238 FAIL_IF_FALSE(constantIndex < m_module->f64Constants().size(), "The constant index is incorrect.");
 1239 return context.createLiteralPoolExpressionF64(constantIndex);
 1240}
 1241
 1242template <class Context>
 1243ContextExpression WASMFunctionParser::parseLiteralPoolExpressionF64(Context& context)
 1244{
 1245 uint32_t constantIndex;
 1246 READ_COMPACT_UINT32_OR_FAIL(constantIndex, "Cannot read the constant index.");
 1247 return parseLiteralPoolExpressionF64(context, constantIndex);
 1248}
 1249
 1250template <class Context>
 1251ContextExpression WASMFunctionParser::parseLiteralImmediateExpressionF64(Context& context)
 1252{
 1253 double immediate;
 1254 READ_DOUBLE_OR_FAIL(immediate, "Cannot read the immediate.");
 1255 return context.createLiteralImmediateExpressionF64(immediate);
 1256}
 1257
 1258template <class Context>
 1259ContextExpression WASMFunctionParser::parseGetLocalExpressionF64(Context& context, uint32_t localIndex)
 1260{
 1261 FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local variable index is incorrect.");
 1262 FAIL_IF_FALSE(m_localTypes[localIndex] == WASMType::F64, "Expected a local variable of type float64.");
 1263 return context.createGetLocalExpressionF64(localIndex);
 1264}
 1265
 1266template <class Context>
 1267ContextExpression WASMFunctionParser::parseGetLocalExpressionF64(Context& context)
 1268{
 1269 uint32_t localIndex;
 1270 READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index.");
 1271 return parseGetLocalExpressionF64(context, localIndex);
 1272}
 1273
 1274template <class Context>
 1275ContextExpression WASMFunctionParser::parseGetGlobalExpressionF64(Context& context)
 1276{
 1277 uint32_t globalIndex;
 1278 READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index.");
 1279 FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect.");
 1280 FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == WASMType::F64, "Expected a global variable of type float64.");
 1281 return context.createGetGlobalExpressionF64(globalIndex);
 1282}
 1283
 1284template <class Context>
 1285ContextExpression WASMFunctionParser::parseSetLocalExpressionF64(Context& context)
 1286{
 1287 uint32_t localIndex;
 1288 READ_COMPACT_UINT32_OR_FAIL(localIndex, "Cannot read the local index.");
 1289 FAIL_IF_FALSE(localIndex < m_localTypes.size(), "The local variable index is incorrect.");
 1290 FAIL_IF_FALSE(m_localTypes[localIndex] == WASMType::F64, "Expected a local variable of type float64.");
 1291 ContextExpression expression = parseExpressionF64(context);
 1292 PROPAGATE_ERROR();
 1293 return context.createSetLocalExpressionF64(localIndex, expression);
 1294}
 1295
 1296template <class Context>
 1297ContextExpression WASMFunctionParser::parseSetGlobalExpressionF64(Context& context)
 1298{
 1299 uint32_t globalIndex;
 1300 READ_COMPACT_UINT32_OR_FAIL(globalIndex, "Cannot read the global index.");
 1301 FAIL_IF_FALSE(globalIndex < m_module->globalVariableTypes().size(), "The global index is incorrect.");
 1302 FAIL_IF_FALSE(m_module->globalVariableTypes()[globalIndex] == WASMType::F64, "Expected a global variable of type float64.");
 1303 ContextExpression expression = parseExpressionF64(context);
 1304 PROPAGATE_ERROR();
 1305 return context.createSetGlobal(globalIndex, expression, WASMType::F64, true);
 1306}
 1307
 1308template <class Context>
 1309ContextExpression WASMFunctionParser::parseLoadExpressionF64(Context& context)
 1310{
 1311 return parseLoad(context, false, WASMExpressionType::F64, WASMMemoryType::F64, false);
 1312}
 1313
 1314template <class Context>
 1315ContextExpression WASMFunctionParser::parseLoadWithOffsetExpressionF64(Context& context)
 1316{
 1317 return parseLoad(context, true, WASMExpressionType::F64, WASMMemoryType::F64, false);
 1318}
 1319
 1320template <class Context>
 1321ContextExpression WASMFunctionParser::parseStoreExpressionF64(Context& context)
 1322{
 1323 return parseStore(context, false, WASMExpressionType::F64, WASMMemoryType::F64, true);
 1324}
 1325
 1326template <class Context>
 1327ContextExpression WASMFunctionParser::parseStoreWithOffsetExpressionF64(Context& context)
 1328{
 1329 return parseStore(context, true, WASMExpressionType::F64, WASMMemoryType::F64, true);
 1330}
 1331
 1332template <class Context>
 1333ContextExpression WASMFunctionParser::parseCallInternalExpressionF64(Context& context)
 1334{
 1335 return parseCallInternal(context, true, WASMExpressionType::F64);
 1336}
 1337
 1338template <class Context>
 1339ContextExpression WASMFunctionParser::parseCallIndirectExpressionF64(Context& context)
 1340{
 1341 return parseCallIndirect(context, true, WASMExpressionType::F64);
 1342}
 1343
 1344template <class Context>
 1345ContextExpression WASMFunctionParser::parseCallImportExpressionF64(Context& context)
 1346{
 1347 return parseCallImport(context, true, WASMExpressionType::F64);
 1348}
 1349
 1350template <class Context>
 1351ContextExpression WASMFunctionParser::parseConditionalExpressionF64(Context& context)
 1352{
 1353ContextExpression expression = parseExpressionI32(context);
 1354 PROPAGATE_ERROR();
 1355 ContextJump els = context.jitBranchIfZero(expression);
 1356 parseExpressionF64(context);
 1357 PROPAGATE_ERROR();
 1358 ContextJump end = context.jitJump();
 1359 context.jitLinkJump(els);
 1360 context.pop();
 1361 parseExpressionF64(context);
 1362 PROPAGATE_ERROR();
 1363 context.jitLinkJump(end);
 1364 return UNUSED;
 1365}
 1366
 1367template <class Context>
 1368ContextExpression WASMFunctionParser::parseCommaExpressionF64(Context& context)
 1369{
 1370 WASMExpressionType expressionType;
 1371 READ_EXPRESSION_TYPE_OR_FAIL(expressionType, "Cannot read the expression type.");
 1372 parseExpression(context, expressionType);
 1373 PROPAGATE_ERROR();
 1374 if (expressionType != WASMExpressionType::Void)
 1375 context.pop();
 1376 parseExpressionF64(context);
 1377 PROPAGATE_ERROR();
 1378 return UNUSED;
 1379}
 1380
 1381template <class Context>
 1382ContextExpression WASMFunctionParser::parseFromS32ExpressionF64(Context& context)
 1383{
 1384 ContextExpression expression = parseExpressionI32(context);
 1385 PROPAGATE_ERROR();
 1386 return context.createFromS32ExpressionF64(expression);
 1387}
 1388
 1389template <class Context>
 1390ContextExpression WASMFunctionParser::parseFromU32ExpressionF64(Context& context)
 1391{
 1392 ContextExpression expression = parseExpressionI32(context);
 1393 PROPAGATE_ERROR();
 1394 return context.createFromU32ExpressionF64(expression);
 1395}
 1396
 1397template <class Context>
 1398ContextExpression WASMFunctionParser::parseUnaryExpressionF64(Context& context, WASMOpExpressionF64 op)
 1399{
 1400 ContextExpression expression = parseExpressionF64(context);
 1401 PROPAGATE_ERROR();
 1402 return context.createUnaryExpressionF64(expression, op);
 1403}
 1404
 1405template <class Context>
 1406ContextExpression WASMFunctionParser::parseBinaryExpressionF64(Context& context, WASMOpExpressionF64 op)
 1407{
 1408 ContextExpression expression1 = parseExpressionF64(context);
 1409 PROPAGATE_ERROR();
 1410 ContextExpression expression2 = parseExpressionF64(context);
 1411 PROPAGATE_ERROR();
 1412 return context.createBinaryExpressionF64(expression1, expression2, op);
 1413}
 1414
 1415template <class Context>
 1416ContextExpression WASMFunctionParser::parseExpressionVoid(Context& context)
 1417{
 1418 WASMOpExpressionVoid op;
 1419 op = m_reader.readOpExpressionVoid(); // FIXME
 1420 switch (op) {
 1421 case WASMOpExpressionVoid::CallInternal:
 1422 return parseCallInternalExpressionVoid(context);
 1423 case WASMOpExpressionVoid::CallIndirect:
 1424 return parseCallIndirectExpressionVoid(context);
 1425 case WASMOpExpressionVoid::CallImport:
 1426 return parseCallImportExpressionVoid(context);
 1427 default:
 1428 RELEASE_ASSERT_NOT_REACHED();
 1429 }
 1430}
 1431
 1432template <class Context>
 1433ContextExpression WASMFunctionParser::parseCallInternalExpressionVoid(Context& context)
 1434{
 1435 return parseCallInternal(context, true, WASMExpressionType::Void);
 1436}
 1437
 1438template <class Context>
 1439ContextExpression WASMFunctionParser::parseCallIndirectExpressionVoid(Context& context)
 1440{
 1441 return parseCallIndirect(context, true, WASMExpressionType::Void);
 1442}
 1443
 1444template <class Context>
 1445ContextExpression WASMFunctionParser::parseCallImportExpressionVoid(Context& context)
 1446{
 1447 return parseCallImport(context, true, WASMExpressionType::Void);
 1448}
 1449
 1450template <class Context>
 1451ContextMemoryAddress WASMFunctionParser::parseMemoryAddress(Context& context, bool hasOffset)
 1452{
 1453 uint32_t offset = 0;
 1454 if (hasOffset)
 1455 READ_COMPACT_UINT32_OR_FAIL(offset, "Cannot read the offset.");
 1456
 1457 bool hasImmediateIndex;
 1458 uint32_t immediateIndex;
 1459 ContextExpression indexExpression;
 1460 if (m_reader.ifI32Literal(m_module->i32Constants(), &immediateIndex)) {
 1461 hasImmediateIndex = true;
 1462 indexExpression = 0;
 1463 } else {
 1464 hasImmediateIndex = false;
 1465 indexExpression = parseExpressionI32(context);
 1466 PROPAGATE_ERROR();
 1467 }
 1468 return ContextMemoryAddress(hasImmediateIndex, immediateIndex, indexExpression, offset);
 1469}
 1470
 1471template <class Context>
 1472ContextExpression WASMFunctionParser::parseLoad(Context& context, bool hasOffset, WASMExpressionType expressionType, WASMMemoryType memoryType, bool signExtended)
 1473{
 1474 const ContextMemoryAddress& memoryAddress = parseMemoryAddress(context, hasOffset);
 1475 PROPAGATE_ERROR();
 1476
 1477 return context.createLoad(memoryAddress, expressionType, memoryType, signExtended);
 1478}
 1479
 1480template <class Context>
 1481ContextExpression WASMFunctionParser::parseStore(Context& context, bool hasOffset, WASMExpressionType expressionType, WASMMemoryType memoryType, bool isExpression)
 1482{
 1483 const ContextMemoryAddress& memoryAddress = parseMemoryAddress(context, hasOffset);
 1484 PROPAGATE_ERROR();
 1485
 1486 ContextExpression value = parseExpression(context, expressionType);
 1487 PROPAGATE_ERROR();
 1488
 1489 return context.createStore(memoryAddress, expressionType, memoryType, value, isExpression);
 1490}
 1491
 1492template <class Context>
 1493ContextExpressionList WASMFunctionParser::parseCallArguments(Context& context, const Vector<WASMType>& arguments)
 1494{
 1495 for (size_t i = 0; i < arguments.size(); ++i) {
 1496 parseExpression(context, WASMExpressionType(arguments[i]));
 1497 PROPAGATE_ERROR();
 1498 }
 1499 return UNUSED;
 1500}
 1501
 1502template <class Context>
 1503ContextExpression WASMFunctionParser::parseCallInternal(Context& context, bool isExpression, WASMExpressionType returnType)
 1504{
 1505 uint32_t functionIndex;
 1506 READ_COMPACT_UINT32_OR_FAIL(functionIndex, "Cannot read the function index.");
 1507 FAIL_IF_FALSE(functionIndex < m_module->functionDeclarations().size(), "The function index is incorrect.");
 1508 const WASMSignature& signature = m_module->signatures()[m_module->functionDeclarations()[functionIndex].signatureIndex];
 1509 if (isExpression)
 1510 FAIL_IF_FALSE(signature.returnType == returnType, "Wrong return type.");
 1511
 1512 parseCallArguments(context, signature.arguments);
 1513 PROPAGATE_ERROR();
 1514 return context.createCallInternal(functionIndex, signature, returnType);
 1515}
 1516
 1517template <class Context>
 1518ContextExpression WASMFunctionParser::parseCallIndirect(Context& context, bool isExpression, WASMExpressionType returnType)
 1519{
 1520 uint32_t functionPointerTableIndex;
 1521 READ_COMPACT_UINT32_OR_FAIL(functionPointerTableIndex, "Cannot read the function pointer table index.");
 1522 FAIL_IF_FALSE(functionPointerTableIndex < m_module->functionPointerTables().size(), "The function pointer table index is incorrect.");
 1523 const WASMFunctionPointerTable& functionPointerTable = m_module->functionPointerTables()[functionPointerTableIndex];
 1524 const WASMSignature& signature = m_module->signatures()[functionPointerTable.signatureIndex];
 1525 if (isExpression)
 1526 FAIL_IF_FALSE(signature.returnType == returnType, "Wrong return type.");
 1527
 1528 ContextExpression elementIndex = parseExpressionI32(context);
 1529 PROPAGATE_ERROR();
 1530
 1531 parseCallArguments(context, signature.arguments);
 1532 PROPAGATE_ERROR();
 1533 return context.createCallIndirect(functionPointerTableIndex, elementIndex, signature, returnType);
 1534}
 1535
 1536template <class Context>
 1537ContextExpression WASMFunctionParser::parseCallImport(Context& context, bool isExpression, WASMExpressionType returnType)
 1538{
 1539 uint32_t functionImportSignatureIndex;
 1540 READ_COMPACT_UINT32_OR_FAIL(functionImportSignatureIndex, "Cannot read the function import signature index.");
 1541 FAIL_IF_FALSE(functionImportSignatureIndex < m_module->functionImportSignatures().size(), "The function import signature index is incorrect.");
 1542 const WASMFunctionImportSignature& functionImportSignature = m_module->functionImportSignatures()[functionImportSignatureIndex];
 1543 const WASMSignature& signature = m_module->signatures()[functionImportSignature.signatureIndex];
 1544 if (isExpression)
 1545 FAIL_IF_FALSE(signature.returnType == returnType, "Wrong return type.");
 1546
 1547 parseCallArguments(context, signature.arguments);
 1548 PROPAGATE_ERROR();
 1549 return context.createCallImport(functionImportSignatureIndex, signature, returnType);
 1550}
 1551
 1552} // namespace JSC
 1553
 1554#endif // ENABLE(WEBASSEMBLY)

Source/JavaScriptCore/wasm/WASMFunctionParser.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef WASMFunctionParser_h
 27#define WASMFunctionParser_h
 28
 29#if ENABLE(WEBASSEMBLY)
 30
 31#include "SourceCode.h"
 32#include "WASMReader.h"
 33
 34#define ContextExpression typename Context::Expression
 35#define ContextStatement typename Context::Statement
 36#define ContextExpressionList typename Context::ExpressionList
 37#define ContextJump typename Context::Jump
 38#define ContextLabel typename Context::Label
 39#define ContextMemoryAddress typename Context::MemoryAddress
 40
 41namespace JSC {
 42
 43class CodeBlock;
 44class JSWASMModule;
 45class VM;
 46
 47class WASMFunctionParser {
 48public:
 49 static bool checkSyntax(const JSWASMModule*, const SourceCode&, size_t functionIndex, unsigned startOffsetInSource, unsigned& endOffsetInSource, unsigned& stackHeight, String& errorMessage);
 50 static void generateCode(VM*, CodeBlock*, const JSWASMModule*, const SourceCode&, size_t functionIndex, unsigned startOffsetInSource, unsigned stackHeight);
 51
 52private:
 53 WASMFunctionParser(const JSWASMModule* module, const SourceCode& source)
 54 : m_module(module)
 55 , m_reader(static_cast<WebAssemblySourceProvider*>(source.provider())->data())
 56 , m_breakScopeDepth(0)
 57 , m_continueScopeDepth(0)
 58 , m_labelDepth(0)
 59 {
 60 }
 61
 62 template <class Context> bool parseFunction(Context&, size_t functionIndex, unsigned startOffsetInSource);
 63 void initializeLocalTypes(const WASMSignature&);
 64 bool parseLocalVariables();
 65
 66 template <class Context> ContextStatement parseStatement(Context&);
 67 template <class Context> ContextStatement parseSetLocalStatement(Context&, uint32_t localIndex);
 68 template <class Context> ContextStatement parseSetLocalStatement(Context&);
 69 template <class Context> ContextStatement parseSetGlobalStatement(Context&, uint32_t globalIndex);
 70 template <class Context> ContextStatement parseSetGlobalStatement(Context&);
 71 template <class Context> ContextStatement parseStoreStatement(Context&, WASMOpStatement);
 72 template <class Context> ContextStatement parseCallInternalStatement(Context&);
 73 template <class Context> ContextStatement parseCallIndirectStatement(Context&);
 74 template <class Context> ContextStatement parseCallImportStatement(Context&);
 75 template <class Context> ContextStatement parseReturnStatement(Context&);
 76 template <class Context> ContextStatement parseStatementList(Context&);
 77 template <class Context> ContextStatement parseBlockStatement(Context&);
 78 template <class Context> ContextStatement parseIfStatement(Context&);
 79 template <class Context> ContextStatement parseIfElseStatement(Context&);
 80 template <class Context> ContextStatement parseWhileStatement(Context&);
 81 template <class Context> ContextStatement parseDoStatement(Context&);
 82 template <class Context> ContextStatement parseLabelStatement(Context&);
 83 template <class Context> ContextStatement parseBreakStatement(Context&);
 84 template <class Context> ContextStatement parseBreakLabelStatement(Context&);
 85 template <class Context> ContextStatement parseContinueStatement(Context&);
 86 template <class Context> ContextStatement parseContinueLabelStatement(Context&);
 87 template <class Context> ContextStatement parseSwitchStatement(Context&);
 88
 89 template <class Context> ContextExpression parseExpression(Context&, WASMExpressionType);
 90
 91 template <class Context> ContextExpression parseExpressionI32(Context&);
 92 template <class Context> ContextExpression parseLiteralPoolExpressionI32(Context&, uint32_t constantIndex);
 93 template <class Context> ContextExpression parseLiteralPoolExpressionI32(Context&);
 94 template <class Context> ContextExpression parseLiteralImmediateExpressionI32(Context&, uint32_t immediate);
 95 template <class Context> ContextExpression parseLiteralImmediateExpressionI32(Context&);
 96 template <class Context> ContextExpression parseGetLocalExpressionI32(Context&, uint32_t localIndex);
 97 template <class Context> ContextExpression parseGetLocalExpressionI32(Context&);
 98 template <class Context> ContextExpression parseGetGlobalExpressionI32(Context&);
 99 template <class Context> ContextExpression parseSetLocalExpressionI32(Context&);
 100 template <class Context> ContextExpression parseSetGlobalExpressionI32(Context&);
 101 template <class Context> ContextExpression parseLoadExpressionI32(Context&, WASMOpExpressionI32);
 102 template <class Context> ContextExpression parseStoreExpressionI32(Context&, WASMOpExpressionI32);
 103 template <class Context> ContextExpression parseCallInternalExpressionI32(Context&);
 104 template <class Context> ContextExpression parseCallIndirectExpressionI32(Context&);
 105 template <class Context> ContextExpression parseCallImportExpressionI32(Context&);
 106 template <class Context> ContextExpression parseConditionalExpressionI32(Context&);
 107 template <class Context> ContextExpression parseCommaExpressionI32(Context&);
 108 template <class Context> ContextExpression parseFromF64ExpressionI32(Context&);
 109 template <class Context> ContextExpression parseUnaryExpressionI32(Context&, WASMOpExpressionI32);
 110 template <class Context> ContextExpression parseBinaryExpressionI32(Context&, WASMOpExpressionI32);
 111 template <class Context> ContextExpression parseRelationalI32ExpressionI32(Context&, WASMOpExpressionI32);
 112 template <class Context> ContextExpression parseRelationalF64ExpressionI32(Context&, WASMOpExpressionI32);
 113 // template <class Context> ContextExpression parseMinOrMaxExpressionI32(Context&, WASMOpExpressionI32);
 114
 115 template <class Context> ContextExpression parseExpressionF32(Context&);
 116 template <class Context> ContextExpression parseLiteralPoolExpressionF32(Context&, uint32_t constantIndex);
 117 template <class Context> ContextExpression parseLiteralPoolExpressionF32(Context&);
 118 template <class Context> ContextExpression parseLiteralImmediateExpressionF32(Context&);
 119 template <class Context> ContextExpression parseGetLocalExpressionF32(Context&, uint32_t localIndex);
 120 template <class Context> ContextExpression parseGetLocalExpressionF32(Context&);
 121 template <class Context> ContextExpression parseGetGlobalExpressionF32(Context&);
 122 template <class Context> ContextExpression parseSetLocalExpressionF32(Context&);
 123 template <class Context> ContextExpression parseSetGlobalExpressionF32(Context&);
 124 template <class Context> ContextExpression parseLoadExpressionF32(Context&);
 125 template <class Context> ContextExpression parseLoadWithOffsetExpressionF32(Context&);
 126 template <class Context> ContextExpression parseStoreExpressionF32(Context&);
 127 template <class Context> ContextExpression parseStoreWithOffsetExpressionF32(Context&);
 128 template <class Context> ContextExpression parseFromF64ExpressionF32(Context&);
 129
 130 template <class Context> ContextExpression parseExpressionF64(Context&);
 131 template <class Context> ContextExpression parseLiteralPoolExpressionF64(Context&, uint32_t constantIndex);
 132 template <class Context> ContextExpression parseLiteralPoolExpressionF64(Context&);
 133 template <class Context> ContextExpression parseLiteralImmediateExpressionF64(Context&);
 134 template <class Context> ContextExpression parseGetLocalExpressionF64(Context&, uint32_t localIndex);
 135 template <class Context> ContextExpression parseGetLocalExpressionF64(Context&);
 136 template <class Context> ContextExpression parseGetGlobalExpressionF64(Context&);
 137 template <class Context> ContextExpression parseSetLocalExpressionF64(Context&);
 138 template <class Context> ContextExpression parseSetGlobalExpressionF64(Context&);
 139 template <class Context> ContextExpression parseLoadExpressionF64(Context&);
 140 template <class Context> ContextExpression parseLoadWithOffsetExpressionF64(Context&);
 141 template <class Context> ContextExpression parseStoreExpressionF64(Context&);
 142 template <class Context> ContextExpression parseStoreWithOffsetExpressionF64(Context&);
 143 template <class Context> ContextExpression parseCallInternalExpressionF64(Context&);
 144 template <class Context> ContextExpression parseCallIndirectExpressionF64(Context&);
 145 template <class Context> ContextExpression parseCallImportExpressionF64(Context&);
 146 template <class Context> ContextExpression parseConditionalExpressionF64(Context&);
 147 template <class Context> ContextExpression parseCommaExpressionF64(Context&);
 148 template <class Context> ContextExpression parseFromS32ExpressionF64(Context&);
 149 template <class Context> ContextExpression parseFromU32ExpressionF64(Context&);
 150 template <class Context> ContextExpression parseUnaryExpressionF64(Context&, WASMOpExpressionF64);
 151 template <class Context> ContextExpression parseBinaryExpressionF64(Context&, WASMOpExpressionF64);
 152
 153 template <class Context> ContextExpression parseExpressionVoid(Context&);
 154 template <class Context> ContextExpression parseCallInternalExpressionVoid(Context&);
 155 template <class Context> ContextExpression parseCallIndirectExpressionVoid(Context&);
 156 template <class Context> ContextExpression parseCallImportExpressionVoid(Context&);
 157
 158 template <class Context> ContextMemoryAddress parseMemoryAddress(Context&, bool hasOffset);
 159 template <class Context> ContextExpression parseLoad(Context&, bool hasOffset, WASMExpressionType, WASMMemoryType, bool signExtended);
 160 template <class Context> ContextExpression parseStore(Context&, bool hasOffset, WASMExpressionType, WASMMemoryType, bool isExpression);
 161
 162 template <class Context> ContextExpressionList parseCallArguments(Context&, const Vector<WASMType>& arguments);
 163 template <class Context> ContextExpression parseCallInternal(Context&, bool isExpression, WASMExpressionType returnType);
 164 template <class Context> ContextExpression parseCallIndirect(Context&, bool isExpression, WASMExpressionType returnType);
 165 template <class Context> ContextExpression parseCallImport(Context&, bool isExpression, WASMExpressionType returnType);
 166
 167 const JSWASMModule* m_module; // FIXME: need to fix this!
 168 WASMReader m_reader;
 169 String m_errorMessage;
 170
 171 WASMExpressionType m_returnType;
 172 Vector<WASMType> m_localTypes;
 173 uint32_t m_numberOfI32Vars; // FIXME: Do we really have to store these?
 174 uint32_t m_numberOfF32Vars;
 175 uint32_t m_numberOfF64Vars;
 176
 177 unsigned m_breakScopeDepth;
 178 unsigned m_continueScopeDepth;
 179 unsigned m_labelDepth;
 180};
 181
 182} // namespace JSC
 183
 184#endif // ENABLE(WEBASSEMBLY)
 185
 186#endif // WASMFunctionParser_h

Source/JavaScriptCore/wasm/WASMMagicNumber.h

1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef WASMMagicNumber_h
27 #define WASMMagicNumber_h
28 
29 #if ENABLE(WEBASSEMBLY)
30 
31 namespace JSC {
32 
33 static const uint32_t wasmMagicNumber = 0x6d736177;
34 
35 } // namespace JSC
36 
37 #endif // ENABLE(WEBASSEMBLY)
38 
39 #endif // WASMMagicNumber_h

Source/JavaScriptCore/wasm/WASMModuleParser.cpp

2828
2929#if ENABLE(WEBASSEMBLY)
3030
 31#include "JSArrayBuffer.h"
3132#include "JSCInlines.h"
32 #include "JSWASMModule.h"
33 #include "WASMMagicNumber.h"
 33#include "WASMConstants.h"
 34#include "WASMFormat.h"
 35#include "WASMFunctionParser.h"
 36#include <wtf/MathExtras.h>
3437
35 #define FAIL_WITH_MESSAGE(errorMessage) do { m_errorMessage = errorMessage; return false; } while (0)
36 #define READ_UNSIGNED_INT32_OR_FAIL(x, errorMessage) do { if (!m_reader.readUnsignedInt32(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 38#define PROPAGATE_ERROR() do { if (!m_errorMessage.isNull()) return; } while (0)
 39#define FAIL_WITH_MESSAGE(errorMessage) do { m_errorMessage = errorMessage; return; } while (0)
 40#define READ_UINT32_OR_FAIL(x, errorMessage) do { if (!m_reader.readUInt32(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
3741#define READ_FLOAT_OR_FAIL(x, errorMessage) do { if (!m_reader.readFloat(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
3842#define READ_DOUBLE_OR_FAIL(x, errorMessage) do { if (!m_reader.readDouble(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 43#define READ_STRING_OR_FAIL(x, errorMessage) do { if (!m_reader.readString(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 44#define READ_COMPACT_UINT32_OR_FAIL(x, errorMessage) do { if (!m_reader.readCompactUInt32(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 45#define READ_TYPE_OR_FAIL(x, errorMessage) do { if (!m_reader.readType(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 46#define READ_EXPRESSION_TYPE_OR_FAIL(x, errorMessage) do { if (!m_reader.readExpressionType(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
 47#define READ_EXPORT_FORMAT_OR_FAIL(x, errorMessage) do { if (!m_reader.readExportFormat(x)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
3948#define FAIL_IF_FALSE(condition, errorMessage) do { if (!(condition)) FAIL_WITH_MESSAGE(errorMessage); } while (0)
4049
4150namespace JSC {
4251
43 WASMModuleParser::WASMModuleParser(const SourceCode& source)
44  : m_reader(static_cast<WebAssemblySourceProvider*>(source.provider())->data())
 52JSWASMModule* WASMModuleParser::parse(VM& vm, JSGlobalObject* globalObject, ExecState* exec, JSObject* env, JSArrayBuffer* arrayBuffer, String& errorMessage)
4553{
46 }
47 
48 JSWASMModule* WASMModuleParser::parse(VM& vm, JSGlobalObject* globalObject, String& errorMessage)
49 {
50  JSWASMModule* module = JSWASMModule::create(vm, globalObject->wasmModuleStructure());
51  parseModule();
 54 m_module = JSWASMModule::create(vm, globalObject->wasmModuleStructure(), arrayBuffer);
 55 parseModule(vm, globalObject, exec, env);
5256 if (!m_errorMessage.isNull()) {
5357 errorMessage = m_errorMessage;
5458 return nullptr;
5559 }
56  return module;
 60 return m_module;
5761}
5862
59 bool WASMModuleParser::parseModule()
 63void WASMModuleParser::parseModule(VM& vm, JSGlobalObject* globalObject, ExecState* exec, JSObject* env)
6064{
6165 uint32_t magicNumber;
62  READ_UNSIGNED_INT32_OR_FAIL(magicNumber, "Cannot read the magic number.");
 66 uint32_t outputSizeInASMJS;
 67 READ_UINT32_OR_FAIL(magicNumber, "Cannot read the magic number.");
6368 FAIL_IF_FALSE(magicNumber == wasmMagicNumber, "The magic number is incorrect.");
 69 READ_UINT32_OR_FAIL(outputSizeInASMJS, "Cannot read the output size in asm.js format.");
 70
 71 parseConstantPoolSection();
 72 PROPAGATE_ERROR();
 73 parseSignatureSection();
 74 PROPAGATE_ERROR();
 75 parseFunctionImportSection(exec, env);
 76 PROPAGATE_ERROR();
 77 parseGlobalSection(exec, env);
 78 PROPAGATE_ERROR();
 79 parseFunctionDeclarationSection();
 80 PROPAGATE_ERROR();
 81 parseFunctionPointerTableSection();
 82 PROPAGATE_ERROR();
 83 parseFunctionDefinitionSection(vm, globalObject);
 84 PROPAGATE_ERROR();
 85 parseExportSection(vm);
 86}
 87
 88void WASMModuleParser::parseConstantPoolSection()
 89{
 90 uint32_t numberOfI32Constants;
 91 uint32_t numberOfF32Constants;
 92 uint32_t numberOfF64Constants;
 93 READ_COMPACT_UINT32_OR_FAIL(numberOfI32Constants, "Cannot read the number of int32 constants.");
 94 READ_COMPACT_UINT32_OR_FAIL(numberOfF32Constants, "Cannot read the number of float32 constants.");
 95 READ_COMPACT_UINT32_OR_FAIL(numberOfF64Constants, "Cannot read the number of float64 constants.");
 96 m_module->i32Constants().reserveInitialCapacity(numberOfI32Constants);
 97 m_module->f32Constants().reserveInitialCapacity(numberOfF32Constants);
 98 m_module->f64Constants().reserveInitialCapacity(numberOfF64Constants);
 99
 100 for (uint32_t i = 0; i < numberOfI32Constants; ++i) {
 101 uint32_t constant;
 102 READ_COMPACT_UINT32_OR_FAIL(constant, "Cannot read an int32 constant.");
 103 m_module->i32Constants().append(constant);
 104 }
 105 for (uint32_t i = 0; i < numberOfF32Constants; ++i) {
 106 float constant;
 107 READ_FLOAT_OR_FAIL(constant, "Cannot read a float32 constant.");
 108 m_module->f32Constants().append(constant);
 109 }
 110 for (uint32_t i = 0; i < numberOfF64Constants; ++i) {
 111 double constant;
 112 READ_DOUBLE_OR_FAIL(constant, "Cannot read a float64 constant.");
 113 m_module->f64Constants().append(constant);
 114 }
 115}
 116
 117void WASMModuleParser::parseSignatureSection()
 118{
 119 uint32_t numberOfSignatures;
 120 READ_COMPACT_UINT32_OR_FAIL(numberOfSignatures, "Cannot read the number of signatures.");
 121 m_module->signatures().reserveInitialCapacity(numberOfSignatures);
 122 for (uint32_t signatureIndex = 0; signatureIndex < numberOfSignatures; ++signatureIndex) {
 123 WASMSignature signature;
 124 READ_EXPRESSION_TYPE_OR_FAIL(signature.returnType, "Cannot read the return type.");
 125 uint32_t argumentCount;
 126 READ_COMPACT_UINT32_OR_FAIL(argumentCount, "Cannot read the number of arguments.");
 127 signature.arguments.reserveInitialCapacity(argumentCount);
 128 for (uint32_t argumentIndex = 0; argumentIndex < argumentCount; ++argumentIndex) {
 129 WASMType type;
 130 READ_TYPE_OR_FAIL(type, "Cannot read the type of an argument.");
 131 signature.arguments.append(type);
 132 }
 133 m_module->signatures().append(signature);
 134 }
 135}
 136
 137void WASMModuleParser::parseFunctionImportSection(ExecState* exec, JSObject* env)
 138{
 139 uint32_t numberOfFunctionImports;
 140 uint32_t numberOfFunctionImportSignatures;
 141 READ_COMPACT_UINT32_OR_FAIL(numberOfFunctionImports, "Cannot read the number of function imports.");
 142 READ_COMPACT_UINT32_OR_FAIL(numberOfFunctionImportSignatures, "Cannot read the number of function import signatures.");
 143 m_module->functionImports().reserveInitialCapacity(numberOfFunctionImports);
 144 m_module->functionImportSignatures().reserveInitialCapacity(numberOfFunctionImportSignatures);
 145
 146 m_module->importedFunctions().reserveInitialCapacity(numberOfFunctionImports);
 147
 148 for (uint32_t functionImportIndex = 0; functionImportIndex < numberOfFunctionImports; ++functionImportIndex) {
 149 WASMFunctionImport functionImport;
 150 READ_STRING_OR_FAIL(functionImport.functionName, "Cannot read the function import name.");
 151 m_module->functionImports().append(functionImport);
 152
 153 uint32_t numberOfSignatures;
 154 READ_COMPACT_UINT32_OR_FAIL(numberOfSignatures, "Cannot read the number of signatures.");
 155 FAIL_IF_FALSE(m_module->functionImportSignatures().size() + numberOfSignatures <= numberOfFunctionImportSignatures, "The number of function import signatures is incorrect.");
 156
 157 for (uint32_t i = 0; i < numberOfSignatures; ++i) {
 158 WASMFunctionImportSignature functionImportSignature;
 159 READ_COMPACT_UINT32_OR_FAIL(functionImportSignature.signatureIndex, "Cannot read the signature index.");
 160 FAIL_IF_FALSE(functionImportSignature.signatureIndex < m_module->signatures().size(), "The signature index is incorrect.");
 161 functionImportSignature.functionImportIndex = functionImportIndex;
 162 m_module->functionImportSignatures().append(functionImportSignature);
 163 }
 164
 165 // -----------
 166
 167 const String& functionImportName = functionImport.functionName;
 168
 169 Identifier identifier = Identifier::fromString(&exec->vm(), functionImportName);
 170 PropertySlot slot(env);
 171
 172 if (!env->getPropertySlot(exec, identifier, slot)) {
 173 // FIXME: Print a more useful message.
 174 fprintf(stderr, "Can't find a function named \"%s\".\n", functionImportName.utf8().data());
 175 FAIL_WITH_MESSAGE("Can't find an imported function.");
 176 }
 177
 178 JSValue value = slot.getValue(exec, identifier);
 179 FAIL_IF_FALSE(value.isFunction(), "An imported function is not a function.");
 180
 181 JSFunction* function = jsCast<JSFunction*>(value.asCell());
 182 m_module->importedFunctions().append(WriteBarrier<JSFunction>(exec->vm(), m_module, function));
 183 }
 184 FAIL_IF_FALSE(m_module->functionImportSignatures().size() == numberOfFunctionImportSignatures, "The number of function import signatures is incorrect.");
 185}
 186
 187void WASMModuleParser::parseGlobalSection(ExecState* exec, JSObject* env)
 188{
 189 uint32_t numberOfNonImportedI32GlobalVariables;
 190 uint32_t numberOfNonImportedF32GlobalVariables;
 191 uint32_t numberOfNonImportedF64GlobalVariables;
 192 uint32_t numberOfImportedI32GlobalVariables;
 193 uint32_t numberOfImportedF32GlobalVariables;
 194 uint32_t numberOfImportedF64GlobalVariables;
 195 READ_COMPACT_UINT32_OR_FAIL(numberOfNonImportedI32GlobalVariables, "Cannot read the number of non-imported int32 global variables.");
 196 READ_COMPACT_UINT32_OR_FAIL(numberOfNonImportedF32GlobalVariables, "Cannot read the number of non-imported float32 global variables.");
 197 READ_COMPACT_UINT32_OR_FAIL(numberOfNonImportedF64GlobalVariables, "Cannot read the number of non-imported float64 global variables.");
 198 READ_COMPACT_UINT32_OR_FAIL(numberOfImportedI32GlobalVariables, "Cannot read the number of imported int32 global variables.");
 199 READ_COMPACT_UINT32_OR_FAIL(numberOfImportedF32GlobalVariables, "Cannot read the number of imported float32 global variables.");
 200 READ_COMPACT_UINT32_OR_FAIL(numberOfImportedF64GlobalVariables, "Cannot read the number of imported float64 global variables.");
 201 uint32_t numberOfGlobalVariables = numberOfNonImportedI32GlobalVariables + numberOfNonImportedF32GlobalVariables + numberOfNonImportedF64GlobalVariables +
 202 numberOfImportedI32GlobalVariables + numberOfImportedF32GlobalVariables + numberOfImportedF64GlobalVariables;
 203
 204 Vector<WASMType>& globalVariableTypes = m_module->globalVariableTypes();
 205 Vector<const void*>& globalVariableAddresses = m_module->globalVariableAddresses();
 206
 207 globalVariableTypes.reserveInitialCapacity(numberOfGlobalVariables);
 208 globalVariableAddresses.reserveInitialCapacity(numberOfGlobalVariables);
 209
 210 size_t globalDataSize = 8 +
 211 (numberOfNonImportedI32GlobalVariables * sizeof(uint32_t)) +
 212 (numberOfNonImportedF32GlobalVariables * sizeof(float)) +
 213 (numberOfNonImportedF64GlobalVariables * sizeof(double)) +
 214 (numberOfImportedI32GlobalVariables * sizeof(uint32_t)) +
 215 (numberOfImportedF32GlobalVariables * sizeof(float)) +
 216 (numberOfImportedF64GlobalVariables * sizeof(double));
 217 m_module->globalData().data = fastMalloc(globalDataSize);
 218 void* globalAddress = m_module->globalData().data;
 219
 220 for (uint32_t i = 0; i < numberOfNonImportedI32GlobalVariables; ++i) {
 221 globalVariableTypes.append(WASMType::I32);
 222 *((uint32_t*)globalAddress) = 0;
 223 globalVariableAddresses.append(globalAddress);
 224 globalAddress = (uint32_t*)globalAddress + 1;
 225 }
 226 for (uint32_t i = 0; i < numberOfNonImportedF32GlobalVariables; ++i) {
 227 globalVariableTypes.append(WASMType::F32);
 228 *((float*)globalAddress) = 0.f;
 229 globalVariableAddresses.append(globalAddress);
 230 globalAddress = (float*)globalAddress + 1;
 231 }
 232 globalAddress = bitwise_cast<void*>((bitwise_cast<uintptr_t>(globalAddress) + 8 - 1) & ~static_cast<uintptr_t>(8 - 1));
 233 for (uint32_t i = 0; i < numberOfNonImportedF64GlobalVariables; ++i) {
 234 globalVariableTypes.append(WASMType::F64);
 235 *((double*)globalAddress) = 0.0;
 236 globalVariableAddresses.append(globalAddress);
 237 globalAddress = (double*)globalAddress + 1;
 238 }
 239 for (uint32_t i = 0; i < numberOfImportedI32GlobalVariables; ++i) {
 240 String importName;
 241 READ_STRING_OR_FAIL(importName, "Cannot read the import name of an int32 global variable.");
 242 globalVariableTypes.append(WASMType::I32);
 243
 244 // FIXME: D.R.Y.
 245
 246 Identifier identifier = Identifier::fromString(&exec->vm(), importName);
 247 PropertySlot slot(env);
 248
 249 if (!env->getPropertySlot(exec, identifier, slot)) {
 250 // FIXME: Don't use fprintf.
 251 fprintf(stderr, "Can't find a global variable named \"%s\".\n", importName.utf8().data());
 252 FAIL_WITH_MESSAGE("Can't find a global variable.");
 253 }
 254
 255 JSValue value = slot.getValue(exec, identifier);
 256 FAIL_IF_FALSE(value.isNumber() || value.isBoolean(), "An imported global variable is not a number.");
 257
 258 *((uint32_t*)globalAddress) = value.toUInt32(exec);
 259 globalVariableAddresses.append(globalAddress);
 260 globalAddress = (uint32_t*)globalAddress + 1;
 261 }
 262 for (uint32_t i = 0; i < numberOfImportedF32GlobalVariables; ++i) {
 263 String importName;
 264 READ_STRING_OR_FAIL(importName, "Cannot read the import name of a float32 global variable.");
 265 globalVariableTypes.append(WASMType::F32);
 266
 267 // FIXME
 268 *((float*)globalAddress) = 0.f;
 269 globalVariableAddresses.append(globalAddress);
 270 globalAddress = (float*)globalAddress + 1;
 271
 272 RELEASE_ASSERT_NOT_REACHED();
 273 }
 274 globalAddress = bitwise_cast<void*>((bitwise_cast<uintptr_t>(globalAddress) + 8 - 1) & ~static_cast<uintptr_t>(8 - 1));
 275 for (uint32_t i = 0; i < numberOfImportedF64GlobalVariables; ++i) {
 276 String importName;
 277 READ_STRING_OR_FAIL(importName, "Cannot read the import name of a float64 global variable.");
 278 globalVariableTypes.append(WASMType::F64);
 279
 280 // FIXME: D.R.Y.
 281
 282 Identifier identifier = Identifier::fromString(&exec->vm(), importName);
 283 PropertySlot slot(env);
 284
 285 if (!env->getPropertySlot(exec, identifier, slot)) {
 286 // FIXME: Don't use fprintf.
 287 fprintf(stderr, "Can't find a global variable named \"%s\".\n", importName.utf8().data());
 288 FAIL_WITH_MESSAGE("Can't find a global variable.");
 289 }
 290
 291 JSValue value = slot.getValue(exec, identifier);
 292 FAIL_IF_FALSE(value.isNumber(), "An imported global variable is not a number.");
 293
 294 *((double*)globalAddress) = value.toNumber(exec);
 295 globalVariableAddresses.append(globalAddress);
 296 globalAddress = (double*)globalAddress + 1;
 297 }
 298
 299 ASSERT(bitwise_cast<uintptr_t>(globalAddress) <= bitwise_cast<uintptr_t>(m_module->globalData().data) + globalDataSize);
 300}
 301
 302void WASMModuleParser::parseFunctionDeclarationSection()
 303{
 304 uint32_t numberOfFunctionDeclarations;
 305 READ_COMPACT_UINT32_OR_FAIL(numberOfFunctionDeclarations, "Cannot read the number of function declarations.");
 306 m_module->functionDeclarations().reserveInitialCapacity(numberOfFunctionDeclarations);
 307 for (uint32_t i = 0; i < numberOfFunctionDeclarations; ++i) {
 308 WASMFunctionDeclaration functionDeclaration;
 309 READ_COMPACT_UINT32_OR_FAIL(functionDeclaration.signatureIndex, "Cannot read the signature index.");
 310 FAIL_IF_FALSE(functionDeclaration.signatureIndex < m_module->signatures().size(), "The signature index is incorrect.");
 311 m_module->functionDeclarations().append(functionDeclaration);
 312 }
 313}
 314
 315void WASMModuleParser::parseFunctionPointerTableSection()
 316{
 317 uint32_t numberOfFunctionPointerTables;
 318 READ_COMPACT_UINT32_OR_FAIL(numberOfFunctionPointerTables, "Cannot read the number of function pointer tables.");
 319 m_module->functionPointerTables().reserveInitialCapacity(numberOfFunctionPointerTables);
 320 for (uint32_t i = 0; i < numberOfFunctionPointerTables; ++i) {
 321 WASMFunctionPointerTable functionPointerTable;
 322 READ_COMPACT_UINT32_OR_FAIL(functionPointerTable.signatureIndex, "Cannot read the signature index.");
 323 FAIL_IF_FALSE(functionPointerTable.signatureIndex < m_module->signatures().size(), "The signature index is incorrect.");
 324 uint32_t numberOfElements;
 325 READ_COMPACT_UINT32_OR_FAIL(numberOfElements, "Cannot read the number of elements of a function pointer table.");
 326 FAIL_IF_FALSE(hasOneBitSet(numberOfElements), "The number of elements must be a power of two.");
 327 functionPointerTable.elements.reserveInitialCapacity(numberOfElements);
 328 for (uint32_t j = 0; j < numberOfElements; ++j) {
 329 uint32_t element;
 330 READ_COMPACT_UINT32_OR_FAIL(element, "Cannot read an element of a function pointer table.");
 331 functionPointerTable.elements.append(element);
 332 }
 333 m_module->functionPointerTables().append(functionPointerTable);
 334 }
 335}
 336
 337void WASMModuleParser::parseFunctionDefinitionSection(VM& vm, JSGlobalObject* globalObject)
 338{
 339 for (size_t i = 0; i < m_module->functionDeclarations().size(); ++i) {
 340 parseFunctionDefinition(vm, globalObject, i);
 341 PROPAGATE_ERROR();
 342 }
 343}
 344
 345void WASMModuleParser::parseExportSection(VM& vm)
 346{
 347 WASMExportFormat exportFormat;
 348 READ_EXPORT_FORMAT_OR_FAIL(exportFormat, "Cannot read the export format.");
 349 switch (exportFormat) {
 350 case WASMExportFormat::Default: {
 351 uint32_t functionIndex;
 352 READ_COMPACT_UINT32_OR_FAIL(functionIndex, "Cannot read the function index.");
 353 FAIL_IF_FALSE(functionIndex < m_module->functions().size(), "The function index is incorrect.");
 354 Identifier identifier = Identifier::fromString(&vm, "default"); // TODO: Use other names
 355 m_module->putDirect(vm, identifier, m_module->functions()[functionIndex].get());
 356 break;
 357 }
 358 case WASMExportFormat::Record: {
 359 uint32_t numberOfExports;
 360 READ_COMPACT_UINT32_OR_FAIL(numberOfExports, "Cannot read the number of exports.");
 361 for (uint32_t exportIndex = 0; exportIndex < numberOfExports; ++exportIndex) {
 362 String exportName;
 363 READ_STRING_OR_FAIL(exportName, "Cannot read the function export name.");
 364 // TODO: Check if exportName is legal.
 365 uint32_t functionIndex;
 366 READ_COMPACT_UINT32_OR_FAIL(functionIndex, "Cannot read the function index.");
 367 FAIL_IF_FALSE(functionIndex < m_module->functions().size(), "The function index is incorrect.");
 368 Identifier identifier = Identifier::fromString(&vm, exportName);
 369 m_module->putDirect(vm, identifier, m_module->functions()[functionIndex].get());
 370 }
 371 break;
 372 }
 373 default:
 374 ASSERT_NOT_REACHED();
 375 }
 376}
 377
 378void WASMModuleParser::parseFunctionDefinition(VM& vm, JSGlobalObject* globalObject, size_t functionIndex)
 379{
 380 unsigned startOffsetInSource = m_reader.index();
 381 unsigned endOffsetInSource;
 382 unsigned stackHeight;
 383 String errorMessage;
 384 if (!WASMFunctionParser::checkSyntax(m_module, m_source, functionIndex, startOffsetInSource, endOffsetInSource, stackHeight, errorMessage)) {
 385 m_errorMessage = errorMessage;
 386 return;
 387 }
 388
 389 SourceCode source(m_source.provider(), startOffsetInSource, endOffsetInSource, 1, 1);
 390
 391 UnlinkedFunctionExecutable* unlinkedFunctionExecutable = UnlinkedFunctionExecutable::create(&vm, startOffsetInSource, endOffsetInSource - startOffsetInSource, m_module, functionIndex, stackHeight);
 392 FunctionExecutable* functionExecutable = unlinkedFunctionExecutable->link(vm, m_source);
64393
65  // TODO: parse the rest
 394 JSFunction* jsFunction = JSFunction::create(vm, functionExecutable, globalObject);
 395 m_module->functions().append(WriteBarrier<JSFunction>(vm, m_module, jsFunction));
66396
67  return true;
 397 m_reader.setIndex(endOffsetInSource);
68398}
69399
70 JSWASMModule* parseWebAssembly(ExecState* exec, const SourceCode& source, String& errorMessage)
 400JSWASMModule* parseWebAssembly(ExecState* exec, const SourceCode& source, JSObject* env, JSArrayBuffer* arrayBuffer, String& errorMessage)
71401{
72  WASMModuleParser WASMModuleParser(source);
73  return WASMModuleParser.parse(exec->vm(), exec->lexicalGlobalObject(), errorMessage);
 402 WASMModuleParser moduleParser(source);
 403 return moduleParser.parse(exec->vm(), exec->lexicalGlobalObject(), exec, env, arrayBuffer, errorMessage);
74404}
75405
76406} // namespace JSC

Source/JavaScriptCore/wasm/WASMModuleParser.h

2828
2929#if ENABLE(WEBASSEMBLY)
3030
 31#include "JSObject.h"
 32#include "JSWASMModule.h"
3133#include "WASMReader.h"
32 #include <wtf/text/WTFString.h>
3334
3435namespace JSC {
3536
36 class ExecState;
37 class JSGlobalObject;
38 class JSWASMModule;
39 class SourceCode;
40 class VM;
41 
4237class WASMModuleParser {
4338public:
44  WASMModuleParser(const SourceCode&);
45  JSWASMModule* parse(VM&, JSGlobalObject*, String& errorMessage);
 39 WASMModuleParser(const SourceCode& source)
 40 : m_reader(static_cast<WebAssemblySourceProvider*>(source.provider())->data())
 41 , m_source(source)
 42 {
 43 }
 44
 45 JSWASMModule* parse(VM&, JSGlobalObject*, ExecState*, JSObject* env, JSArrayBuffer*, String& errorMessage);
4646
4747private:
48  bool parseModule();
 48 void parseModule(VM&, JSGlobalObject*, ExecState*, JSObject* env);
 49 void parseConstantPoolSection();
 50 void parseSignatureSection();
 51 void parseFunctionImportSection(ExecState*, JSObject* env);
 52 void parseGlobalSection(ExecState*, JSObject* env);
 53 void parseFunctionDeclarationSection();
 54 void parseFunctionPointerTableSection();
 55 void parseFunctionDefinitionSection(VM&, JSGlobalObject*);
 56 void parseExportSection(VM&);
 57
 58 void parseFunctionDefinition(VM&, JSGlobalObject*, size_t functionIndex);
4959
 60 JSWASMModule* m_module; // FIXME: shouldn't be a state
5061 WASMReader m_reader;
 62 const SourceCode& m_source; // FIXME:
5163 String m_errorMessage;
5264};
5365
54 JS_EXPORT_PRIVATE JSWASMModule* parseWebAssembly(ExecState*, const SourceCode&, String& errorMessage);
 66JS_EXPORT_PRIVATE JSWASMModule* parseWebAssembly(ExecState*, const SourceCode&, JSObject* env, JSArrayBuffer*, String& errorMessage);
5567
5668} // namespace JSC
5769

Source/JavaScriptCore/wasm/WASMReader.cpp

2323 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424 */
2525
 26/*
 27 Licensed under the Apache License, Version 2.0 (the "License");
 28 you may not use this file except in compliance with the License.
 29 You may obtain a copy of the License at
 30
 31 http://www.apache.org/licenses/LICENSE-2.0
 32
 33 Unless required by applicable law or agreed to in writing, software
 34 distributed under the License is distributed on an "AS IS" BASIS,
 35 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 36 See the License for the specific language governing permissions and
 37 limitations under the License.
 38*/
 39
2640#include "config.h"
2741#include "WASMReader.h"
2842

3246
3347namespace JSC {
3448
35 bool WASMReader::readUnsignedInt32(uint32_t& result)
 49bool WASMReader::readUInt32(uint32_t& result)
3650{
3751 CHECK_READ(4);
3852 result = m_cursor[0] | m_cursor[1] << 8 | m_cursor[2] << 16 | m_cursor[3] << 24;

@@bool WASMReader::readDouble(double& result)
7690 return true;
7791}
7892
 93bool WASMReader::readCompactUInt32(uint32_t& result)
 94{
 95 uint32_t sum = 0;
 96 unsigned shift = 0;
 97 do {
 98 CHECK_READ(1);
 99 uint8_t byte = *m_cursor++;
 100 if (byte < 0x80) {
 101 if ((shift == 28 && byte >= 0x10) || (shift && !byte))
 102 return false;
 103 result = sum | (byte << shift);
 104 return true;
 105 }
 106 sum |= (byte & 0x7f) << shift;
 107 shift += 7;
 108 } while (shift < 35);
 109 return false;
 110}
 111
 112bool WASMReader::readCompactInt32(uint32_t& result)
 113{
 114 uint32_t sum = 0;
 115 unsigned shift = 0;
 116 do {
 117 CHECK_READ(1);
 118 uint8_t byte = *m_cursor++;
 119 if (byte < 0x80) {
 120 // FIXME: Add special checks if shift == 28.
 121 sum |= byte << shift;
 122 int signExtend = (32 - 7) - shift;
 123 if (signExtend > 0)
 124 result = int32_t(sum) << signExtend >> signExtend;
 125 else
 126 result = int32_t(sum);
 127 return true;
 128 }
 129 sum |= (byte & 0x7f) << shift;
 130 shift += 7;
 131 } while (shift < 35);
 132 return false;
 133}
 134
 135bool WASMReader::readString(String& result)
 136{
 137 StringBuilder builder;
 138 while (true) {
 139 CHECK_READ(1);
 140 char c = *m_cursor++;
 141 if (!c)
 142 break;
 143 builder.append(c);
 144 }
 145 result = builder.toString();
 146 return true;
 147}
 148
 149bool WASMReader::readType(WASMType& result)
 150{
 151 return readByte<WASMType>(result, (uint8_t)WASMType::NumberOfTypes);
 152}
 153
 154bool WASMReader::readExpressionType(WASMExpressionType& result)
 155{
 156 return readByte<WASMExpressionType>(result, (uint8_t)WASMExpressionType::NumberOfExpressionTypes);
 157}
 158
 159bool WASMReader::readExportFormat(WASMExportFormat& result)
 160{
 161 return readByte<WASMExportFormat>(result, (uint8_t)WASMExportFormat::NumberOfExportFormats);
 162}
 163
 164bool WASMReader::readSwitchCase(WASMSwitchCase& result)
 165{
 166 return readByte<WASMSwitchCase>(result, (uint8_t)WASMSwitchCase::NumberOfSwitchCases);
 167}
 168
 169template <class T> bool WASMReader::readByte(T& result, uint8_t numberOfValues)
 170{
 171 CHECK_READ(1);
 172 uint8_t byte = *m_cursor++;
 173 if (byte >= numberOfValues)
 174 return false;
 175 result = T(byte);
 176 return true;
 177}
 178
 179// FIXME: Remove this.
 180uint32_t WASMReader::readUnsignedInt32()
 181{
 182 uint32_t result = *m_cursor++;
 183 if (result < 0x80)
 184 return result;
 185 result &= 0x7f;
 186 unsigned shift = 7;
 187 while (true) {
 188 uint32_t byte = *m_cursor++;
 189 if (byte < 0x80) {
 190 result |= (byte << shift);
 191 return result;
 192 }
 193 result |= (byte & 0x7f) << shift;
 194 shift += 7;
 195 }
 196}
 197
 198// FIXME: Use CHECK_READ().
 199bool WASMReader::ifI32Literal(const Vector<uint32_t>& i32Constants, uint32_t* u32)
 200{
 201 uint8_t byte = *m_cursor;
 202
 203 if (byte & hasImmediateFlag) {
 204 WASMOpExpressionI32WithImmediate opWithImmediate = WASMOpExpressionI32WithImmediate((byte >> immediateBits) & (opWithImmediateLimit - 1));
 205 uint8_t immediate = byte & (immediateLimit - 1);
 206
 207 if (opWithImmediate == WASMOpExpressionI32WithImmediate::LitImm) {
 208 m_cursor++;
 209 *u32 = immediate;
 210 return true;
 211 }
 212
 213 if (opWithImmediate == WASMOpExpressionI32WithImmediate::LitPool) {
 214 m_cursor++;
 215 *u32 = i32Constants[immediate];
 216 return true;
 217 }
 218
 219 return false;
 220 }
 221
 222 if (WASMOpExpressionI32(byte) == WASMOpExpressionI32::LitImm) {
 223 m_cursor++;
 224 *u32 = readUnsignedInt32();
 225 return true;
 226 }
 227
 228 if (WASMOpExpressionI32(byte) == WASMOpExpressionI32::LitPool) {
 229 m_cursor++;
 230 *u32 = i32Constants[readUnsignedInt32()];
 231 return true;
 232 }
 233
 234 return false;
 235}
 236
79237} // namespace JSC
80238
81239#endif // ENABLE(WEBASSEMBLY)

Source/JavaScriptCore/wasm/WASMReader.h

2828
2929#if ENABLE(WEBASSEMBLY)
3030
31 #include <wtf/Vector.h>
 31#include "WASMConstants.h"
 32#include "WASMFormat.h"
 33#include <wtf/text/StringBuilder.h>
3234
3335namespace JSC {
3436

@@public:
4042 {
4143 }
4244
43  bool readUnsignedInt32(uint32_t& result);
 45 unsigned index() const { return m_cursor - m_buffer.data(); }
 46 void setIndex(unsigned index) { m_cursor = m_buffer.data() + index; }
 47
 48 bool readUInt32(uint32_t& result);
4449 bool readFloat(float& result);
4550 bool readDouble(double& result);
 51 bool readCompactUInt32(uint32_t& result);
 52 bool readCompactInt32(uint32_t& result);
 53 bool readString(String& result);
 54 bool readType(WASMType& result);
 55 bool readExpressionType(WASMExpressionType& result);
 56 bool readExportFormat(WASMExportFormat& result);
 57 bool readSwitchCase(WASMSwitchCase& result);
 58
 59 template<class T, class TWithImmediate> inline bool readCode(T*, TWithImmediate*, uint8_t* immediate);
 60 WASMOpExpressionVoid readOpExpressionVoid() { return readByte<WASMOpExpressionVoid>(); }
 61 bool ifI32Literal(const Vector<uint32_t>& i32s, uint32_t*);
4662
4763private:
 64 template <class T> bool readByte(T& result, uint8_t numberOfValues);
 65 template <class T> T readByte() { return T(*m_cursor++); }
 66 uint32_t readUnsignedInt32();
 67
4868 const Vector<uint8_t>& m_buffer;
4969 const uint8_t* m_cursor;
5070};
5171
 72// FIXME: Use CHECK_READ().
 73template <class T, class TWithImmediate>
 74bool WASMReader::readCode(T* t, TWithImmediate* tWithImmediate, uint8_t* immediate)
 75{
 76 uint8_t byte = *m_cursor++;
 77 if (!(byte & hasImmediateFlag)) {
 78 *t = T(byte);
 79 return true;
 80 }
 81
 82 *tWithImmediate = TWithImmediate((byte >> immediateBits) & (opWithImmediateLimit - 1));
 83 *immediate = byte & (immediateLimit - 1);
 84 return false;
 85}
 86
5287} // namespace JSC
5388
5489#endif // ENABLE(WEBASSEMBLY)

Source/JavaScriptCore/wasm/WASMSyntaxChecker.h

 1/*
 2 * Copyright (C) 2015 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef WASMSyntaxChecker_h
 27#define WASMSyntaxChecker_h
 28
 29#if ENABLE(WEBASSEMBLY)
 30
 31#include "MacroAssembler.h"
 32
 33#define UNUSED 1
 34
 35namespace JSC {
 36
 37class WASMSyntaxChecker {
 38public:
 39 typedef int Expression;
 40 typedef int Statement;
 41 typedef int ExpressionList;
 42 typedef int Jump;
 43 typedef int Label;
 44 struct MemoryAddress {
 45 MemoryAddress(void*) { }
 46 MemoryAddress(bool hasImmediateIndex, uint32_t, Expression, uint32_t)
 47 : hasImmediateIndex(hasImmediateIndex)
 48 {
 49 }
 50 bool hasImmediateIndex;
 51 };
 52
 53 WASMSyntaxChecker()
 54 : m_stackTop(0)
 55 , m_maxStackTop(0)
 56 {
 57 }
 58
 59 void startFunction(const WASMSignature&, uint32_t, uint32_t, uint32_t) { }
 60 void endFunction() { ASSERT(!m_stackTop); }
 61
 62 void setLocal(uint32_t, int, WASMType)
 63 {
 64 m_stackTop--;
 65 }
 66
 67 void returnStatement(int, WASMExpressionType returnType)
 68 {
 69 if (returnType != WASMExpressionType::Void)
 70 m_stackTop--;
 71 }
 72
 73 int createLiteralPoolExpressionI32(uint32_t)
 74 {
 75 m_stackTop++;
 76 recordStackTop();
 77 return UNUSED;
 78 }
 79
 80 int createLiteralPoolExpressionF32(uint32_t)
 81 {
 82 m_stackTop++;
 83 recordStackTop();
 84 return UNUSED;
 85 }
 86
 87 int createLiteralPoolExpressionF64(uint32_t)
 88 {
 89 m_stackTop++;
 90 recordStackTop();
 91 return UNUSED;
 92 }
 93
 94 int createLiteralImmediateExpressionI32(uint32_t)
 95 {
 96 m_stackTop++;
 97 recordStackTop();
 98 return UNUSED;
 99 }
 100
 101 int createLiteralImmediateExpressionF32(float)
 102 {
 103 m_stackTop++;
 104 recordStackTop();
 105 return UNUSED;
 106 }
 107
 108 int createLiteralImmediateExpressionF64(double)
 109 {
 110 m_stackTop++;
 111 recordStackTop();
 112 return UNUSED;
 113 }
 114
 115 int createGetLocalExpressionI32(uint32_t)
 116 {
 117 m_stackTop++;
 118 recordStackTop();
 119 return UNUSED;
 120 }
 121
 122 int createGetLocalExpressionF32(uint32_t)
 123 {
 124 m_stackTop++;
 125 recordStackTop();
 126 return UNUSED;
 127 }
 128
 129 int createGetLocalExpressionF64(uint32_t)
 130 {
 131 m_stackTop++;
 132 recordStackTop();
 133 return UNUSED;
 134 }
 135
 136 int createSetLocalExpressionI32(uint32_t, int)
 137 {
 138 return UNUSED;
 139 }
 140
 141 int createSetLocalExpressionF32(uint32_t, int)
 142 {
 143 return UNUSED;
 144 }
 145
 146 int createSetLocalExpressionF64(uint32_t, int)
 147 {
 148 return UNUSED;
 149 }
 150
 151 int createGetGlobalExpressionI32(uint32_t)
 152 {
 153 m_stackTop++;
 154 recordStackTop();
 155 return UNUSED;
 156 }
 157
 158 int createGetGlobalExpressionF32(uint32_t)
 159 {
 160 m_stackTop++;
 161 recordStackTop();
 162 return UNUSED;
 163 }
 164
 165 int createGetGlobalExpressionF64(uint32_t)
 166 {
 167 m_stackTop++;
 168 recordStackTop();
 169 return UNUSED;
 170 }
 171
 172 int createSetGlobal(uint32_t, Expression, WASMType, bool isExpression)
 173 {
 174 if (!isExpression)
 175 m_stackTop--;
 176 return UNUSED;
 177 }
 178
 179 int createLoad(const MemoryAddress& memoryAddress, WASMExpressionType, WASMMemoryType, bool)
 180 {
 181 if (!memoryAddress.hasImmediateIndex)
 182 m_stackTop--;
 183 m_stackTop++;
 184 recordStackTop();
 185 return UNUSED;
 186 }
 187
 188 int createStore(const MemoryAddress& memoryAddress, WASMExpressionType, WASMMemoryType, Expression, bool isExpression)
 189 {
 190 m_stackTop--;
 191 if (!memoryAddress.hasImmediateIndex)
 192 m_stackTop--;
 193 if (isExpression)
 194 m_stackTop++;
 195 return UNUSED;
 196 }
 197
 198 int createCallInternal(uint32_t, const WASMSignature& signature, WASMExpressionType returnType)
 199 {
 200 // FIXME: alignment?
 201 m_stackTop -= signature.arguments.size();
 202 if (returnType != WASMExpressionType::Void) {
 203 m_stackTop++;
 204 recordStackTop();
 205 }
 206 return UNUSED;
 207 }
 208
 209 int createCallIndirect(uint32_t, int, const WASMSignature& signature, WASMExpressionType returnType)
 210 {
 211 // FIXME: alignment?
 212 m_stackTop -= signature.arguments.size() + 1;
 213 if (returnType != WASMExpressionType::Void) {
 214 m_stackTop++;
 215 recordStackTop();
 216 }
 217 return UNUSED;
 218 }
 219
 220 int createCallImport(uint32_t, const WASMSignature& signature, WASMExpressionType returnType)
 221 {
 222 // FIXME: alignment?
 223 m_stackTop -= signature.arguments.size();
 224 if (returnType != WASMExpressionType::Void) {
 225 m_stackTop++;
 226 recordStackTop();
 227 }
 228 return UNUSED;
 229 }
 230
 231 int createFromF64ExpressionI32(int)
 232 {
 233 return UNUSED;
 234 }
 235
 236 int createFromF64ExpressionF32(int)
 237 {
 238 return UNUSED;
 239 }
 240
 241 int createFromS32ExpressionF64(int)
 242 {
 243 return UNUSED;
 244 }
 245
 246 int createFromU32ExpressionF64(int)
 247 {
 248 return UNUSED;
 249 }
 250
 251 int createUnaryExpressionI32(int, WASMOpExpressionI32)
 252 {
 253 return UNUSED;
 254 }
 255
 256 int createUnaryExpressionF64(int, WASMOpExpressionF64)
 257 {
 258 return UNUSED;
 259 }
 260
 261 int createBinaryExpressionI32(int, int, WASMOpExpressionI32)
 262 {
 263 m_stackTop--;
 264 return UNUSED;
 265 }
 266
 267 int createRelationalI32ExpressionI32(int, int, WASMOpExpressionI32)
 268 {
 269 m_stackTop--;
 270 return UNUSED;
 271 }
 272
 273 int createRelationalF64ExpressionI32(int, int, WASMOpExpressionI32)
 274 {
 275 m_stackTop--;
 276 return UNUSED;
 277 }
 278
 279 int createBinaryExpressionF64(int, int, WASMOpExpressionF64)
 280 {
 281 m_stackTop--;
 282 return UNUSED;
 283 }
 284
 285 Jump jitJump() { return UNUSED; }
 286 void jitJump(Label) { }
 287 void jitLinkJump(Jump) { }
 288 void jitLinkJumpToLabel(Jump, Label) { }
 289 Label jitLabel() { return UNUSED; }
 290
 291 Jump jitBranchIfZero(int)
 292 {
 293 m_stackTop--;
 294 return UNUSED;
 295 }
 296
 297 Jump jitBranchIfNonZero(int)
 298 {
 299 m_stackTop--;
 300 return UNUSED;
 301 }
 302
 303 void generateSwitchTable(Expression, const Vector<int32_t>&, bool, const Vector<Label>&)
 304 {
 305 m_stackTop--;
 306 }
 307
 308 void pop() // FIXME: This seems hacky.
 309 {
 310 m_stackTop--;
 311 }
 312
 313 unsigned maxStackTop() const { return m_maxStackTop; }
 314
 315 void startLoop() { }
 316 void endLoop() { }
 317 void startSwitch() { }
 318 void endSwitch() { }
 319 void linkBreak() { }
 320 void linkContinue() { }
 321 void breakStatement() { }
 322 void continueStatement() { }
 323 void startLabel() { }
 324 void endLabel() { }
 325 void breakLabelStatement(uint32_t) { }
 326 void continueLabelStatement(uint32_t) { }
 327
 328private:
 329 void recordStackTop()
 330 {
 331 if (m_stackTop > m_maxStackTop)
 332 m_maxStackTop = m_stackTop;
 333 }
 334
 335 unsigned m_stackTop;
 336 unsigned m_maxStackTop;
 337};
 338
 339} // namespace JSC
 340
 341#endif // ENABLE(WEBASSEMBLY)
 342
 343#endif // WASMSyntaxChecker_h