| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/signature.h" | 5 #include "src/signature.h" |
| 6 | 6 |
| 7 #include "src/bit-vector.h" | 7 #include "src/bit-vector.h" |
| 8 #include "src/flags.h" | 8 #include "src/flags.h" |
| 9 #include "src/handles.h" | 9 #include "src/handles.h" |
| 10 #include "src/zone/zone-containers.h" | 10 #include "src/zone/zone-containers.h" |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 }; | 92 }; |
| 93 | 93 |
| 94 static Value* NO_VALUE = nullptr; | 94 static Value* NO_VALUE = nullptr; |
| 95 | 95 |
| 96 enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry }; | 96 enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry }; |
| 97 | 97 |
| 98 // An entry on the control stack (i.e. if, block, loop). | 98 // An entry on the control stack (i.e. if, block, loop). |
| 99 struct Control { | 99 struct Control { |
| 100 const byte* pc; | 100 const byte* pc; |
| 101 ControlKind kind; | 101 ControlKind kind; |
| 102 int stack_depth; // stack height at the beginning of the construct. | 102 size_t stack_depth; // stack height at the beginning of the construct. |
| 103 SsaEnv* end_env; // end environment for the construct. | 103 SsaEnv* end_env; // end environment for the construct. |
| 104 SsaEnv* false_env; // false environment (only for if). | 104 SsaEnv* false_env; // false environment (only for if). |
| 105 TryInfo* try_info; // Information used for compiling try statements. | 105 TryInfo* try_info; // Information used for compiling try statements. |
| 106 int32_t previous_catch; // The previous Control (on the stack) with a catch. | 106 int32_t previous_catch; // The previous Control (on the stack) with a catch. |
| 107 | 107 |
| 108 // Values merged into the end of this control construct. | 108 // Values merged into the end of this control construct. |
| 109 MergeValues merge; | 109 MergeValues merge; |
| 110 | 110 |
| 111 inline bool is_if() const { return kind == kControlIf; } | 111 inline bool is_if() const { return kind == kControlIf; } |
| 112 inline bool is_block() const { return kind == kControlBlock; } | 112 inline bool is_block() const { return kind == kControlBlock; } |
| 113 inline bool is_loop() const { return kind == kControlLoop; } | 113 inline bool is_loop() const { return kind == kControlLoop; } |
| 114 inline bool is_try() const { return kind == kControlTry; } | 114 inline bool is_try() const { return kind == kControlTry; } |
| 115 | 115 |
| 116 // Named constructors. | 116 // Named constructors. |
| 117 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env, | 117 static Control Block(const byte* pc, size_t stack_depth, SsaEnv* end_env, |
| 118 int32_t previous_catch) { | 118 int32_t previous_catch) { |
| 119 return {pc, kControlBlock, stack_depth, end_env, | 119 return {pc, kControlBlock, stack_depth, end_env, |
| 120 nullptr, nullptr, previous_catch, {0, {NO_VALUE}}}; | 120 nullptr, nullptr, previous_catch, {0, {NO_VALUE}}}; |
| 121 } | 121 } |
| 122 | 122 |
| 123 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, | 123 static Control If(const byte* pc, size_t stack_depth, SsaEnv* end_env, |
| 124 SsaEnv* false_env, int32_t previous_catch) { | 124 SsaEnv* false_env, int32_t previous_catch) { |
| 125 return {pc, kControlIf, stack_depth, end_env, | 125 return {pc, kControlIf, stack_depth, end_env, |
| 126 false_env, nullptr, previous_catch, {0, {NO_VALUE}}}; | 126 false_env, nullptr, previous_catch, {0, {NO_VALUE}}}; |
| 127 } | 127 } |
| 128 | 128 |
| 129 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env, | 129 static Control Loop(const byte* pc, size_t stack_depth, SsaEnv* end_env, |
| 130 int32_t previous_catch) { | 130 int32_t previous_catch) { |
| 131 return {pc, kControlLoop, stack_depth, end_env, | 131 return {pc, kControlLoop, stack_depth, end_env, |
| 132 nullptr, nullptr, previous_catch, {0, {NO_VALUE}}}; | 132 nullptr, nullptr, previous_catch, {0, {NO_VALUE}}}; |
| 133 } | 133 } |
| 134 | 134 |
| 135 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, | 135 static Control Try(const byte* pc, size_t stack_depth, SsaEnv* end_env, |
| 136 Zone* zone, SsaEnv* catch_env, int32_t previous_catch) { | 136 Zone* zone, SsaEnv* catch_env, int32_t previous_catch) { |
| 137 DCHECK_NOT_NULL(catch_env); | 137 DCHECK_NOT_NULL(catch_env); |
| 138 TryInfo* try_info = new (zone) TryInfo(catch_env); | 138 TryInfo* try_info = new (zone) TryInfo(catch_env); |
| 139 return {pc, kControlTry, stack_depth, end_env, | 139 return {pc, kControlTry, stack_depth, end_env, |
| 140 nullptr, try_info, previous_catch, {0, {NO_VALUE}}}; | 140 nullptr, try_info, previous_catch, {0, {NO_VALUE}}}; |
| 141 } | 141 } |
| 142 }; | 142 }; |
| 143 | 143 |
| 144 // Macros that build nodes only if there is a graph and the current SSA | 144 // Macros that build nodes only if there is a graph and the current SSA |
| 145 // environment is reachable from start. This avoids problems with malformed | 145 // environment is reachable from start. This avoids problems with malformed |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 if (c->merge.arity == 1) { | 647 if (c->merge.arity == 1) { |
| 648 c->merge.vals.first = {pc_, nullptr, sig_->GetReturn(0)}; | 648 c->merge.vals.first = {pc_, nullptr, sig_->GetReturn(0)}; |
| 649 } else if (c->merge.arity > 1) { | 649 } else if (c->merge.arity > 1) { |
| 650 c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity); | 650 c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity); |
| 651 for (unsigned i = 0; i < c->merge.arity; i++) { | 651 for (unsigned i = 0; i < c->merge.arity; i++) { |
| 652 c->merge.vals.array[i] = {pc_, nullptr, sig_->GetReturn(i)}; | 652 c->merge.vals.array[i] = {pc_, nullptr, sig_->GetReturn(i)}; |
| 653 } | 653 } |
| 654 } | 654 } |
| 655 } | 655 } |
| 656 | 656 |
| 657 if (pc_ >= end_) return; // Nothing to do. | 657 while (pc_ < end_) { // decoding loop. |
| 658 | |
| 659 while (true) { // decoding loop. | |
| 660 unsigned len = 1; | 658 unsigned len = 1; |
| 661 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); | 659 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); |
| 662 if (!WasmOpcodes::IsPrefixOpcode(opcode)) { | 660 if (!WasmOpcodes::IsPrefixOpcode(opcode)) { |
| 663 TRACE(" @%-8d #%02x:%-20s|", startrel(pc_), opcode, | 661 TRACE(" @%-8d #%02x:%-20s|", startrel(pc_), opcode, |
| 664 WasmOpcodes::ShortOpcodeName(opcode)); | 662 WasmOpcodes::ShortOpcodeName(opcode)); |
| 665 } | 663 } |
| 666 | 664 |
| 667 FunctionSig* sig = WasmOpcodes::Signature(opcode); | 665 FunctionSig* sig = WasmOpcodes::Signature(opcode); |
| 668 if (sig) { | 666 if (sig) { |
| 669 BuildSimpleOperator(opcode, sig); | 667 BuildSimpleOperator(opcode, sig); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 // A loop just leaves the values on the stack. | 802 // A loop just leaves the values on the stack. |
| 805 TypeCheckLoopFallThru(c); | 803 TypeCheckLoopFallThru(c); |
| 806 PopControl(); | 804 PopControl(); |
| 807 SetEnv("loop:end", ssa_env_); | 805 SetEnv("loop:end", ssa_env_); |
| 808 break; | 806 break; |
| 809 } | 807 } |
| 810 if (c->is_if()) { | 808 if (c->is_if()) { |
| 811 if (c->false_env != nullptr) { | 809 if (c->false_env != nullptr) { |
| 812 // End the true branch of a one-armed if. | 810 // End the true branch of a one-armed if. |
| 813 Goto(c->false_env, c->end_env); | 811 Goto(c->false_env, c->end_env); |
| 814 if (ssa_env_->go() && | 812 if (ssa_env_->go() && stack_.size() != c->stack_depth) { |
| 815 static_cast<int>(stack_.size()) != c->stack_depth) { | |
| 816 error("end of if expected empty stack"); | 813 error("end of if expected empty stack"); |
| 817 stack_.resize(c->stack_depth); | 814 stack_.resize(c->stack_depth); |
| 818 } | 815 } |
| 819 if (c->merge.arity > 0) { | 816 if (c->merge.arity > 0) { |
| 820 error("non-void one-armed if"); | 817 error("non-void one-armed if"); |
| 821 } | 818 } |
| 822 name = "if:merge"; | 819 name = "if:merge"; |
| 823 } else { | 820 } else { |
| 824 // End the false branch of a two-armed if. | 821 // End the false branch of a two-armed if. |
| 825 name = "if_else:merge"; | 822 name = "if_else:merge"; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 839 // Push the end values onto the stack. | 836 // Push the end values onto the stack. |
| 840 stack_.resize(c->stack_depth); | 837 stack_.resize(c->stack_depth); |
| 841 if (c->merge.arity == 1) { | 838 if (c->merge.arity == 1) { |
| 842 stack_.push_back(c->merge.vals.first); | 839 stack_.push_back(c->merge.vals.first); |
| 843 } else { | 840 } else { |
| 844 for (unsigned i = 0; i < c->merge.arity; i++) { | 841 for (unsigned i = 0; i < c->merge.arity; i++) { |
| 845 stack_.push_back(c->merge.vals.array[i]); | 842 stack_.push_back(c->merge.vals.array[i]); |
| 846 } | 843 } |
| 847 } | 844 } |
| 848 | 845 |
| 849 PopControl(); | 846 if (control_.size() == 1) { |
| 850 | 847 // If at the last (implicit) control, check we are at end. |
| 851 if (control_.empty()) { | |
| 852 // If the last (implicit) control was popped, check we are at end. | |
| 853 if (pc_ + 1 != end_) { | 848 if (pc_ + 1 != end_) { |
| 854 error(pc_, pc_ + 1, "trailing code after function end"); | 849 error(pc_, pc_ + 1, "trailing code after function end"); |
| 850 break; |
| 855 } | 851 } |
| 856 last_end_found_ = true; | 852 last_end_found_ = true; |
| 857 if (ssa_env_->go()) { | 853 if (ssa_env_->go()) { |
| 858 // The result of the block is the return value. | 854 // The result of the block is the return value. |
| 859 TRACE(" @%-8d #xx:%-20s|", startrel(pc_), "ImplicitReturn"); | 855 TRACE(" @%-8d #xx:%-20s|", startrel(pc_), "ImplicitReturn"); |
| 860 DoReturn(); | 856 DoReturn(); |
| 861 TRACE("\n"); | 857 TRACE("\n"); |
| 862 } | 858 } |
| 863 return; | |
| 864 } | 859 } |
| 860 PopControl(); |
| 865 break; | 861 break; |
| 866 } | 862 } |
| 867 case kExprSelect: { | 863 case kExprSelect: { |
| 868 Value cond = Pop(2, kWasmI32); | 864 Value cond = Pop(2, kWasmI32); |
| 869 Value fval = Pop(); | 865 Value fval = Pop(); |
| 870 Value tval = Pop(); | 866 Value tval = Pop(); |
| 871 if (tval.type == kWasmStmt || tval.type != fval.type) { | 867 if (tval.type == kWasmStmt || tval.type != fval.type) { |
| 872 if (tval.type != kWasmEnd && fval.type != kWasmEnd) { | 868 if (tval.type != kWasmEnd && fval.type != kWasmEnd) { |
| 873 error("type mismatch in select"); | 869 error("type mismatch in select"); |
| 874 break; | 870 break; |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1234 break; | 1230 break; |
| 1235 } | 1231 } |
| 1236 default: | 1232 default: |
| 1237 break; | 1233 break; |
| 1238 } | 1234 } |
| 1239 } | 1235 } |
| 1240 PrintF("\n"); | 1236 PrintF("\n"); |
| 1241 } | 1237 } |
| 1242 #endif | 1238 #endif |
| 1243 pc_ += len; | 1239 pc_ += len; |
| 1244 if (pc_ >= end_) { | |
| 1245 // End of code reached or exceeded. | |
| 1246 if (pc_ > end_ && ok()) error("Beyond end of code"); | |
| 1247 return; | |
| 1248 } | |
| 1249 } // end decode loop | 1240 } // end decode loop |
| 1241 if (pc_ > end_ && ok()) error("Beyond end of code"); |
| 1250 } | 1242 } |
| 1251 | 1243 |
| 1252 void EndControl() { ssa_env_->Kill(SsaEnv::kControlEnd); } | 1244 void EndControl() { ssa_env_->Kill(SsaEnv::kControlEnd); } |
| 1253 | 1245 |
| 1254 void SetBlockType(Control* c, BlockTypeOperand& operand) { | 1246 void SetBlockType(Control* c, BlockTypeOperand& operand) { |
| 1255 c->merge.arity = operand.arity; | 1247 c->merge.arity = operand.arity; |
| 1256 if (c->merge.arity == 1) { | 1248 if (c->merge.arity == 1) { |
| 1257 c->merge.vals.first = {pc_, nullptr, operand.read_entry(0)}; | 1249 c->merge.vals.first = {pc_, nullptr, operand.read_entry(0)}; |
| 1258 } else if (c->merge.arity > 1) { | 1250 } else if (c->merge.arity > 1) { |
| 1259 c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity); | 1251 c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1279 } | 1271 } |
| 1280 return nullptr; | 1272 return nullptr; |
| 1281 } | 1273 } |
| 1282 } | 1274 } |
| 1283 | 1275 |
| 1284 ValueType GetReturnType(FunctionSig* sig) { | 1276 ValueType GetReturnType(FunctionSig* sig) { |
| 1285 return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn(); | 1277 return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn(); |
| 1286 } | 1278 } |
| 1287 | 1279 |
| 1288 void PushBlock(SsaEnv* end_env) { | 1280 void PushBlock(SsaEnv* end_env) { |
| 1289 const int stack_depth = static_cast<int>(stack_.size()); | |
| 1290 control_.emplace_back( | 1281 control_.emplace_back( |
| 1291 Control::Block(pc_, stack_depth, end_env, current_catch_)); | 1282 Control::Block(pc_, stack_.size(), end_env, current_catch_)); |
| 1292 } | 1283 } |
| 1293 | 1284 |
| 1294 void PushLoop(SsaEnv* end_env) { | 1285 void PushLoop(SsaEnv* end_env) { |
| 1295 const int stack_depth = static_cast<int>(stack_.size()); | |
| 1296 control_.emplace_back( | 1286 control_.emplace_back( |
| 1297 Control::Loop(pc_, stack_depth, end_env, current_catch_)); | 1287 Control::Loop(pc_, stack_.size(), end_env, current_catch_)); |
| 1298 } | 1288 } |
| 1299 | 1289 |
| 1300 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { | 1290 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { |
| 1301 const int stack_depth = static_cast<int>(stack_.size()); | |
| 1302 control_.emplace_back( | 1291 control_.emplace_back( |
| 1303 Control::If(pc_, stack_depth, end_env, false_env, current_catch_)); | 1292 Control::If(pc_, stack_.size(), end_env, false_env, current_catch_)); |
| 1304 } | 1293 } |
| 1305 | 1294 |
| 1306 void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { | 1295 void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { |
| 1307 const int stack_depth = static_cast<int>(stack_.size()); | 1296 control_.emplace_back(Control::Try(pc_, stack_.size(), end_env, zone_, |
| 1308 control_.emplace_back(Control::Try(pc_, stack_depth, end_env, zone_, | |
| 1309 catch_env, current_catch_)); | 1297 catch_env, current_catch_)); |
| 1310 current_catch_ = static_cast<int32_t>(control_.size() - 1); | 1298 current_catch_ = static_cast<int32_t>(control_.size() - 1); |
| 1311 } | 1299 } |
| 1312 | 1300 |
| 1313 void PopControl() { control_.pop_back(); } | 1301 void PopControl() { control_.pop_back(); } |
| 1314 | 1302 |
| 1315 int DecodeLoadMem(ValueType type, MachineType mem_type) { | 1303 int DecodeLoadMem(ValueType type, MachineType mem_type) { |
| 1316 if (!CheckHasMemory()) return 0; | 1304 if (!CheckHasMemory()) return 0; |
| 1317 MemoryAccessOperand operand(this, pc_, | 1305 MemoryAccessOperand operand(this, pc_, |
| 1318 ElementSizeLog2Of(mem_type.representation())); | 1306 ElementSizeLog2Of(mem_type.representation())); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1424 Push(sig->GetReturn(i), rets ? rets[i] : nullptr); | 1412 Push(sig->GetReturn(i), rets ? rets[i] : nullptr); |
| 1425 } | 1413 } |
| 1426 } | 1414 } |
| 1427 | 1415 |
| 1428 const char* SafeOpcodeNameAt(const byte* pc) { | 1416 const char* SafeOpcodeNameAt(const byte* pc) { |
| 1429 if (pc >= end_) return "<end>"; | 1417 if (pc >= end_) return "<end>"; |
| 1430 return WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc)); | 1418 return WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc)); |
| 1431 } | 1419 } |
| 1432 | 1420 |
| 1433 Value Pop(int index, ValueType expected) { | 1421 Value Pop(int index, ValueType expected) { |
| 1434 if (!ssa_env_->go()) { | |
| 1435 // Unreachable code is essentially not typechecked. | |
| 1436 return {pc_, nullptr, expected}; | |
| 1437 } | |
| 1438 Value val = Pop(); | 1422 Value val = Pop(); |
| 1439 if (val.type != expected) { | 1423 if (val.type != expected) { |
| 1440 if (val.type != kWasmEnd) { | 1424 if (val.type != kWasmEnd) { |
| 1441 error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s", | 1425 error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s", |
| 1442 SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected), | 1426 SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected), |
| 1443 SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type)); | 1427 SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type)); |
| 1444 } | 1428 } |
| 1445 } | 1429 } |
| 1446 return val; | 1430 return val; |
| 1447 } | 1431 } |
| 1448 | 1432 |
| 1449 Value Pop() { | 1433 Value Pop() { |
| 1450 if (!ssa_env_->go()) { | |
| 1451 // Unreachable code is essentially not typechecked. | |
| 1452 return {pc_, nullptr, kWasmEnd}; | |
| 1453 } | |
| 1454 size_t limit = control_.empty() ? 0 : control_.back().stack_depth; | 1434 size_t limit = control_.empty() ? 0 : control_.back().stack_depth; |
| 1455 if (stack_.size() <= limit) { | 1435 if (stack_.size() <= limit) { |
| 1456 Value val = {pc_, nullptr, kWasmStmt}; | 1436 Value val = {pc_, nullptr, kWasmEnd}; |
| 1457 error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_)); | 1437 if (ssa_env_->go()) { |
| 1438 // Popping past the current control start in reachable code. |
| 1439 error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_)); |
| 1440 } |
| 1458 return val; | 1441 return val; |
| 1459 } | 1442 } |
| 1460 Value val = stack_.back(); | 1443 Value val = stack_.back(); |
| 1461 stack_.pop_back(); | 1444 stack_.pop_back(); |
| 1462 return val; | 1445 return val; |
| 1463 } | 1446 } |
| 1464 | 1447 |
| 1465 Value PopUpTo(int stack_depth) { | |
| 1466 if (!ssa_env_->go()) { | |
| 1467 // Unreachable code is essentially not typechecked. | |
| 1468 return {pc_, nullptr, kWasmEnd}; | |
| 1469 } | |
| 1470 if (stack_depth == static_cast<int>(stack_.size())) { | |
| 1471 Value val = {pc_, nullptr, kWasmStmt}; | |
| 1472 return val; | |
| 1473 } else { | |
| 1474 DCHECK_LE(stack_depth, stack_.size()); | |
| 1475 Value val = Pop(); | |
| 1476 stack_.resize(stack_depth); | |
| 1477 return val; | |
| 1478 } | |
| 1479 } | |
| 1480 | |
| 1481 int baserel(const byte* ptr) { | 1448 int baserel(const byte* ptr) { |
| 1482 return base_ ? static_cast<int>(ptr - base_) : 0; | 1449 return base_ ? static_cast<int>(ptr - base_) : 0; |
| 1483 } | 1450 } |
| 1484 | 1451 |
| 1485 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } | 1452 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } |
| 1486 | 1453 |
| 1487 void BreakTo(unsigned depth) { | 1454 void BreakTo(unsigned depth) { |
| 1488 if (!ssa_env_->go()) return; | 1455 if (!ssa_env_->go()) return; |
| 1489 Control* c = &control_[control_.size() - depth - 1]; | 1456 Control* c = &control_[control_.size() - depth - 1]; |
| 1490 if (c->is_loop()) { | 1457 if (c->is_loop()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1501 return; | 1468 return; |
| 1502 } | 1469 } |
| 1503 MergeValuesInto(c); | 1470 MergeValuesInto(c); |
| 1504 } | 1471 } |
| 1505 } | 1472 } |
| 1506 | 1473 |
| 1507 void FallThruTo(Control* c) { | 1474 void FallThruTo(Control* c) { |
| 1508 if (!ssa_env_->go()) return; | 1475 if (!ssa_env_->go()) return; |
| 1509 // Merge the value(s) into the end of the block. | 1476 // Merge the value(s) into the end of the block. |
| 1510 int arity = static_cast<int>(c->merge.arity); | 1477 int arity = static_cast<int>(c->merge.arity); |
| 1511 if (c->stack_depth + arity != static_cast<int>(stack_.size())) { | 1478 if (c->stack_depth + arity != stack_.size()) { |
| 1512 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", | 1479 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", |
| 1513 arity, startrel(c->pc)); | 1480 arity, startrel(c->pc)); |
| 1514 return; | 1481 return; |
| 1515 } | 1482 } |
| 1516 MergeValuesInto(c); | 1483 MergeValuesInto(c); |
| 1517 } | 1484 } |
| 1518 | 1485 |
| 1519 inline Value& GetMergeValueFromStack(Control* c, int i) { | 1486 inline Value& GetMergeValueFromStack(Control* c, int i) { |
| 1520 return stack_[stack_.size() - c->merge.arity + i]; | 1487 return stack_[stack_.size() - c->merge.arity + i]; |
| 1521 } | 1488 } |
| 1522 | 1489 |
| 1523 void TypeCheckLoopFallThru(Control* c) { | 1490 void TypeCheckLoopFallThru(Control* c) { |
| 1524 if (!ssa_env_->go()) return; | 1491 if (!ssa_env_->go()) return; |
| 1525 // Fallthru must match arity exactly. | 1492 // Fallthru must match arity exactly. |
| 1526 int arity = static_cast<int>(c->merge.arity); | 1493 int arity = static_cast<int>(c->merge.arity); |
| 1527 if (c->stack_depth + arity != static_cast<int>(stack_.size())) { | 1494 if (c->stack_depth + arity != stack_.size()) { |
| 1528 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", | 1495 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", |
| 1529 arity, startrel(c->pc)); | 1496 arity, startrel(c->pc)); |
| 1530 return; | 1497 return; |
| 1531 } | 1498 } |
| 1532 // Typecheck the values left on the stack. | 1499 // Typecheck the values left on the stack. |
| 1533 for (unsigned i = 0; i < c->merge.arity; i++) { | 1500 for (unsigned i = 0; i < c->merge.arity; i++) { |
| 1534 Value& val = GetMergeValueFromStack(c, i); | 1501 Value& val = GetMergeValueFromStack(c, i); |
| 1535 Value& old = | 1502 Value& old = |
| 1536 c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i]; | 1503 c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i]; |
| 1537 if (val.type != old.type) { | 1504 if (val.type != old.type) { |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2037 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 2004 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 2038 const byte* start, const byte* end) { | 2005 const byte* start, const byte* end) { |
| 2039 Decoder decoder(start, end); | 2006 Decoder decoder(start, end); |
| 2040 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, | 2007 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, |
| 2041 static_cast<int>(num_locals), zone); | 2008 static_cast<int>(num_locals), zone); |
| 2042 } | 2009 } |
| 2043 | 2010 |
| 2044 } // namespace wasm | 2011 } // namespace wasm |
| 2045 } // namespace internal | 2012 } // namespace internal |
| 2046 } // namespace v8 | 2013 } // namespace v8 |
| OLD | NEW |