Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(433)

Side by Side Diff: src/WasmTranslator.cpp

Issue 1918213003: Subzero, Wasm: Dynamically reallocate read buffer. Runtime improvements. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: General improvements Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« runtime/wasm-runtime.cpp ('K') | « src/WasmTranslator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/WasmTranslator.cpp - WASM to Subzero Translation -------===// 1 //===- subzero/src/WasmTranslator.cpp - WASM to Subzero Translation -------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 return OperandNode(nullptr); 673 return OperandNode(nullptr);
674 } 674 }
675 LOG(out << Dest << "\n"); 675 LOG(out << Dest << "\n");
676 return OperandNode(Dest); 676 return OperandNode(Dest);
677 } 677 }
678 Node Unop(wasm::WasmOpcode Opcode, Node Input) { 678 Node Unop(wasm::WasmOpcode Opcode, Node Input) {
679 LOG(out << "Unop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Input 679 LOG(out << "Unop(" << WasmOpcodes::OpcodeName(Opcode) << ", " << Input
680 << ") = "); 680 << ") = ");
681 Ice::Variable *Dest = nullptr; 681 Ice::Variable *Dest = nullptr;
682 switch (Opcode) { 682 switch (Opcode) {
683 // TODO (eholk): merge these next two cases using getConstantInteger
683 case kExprI32Eqz: { 684 case kExprI32Eqz: {
684 Dest = makeVariable(IceType_i32); 685 Dest = makeVariable(IceType_i32);
685 auto *Tmp = makeVariable(IceType_i1); 686 auto *Tmp = makeVariable(IceType_i1);
686 Control()->appendInst(InstIcmp::create(Func, InstIcmp::Eq, Tmp, Input, 687 Control()->appendInst(InstIcmp::create(Func, InstIcmp::Eq, Tmp, Input,
687 Ctx->getConstantInt32(0))); 688 Ctx->getConstantInt32(0)));
688 Control()->appendInst(InstCast::create(Func, InstCast::Zext, Dest, Tmp)); 689 Control()->appendInst(InstCast::create(Func, InstCast::Zext, Dest, Tmp));
689 break; 690 break;
690 } 691 }
691 case kExprI64Eqz: { 692 case kExprI64Eqz: {
692 Dest = makeVariable(IceType_i32); 693 Dest = makeVariable(IceType_i32);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 Dest = makeVariable(IceType_f64); 766 Dest = makeVariable(IceType_f64);
766 const auto FnName = Ctx->getGlobalString("env$$floor_d"); 767 const auto FnName = Ctx->getGlobalString("env$$floor_d");
767 constexpr bool HasTailCall = false; 768 constexpr bool HasTailCall = false;
768 769
769 auto *Call = InstCall::create( 770 auto *Call = InstCall::create(
770 Func, 1, Dest, Ctx->getConstantExternSym(FnName), HasTailCall); 771 Func, 1, Dest, Ctx->getConstantExternSym(FnName), HasTailCall);
771 Call->addArg(Input); 772 Call->addArg(Input);
772 Control()->appendInst(Call); 773 Control()->appendInst(Call);
773 break; 774 break;
774 } 775 }
776 case kExprF32Sqrt: {
777 Dest = makeVariable(IceType_f32);
778 const auto FnName = Ctx->getGlobalString("llvm.sqrt.f32");
779 bool BadInstrinsic = false;
780 const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
781 assert(!BadInstrinsic);
782 assert(Info);
783
784 auto *Call = InstIntrinsicCall::create(
785 Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
786 Call->addArg(Input);
787 Control()->appendInst(Call);
788 break;
789 }
790 case kExprF64Sqrt: {
791 Dest = makeVariable(IceType_f64);
792 const auto FnName = Ctx->getGlobalString("llvm.sqrt.f64");
793 bool BadInstrinsic = false;
794 const auto *Info = Ctx->getIntrinsicsInfo().find(FnName, BadInstrinsic);
795 assert(!BadInstrinsic);
796 assert(Info);
797
798 auto *Call = InstIntrinsicCall::create(
799 Func, 1, Dest, Ctx->getConstantExternSym(FnName), Info->Info);
800 Call->addArg(Input);
801 Control()->appendInst(Call);
802 break;
803 }
775 case kExprI64UConvertI32: 804 case kExprI64UConvertI32:
776 Dest = makeVariable(IceType_i64); 805 Dest = makeVariable(IceType_i64);
777 Control()->appendInst( 806 Control()->appendInst(
778 InstCast::create(Func, InstCast::Zext, Dest, Input)); 807 InstCast::create(Func, InstCast::Zext, Dest, Input));
779 break; 808 break;
780 case kExprI64SConvertI32: 809 case kExprI64SConvertI32:
781 Dest = makeVariable(IceType_i64); 810 Dest = makeVariable(IceType_i64);
782 Control()->appendInst( 811 Control()->appendInst(
783 InstCast::create(Func, InstCast::Sext, Dest, Input)); 812 InstCast::create(Func, InstCast::Sext, Dest, Input));
784 break; 813 break;
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
1058 LOG(out << "Call Result = " << Node(Dest) << "\n"); 1087 LOG(out << "Call Result = " << Node(Dest) << "\n");
1059 return OperandNode(Dest); 1088 return OperandNode(Dest);
1060 } 1089 }
1061 Node CallIndirect(uint32_t SigIndex, Node *Args) { 1090 Node CallIndirect(uint32_t SigIndex, Node *Args) {
1062 LOG(out << "CallIndirect(" << SigIndex << ")\n"); 1091 LOG(out << "CallIndirect(" << SigIndex << ")\n");
1063 // TODO(eholk): Compile to something better than a switch. 1092 // TODO(eholk): Compile to something better than a switch.
1064 const auto *Module = this->Module->module; 1093 const auto *Module = this->Module->module;
1065 assert(Module); 1094 assert(Module);
1066 const auto &IndirectTable = Module->function_table; 1095 const auto &IndirectTable = Module->function_table;
1067 1096
1068 auto *Abort = getAbortTarget(); 1097 auto *Abort = getIndirectFailTarget();
1069 1098
1070 assert(Args[0].toOperand()); 1099 assert(Args[0].toOperand());
1071 1100
1072 auto *Switch = InstSwitch::create(Func, IndirectTable.size(), 1101 auto *Switch = InstSwitch::create(Func, IndirectTable.size(),
1073 Args[0].toOperand(), Abort); 1102 Args[0].toOperand(), Abort);
1074 assert(Abort); 1103 assert(Abort);
1075 1104
1076 const bool HasReturn = Module->signatures[SigIndex]->return_count() != 0; 1105 const bool HasReturn = Module->signatures[SigIndex]->return_count() != 0;
1077 const Ice::Type DestTy = 1106 const Ice::Type DestTy =
1078 HasReturn ? toIceType(Module->signatures[SigIndex]->GetReturn()) 1107 HasReturn ? toIceType(Module->signatures[SigIndex]->GetReturn())
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 // Do the bounds check. 1195 // Do the bounds check.
1167 // 1196 //
1168 // TODO (eholk): Add a command line argument to control whether bounds 1197 // TODO (eholk): Add a command line argument to control whether bounds
1169 // checks are inserted, and maybe add a way to duplicate bounds checks to 1198 // checks are inserted, and maybe add a way to duplicate bounds checks to
1170 // get a better sense of the overhead. 1199 // get a better sense of the overhead.
1171 if (!llvm::dyn_cast<ConstantInteger32>(Base)) { 1200 if (!llvm::dyn_cast<ConstantInteger32>(Base)) {
1172 // TODO (eholk): creating a new basic block on every memory access is 1201 // TODO (eholk): creating a new basic block on every memory access is
1173 // terrible (see https://goo.gl/Zj7DTr). Try adding a new instruction that 1202 // terrible (see https://goo.gl/Zj7DTr). Try adding a new instruction that
1174 // encapsulates this "abort if false" pattern. 1203 // encapsulates this "abort if false" pattern.
1175 auto *CheckPassed = Func->makeNode(); 1204 auto *CheckPassed = Func->makeNode();
1176 auto *CheckFailed = getAbortTarget(); 1205 auto *CheckFailed = getBoundsFailTarget();
1177 1206
1178 auto *Check = makeVariable(IceType_i1); 1207 auto *Check = makeVariable(IceType_i1);
1179 Control()->appendInst(InstIcmp::create(Func, InstIcmp::Ult, Check, Base, 1208 Control()->appendInst(InstIcmp::create(Func, InstIcmp::Ult, Check, Base,
1180 Ctx->getConstantInt32(MemSize))); 1209 Ctx->getConstantInt32(MemSize)));
1181 Control()->appendInst( 1210 Control()->appendInst(
1182 InstBr::create(Func, Check, CheckPassed, CheckFailed)); 1211 InstBr::create(Func, Check, CheckPassed, CheckFailed));
1183 1212
1184 *ControlPtr = OperandNode(CheckPassed); 1213 *ControlPtr = OperandNode(CheckPassed);
1185 } 1214 }
1186 1215
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 void set_effect_ptr(Node *Effect) { this->EffectPtr = Effect; } 1303 void set_effect_ptr(Node *Effect) { this->EffectPtr = Effect; }
1275 1304
1276 private: 1305 private:
1277 wasm::ModuleEnv *Module; 1306 wasm::ModuleEnv *Module;
1278 Node *ControlPtr; 1307 Node *ControlPtr;
1279 Node *EffectPtr; 1308 Node *EffectPtr;
1280 1309
1281 class Cfg *Func; 1310 class Cfg *Func;
1282 GlobalContext *Ctx; 1311 GlobalContext *Ctx;
1283 1312
1284 CfgNode *AbortTarget = nullptr; 1313 CfgNode *BoundsFailTarget = nullptr;
1314 CfgNode *IndirectFailTarget = nullptr;
1285 1315
1286 SizeT NextArg = 0; 1316 SizeT NextArg = 0;
1287 1317
1288 CfgUnorderedMap<Operand *, InstPhi *> PhiMap; 1318 CfgUnorderedMap<Operand *, InstPhi *> PhiMap;
1289 CfgUnorderedMap<Operand *, CfgNode *> DefNodeMap; 1319 CfgUnorderedMap<Operand *, CfgNode *> DefNodeMap;
1290 1320
1291 InstPhi *getDefiningInst(Operand *Op) const { 1321 InstPhi *getDefiningInst(Operand *Op) const {
1292 const auto &Iter = PhiMap.find(Op); 1322 const auto &Iter = PhiMap.find(Op);
1293 if (Iter == PhiMap.end()) { 1323 if (Iter == PhiMap.end()) {
1294 return nullptr; 1324 return nullptr;
(...skipping 17 matching lines...) Expand all
1312 } 1342 }
1313 1343
1314 CfgNode *getDefNode(Operand *Op) const { 1344 CfgNode *getDefNode(Operand *Op) const {
1315 const auto &Iter = DefNodeMap.find(Op); 1345 const auto &Iter = DefNodeMap.find(Op);
1316 if (Iter == DefNodeMap.end()) { 1346 if (Iter == DefNodeMap.end()) {
1317 return nullptr; 1347 return nullptr;
1318 } 1348 }
1319 return Iter->second; 1349 return Iter->second;
1320 } 1350 }
1321 1351
1322 CfgNode *getAbortTarget() { 1352 CfgNode *getBoundsFailTarget() {
1323 if (!AbortTarget) { 1353 if (!BoundsFailTarget) {
1324 // TODO (eholk): Move this node to the end of the CFG, or even better, 1354 // TODO (eholk): Move this node to the end of the CFG, or even better,
1325 // have only one abort block for the whole module. 1355 // have only one abort block for the whole module.
1326 AbortTarget = Func->makeNode(); 1356 BoundsFailTarget = Func->makeNode();
1327 // TODO (eholk): This should probably actually call abort instead. 1357 BoundsFailTarget->appendInst(InstCall::create(
1328 AbortTarget->appendInst(InstUnreachable::create(Func)); 1358 Func, 0, nullptr,
1359 Ctx->getConstantExternSym(Ctx->getGlobalString("__Sz_bounds_fail")),
1360 false));
1361 BoundsFailTarget->appendInst(InstUnreachable::create(Func));
1329 } 1362 }
1330 1363
1331 return AbortTarget; 1364 return BoundsFailTarget;
1365 }
1366 CfgNode *getIndirectFailTarget() {
1367 if (!IndirectFailTarget) {
1368 // TODO (eholk): Move this node to the end of the CFG, or even better,
1369 // have only one abort block for the whole module.
1370 IndirectFailTarget = Func->makeNode();
1371 IndirectFailTarget->appendInst(InstCall::create(
1372 Func, 0, nullptr,
1373 Ctx->getConstantExternSym(Ctx->getGlobalString("__Sz_indirect_fail")),
1374 false));
1375 IndirectFailTarget->appendInst(InstUnreachable::create(Func));
1376 }
1377
1378 return IndirectFailTarget;
1332 } 1379 }
1333 1380
1334 template <typename F = std::function<void(Ostream &)>> void log(F Fn) const { 1381 template <typename F = std::function<void(Ostream &)>> void log(F Fn) const {
1335 if (BuildDefs::dump() && (getFlags().getVerbose() & IceV_Wasm)) { 1382 if (BuildDefs::dump() && (getFlags().getVerbose() & IceV_Wasm)) {
1336 Fn(Ctx->getStrDump()); 1383 Fn(Ctx->getStrDump());
1337 Ctx->getStrDump().flush(); 1384 Ctx->getStrDump().flush();
1338 } 1385 }
1339 } 1386 }
1340 }; 1387 };
1341 1388
(...skipping 15 matching lines...) Expand all
1357 1404
1358 // We don't always know where the incoming branches are in phi nodes, so this 1405 // We don't always know where the incoming branches are in phi nodes, so this
1359 // function finds them. 1406 // function finds them.
1360 Func->fixPhiNodes(); 1407 Func->fixPhiNodes();
1361 1408
1362 Func->computeInOutEdges(); 1409 Func->computeInOutEdges();
1363 1410
1364 return Func; 1411 return Func;
1365 } 1412 }
1366 1413
1367 // TODO(eholk): compute the correct buffer size. This uses 256k by default, 1414 constexpr SizeT InitialBufferSize = 16 << 10; // 16KB
1368 // which has been big enough for testing but is not a general solution.
1369 constexpr SizeT BufferSize = 256 << 10;
1370 1415
1371 WasmTranslator::WasmTranslator(GlobalContext *Ctx) 1416 WasmTranslator::WasmTranslator(GlobalContext *Ctx)
1372 : Translator(Ctx), Buffer(new uint8_t[ ::BufferSize]), 1417 : Translator(Ctx), Buffer(InitialBufferSize) {}
1373 BufferSize(::BufferSize) {}
1374 1418
1375 void WasmTranslator::translate( 1419 void WasmTranslator::translate(
1376 const std::string &IRFilename, 1420 const std::string &IRFilename,
1377 std::unique_ptr<llvm::DataStreamer> InputStream) { 1421 std::unique_ptr<llvm::DataStreamer> InputStream) {
1378 LOG(out << "Initializing v8/wasm stuff..." 1422 LOG(out << "Initializing v8/wasm stuff..."
1379 << "\n"); 1423 << "\n");
1380 Zone Zone; 1424 Zone Zone;
1381 ZoneScope _(&Zone); 1425 ZoneScope _(&Zone);
1382 1426
1383 SizeT BytesRead = InputStream->GetBytes(Buffer.get(), BufferSize); 1427 SizeT BytesRead = 0;
1384 LOG(out << "Read " << BytesRead << " bytes" 1428 while (true) {
1385 << "\n"); 1429 BytesRead +=
1386 assert(BytesRead < BufferSize); 1430 InputStream->GetBytes(&Buffer[BytesRead], Buffer.size() - BytesRead);
1431 LOG(out << "Read " << BytesRead << " bytes"
1432 << "\n");
1433 if (BytesRead < Buffer.size())
1434 break;
1435 Buffer.resize(Buffer.size() * 2);
1436 }
1387 1437
1388 LOG(out << "Decoding module " << IRFilename << "\n"); 1438 LOG(out << "Decoding module " << IRFilename << "\n");
1389 1439
1390 constexpr v8::internal::Isolate *NoIsolate = nullptr; 1440 constexpr v8::internal::Isolate *NoIsolate = nullptr;
1391 auto Result = DecodeWasmModule(NoIsolate, &Zone, Buffer.get(), 1441 auto Result = DecodeWasmModule(NoIsolate, &Zone, Buffer.data(),
1392 Buffer.get() + BytesRead, false, kWasmOrigin); 1442 Buffer.data() + BytesRead, false, kWasmOrigin);
1393 1443
1394 auto Module = Result.val; 1444 auto Module = Result.val;
1395 1445
1396 LOG(out << "Module info:" 1446 LOG(out << "Module info:"
1397 << "\n"); 1447 << "\n");
1398 LOG(out << " min_mem_pages: " << Module->min_mem_pages << "\n"); 1448 LOG(out << " min_mem_pages: " << Module->min_mem_pages << "\n");
1399 LOG(out << " max_mem_pages: " << Module->max_mem_pages << "\n"); 1449 LOG(out << " max_mem_pages: " << Module->max_mem_pages << "\n");
1400 LOG(out << " number of globals: " << Module->globals.size() << "\n"); 1450 LOG(out << " number of globals: " << Module->globals.size() << "\n");
1401 LOG(out << " number of signatures: " << Module->signatures.size() 1451 LOG(out << " number of signatures: " << Module->signatures.size()
1402 << "\n"); 1452 << "\n");
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1533 lowerGlobals(std::move(Globals)); 1583 lowerGlobals(std::move(Globals));
1534 } 1584 }
1535 1585
1536 // Translate each function. 1586 // Translate each function.
1537 for (const auto Fn : Module->functions) { 1587 for (const auto Fn : Module->functions) {
1538 const auto FnName = getFunctionName(Module, Fn.func_index); 1588 const auto FnName = getFunctionName(Module, Fn.func_index);
1539 1589
1540 LOG(out << " " << Fn.func_index << ": " << FnName << "..."); 1590 LOG(out << " " << Fn.func_index << ": " << FnName << "...");
1541 1591
1542 Body.sig = Fn.sig; 1592 Body.sig = Fn.sig;
1543 Body.base = Buffer.get(); 1593 Body.base = Buffer.data();
1544 Body.start = Buffer.get() + Fn.code_start_offset; 1594 Body.start = Buffer.data() + Fn.code_start_offset;
1545 Body.end = Buffer.get() + Fn.code_end_offset; 1595 Body.end = Buffer.data() + Fn.code_end_offset;
1546 1596
1547 auto Func = translateFunction(&Zone, Body); 1597 auto Func = translateFunction(&Zone, Body);
1548 Func->setFunctionName(Ctx->getGlobalString(FnName)); 1598 Func->setFunctionName(Ctx->getGlobalString(FnName));
1549 1599
1550 Ctx->optQueueBlockingPush(makeUnique<CfgOptWorkItem>(std::move(Func))); 1600 Ctx->optQueueBlockingPush(makeUnique<CfgOptWorkItem>(std::move(Func)));
1551 LOG(out << "done.\n"); 1601 LOG(out << "done.\n");
1552 } 1602 }
1553 1603
1554 return; 1604 return;
1555 } 1605 }
1556 1606
1557 #endif // ALLOW_WASM 1607 #endif // ALLOW_WASM
OLDNEW
« runtime/wasm-runtime.cpp ('K') | « src/WasmTranslator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698