Chromium Code Reviews| 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 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 if (pc_ >= end_) return; // Nothing to do. |
| 658 | 658 |
| 659 while (true) { // decoding loop. | 659 while (true) { // decoding loop. |
|
Clemens Hammacher
2017/01/18 15:46:26
You can also simplify this loop by removing the if
titzer
2017/01/18 17:22:17
Yeah, I originally did this on purpose as a manual
| |
| 660 unsigned len = 1; | 660 unsigned len = 1; |
| 661 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); | 661 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); |
| 662 if (!WasmOpcodes::IsPrefixOpcode(opcode)) { | 662 if (!WasmOpcodes::IsPrefixOpcode(opcode)) { |
| 663 TRACE(" @%-8d #%02x:%-20s|", startrel(pc_), opcode, | 663 TRACE(" @%-8d #%02x:%-20s|", startrel(pc_), opcode, |
| 664 WasmOpcodes::ShortOpcodeName(opcode)); | 664 WasmOpcodes::ShortOpcodeName(opcode)); |
| 665 } | 665 } |
| 666 | 666 |
| 667 FunctionSig* sig = WasmOpcodes::Signature(opcode); | 667 FunctionSig* sig = WasmOpcodes::Signature(opcode); |
| 668 if (sig) { | 668 if (sig) { |
| 669 BuildSimpleOperator(opcode, sig); | 669 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. | 804 // A loop just leaves the values on the stack. |
| 805 TypeCheckLoopFallThru(c); | 805 TypeCheckLoopFallThru(c); |
| 806 PopControl(); | 806 PopControl(); |
| 807 SetEnv("loop:end", ssa_env_); | 807 SetEnv("loop:end", ssa_env_); |
| 808 break; | 808 break; |
| 809 } | 809 } |
| 810 if (c->is_if()) { | 810 if (c->is_if()) { |
| 811 if (c->false_env != nullptr) { | 811 if (c->false_env != nullptr) { |
| 812 // End the true branch of a one-armed if. | 812 // End the true branch of a one-armed if. |
| 813 Goto(c->false_env, c->end_env); | 813 Goto(c->false_env, c->end_env); |
| 814 if (ssa_env_->go() && | 814 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"); | 815 error("end of if expected empty stack"); |
| 817 stack_.resize(c->stack_depth); | 816 stack_.resize(c->stack_depth); |
| 818 } | 817 } |
| 819 if (c->merge.arity > 0) { | 818 if (c->merge.arity > 0) { |
| 820 error("non-void one-armed if"); | 819 error("non-void one-armed if"); |
| 821 } | 820 } |
| 822 name = "if:merge"; | 821 name = "if:merge"; |
| 823 } else { | 822 } else { |
| 824 // End the false branch of a two-armed if. | 823 // End the false branch of a two-armed if. |
| 825 name = "if_else:merge"; | 824 name = "if_else:merge"; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 839 // Push the end values onto the stack. | 838 // Push the end values onto the stack. |
| 840 stack_.resize(c->stack_depth); | 839 stack_.resize(c->stack_depth); |
| 841 if (c->merge.arity == 1) { | 840 if (c->merge.arity == 1) { |
| 842 stack_.push_back(c->merge.vals.first); | 841 stack_.push_back(c->merge.vals.first); |
| 843 } else { | 842 } else { |
| 844 for (unsigned i = 0; i < c->merge.arity; i++) { | 843 for (unsigned i = 0; i < c->merge.arity; i++) { |
| 845 stack_.push_back(c->merge.vals.array[i]); | 844 stack_.push_back(c->merge.vals.array[i]); |
| 846 } | 845 } |
| 847 } | 846 } |
| 848 | 847 |
| 849 PopControl(); | 848 if (control_.size() == 1) { |
| 850 | |
| 851 if (control_.empty()) { | |
| 852 // If the last (implicit) control was popped, check we are at end. | 849 // If the last (implicit) control was popped, check we are at end. |
|
rossberg
2017/01/18 16:21:42
Nit: s/was/is/
titzer
2017/01/18 17:22:17
Done.
| |
| 853 if (pc_ + 1 != end_) { | 850 if (pc_ + 1 != end_) { |
| 854 error(pc_, pc_ + 1, "trailing code after function end"); | 851 error(pc_, pc_ + 1, "trailing code after function end"); |
| 852 break; | |
| 855 } | 853 } |
| 856 last_end_found_ = true; | 854 last_end_found_ = true; |
| 857 if (ssa_env_->go()) { | 855 if (ssa_env_->go()) { |
| 858 // The result of the block is the return value. | 856 // The result of the block is the return value. |
| 859 TRACE(" @%-8d #xx:%-20s|", startrel(pc_), "ImplicitReturn"); | 857 TRACE(" @%-8d #xx:%-20s|", startrel(pc_), "ImplicitReturn"); |
| 860 DoReturn(); | 858 DoReturn(); |
| 861 TRACE("\n"); | 859 TRACE("\n"); |
| 862 } | 860 } |
| 863 return; | |
| 864 } | 861 } |
| 862 PopControl(); | |
| 865 break; | 863 break; |
| 866 } | 864 } |
| 867 case kExprSelect: { | 865 case kExprSelect: { |
| 868 Value cond = Pop(2, kWasmI32); | 866 Value cond = Pop(2, kWasmI32); |
| 869 Value fval = Pop(); | 867 Value fval = Pop(); |
| 870 Value tval = Pop(); | 868 Value tval = Pop(); |
| 871 if (tval.type == kWasmStmt || tval.type != fval.type) { | 869 if (tval.type == kWasmStmt || tval.type != fval.type) { |
| 872 if (tval.type != kWasmEnd && fval.type != kWasmEnd) { | 870 if (tval.type != kWasmEnd && fval.type != kWasmEnd) { |
| 873 error("type mismatch in select"); | 871 error("type mismatch in select"); |
| 874 break; | 872 break; |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1234 break; | 1232 break; |
| 1235 } | 1233 } |
| 1236 default: | 1234 default: |
| 1237 break; | 1235 break; |
| 1238 } | 1236 } |
| 1239 } | 1237 } |
| 1240 PrintF("\n"); | 1238 PrintF("\n"); |
| 1241 } | 1239 } |
| 1242 #endif | 1240 #endif |
| 1243 pc_ += len; | 1241 pc_ += len; |
| 1244 if (pc_ >= end_) { | 1242 if (pc_ >= end_) { |
|
Clemens Hammacher
2017/01/18 15:46:26
This condition could go away then, just put this a
titzer
2017/01/18 17:22:17
Done.
| |
| 1245 // End of code reached or exceeded. | 1243 // End of code reached or exceeded. |
| 1246 if (pc_ > end_ && ok()) error("Beyond end of code"); | 1244 if (pc_ > end_ && ok()) error("Beyond end of code"); |
| 1247 return; | 1245 return; |
| 1248 } | 1246 } |
| 1249 } // end decode loop | 1247 } // end decode loop |
| 1250 } | 1248 } |
| 1251 | 1249 |
| 1252 void EndControl() { ssa_env_->Kill(SsaEnv::kControlEnd); } | 1250 void EndControl() { ssa_env_->Kill(SsaEnv::kControlEnd); } |
| 1253 | 1251 |
| 1254 void SetBlockType(Control* c, BlockTypeOperand& operand) { | 1252 void SetBlockType(Control* c, BlockTypeOperand& operand) { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1279 } | 1277 } |
| 1280 return nullptr; | 1278 return nullptr; |
| 1281 } | 1279 } |
| 1282 } | 1280 } |
| 1283 | 1281 |
| 1284 ValueType GetReturnType(FunctionSig* sig) { | 1282 ValueType GetReturnType(FunctionSig* sig) { |
| 1285 return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn(); | 1283 return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn(); |
| 1286 } | 1284 } |
| 1287 | 1285 |
| 1288 void PushBlock(SsaEnv* end_env) { | 1286 void PushBlock(SsaEnv* end_env) { |
| 1289 const int stack_depth = static_cast<int>(stack_.size()); | |
| 1290 control_.emplace_back( | 1287 control_.emplace_back( |
| 1291 Control::Block(pc_, stack_depth, end_env, current_catch_)); | 1288 Control::Block(pc_, stack_.size(), end_env, current_catch_)); |
| 1292 } | 1289 } |
| 1293 | 1290 |
| 1294 void PushLoop(SsaEnv* end_env) { | 1291 void PushLoop(SsaEnv* end_env) { |
| 1295 const int stack_depth = static_cast<int>(stack_.size()); | |
| 1296 control_.emplace_back( | 1292 control_.emplace_back( |
| 1297 Control::Loop(pc_, stack_depth, end_env, current_catch_)); | 1293 Control::Loop(pc_, stack_.size(), end_env, current_catch_)); |
| 1298 } | 1294 } |
| 1299 | 1295 |
| 1300 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { | 1296 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { |
| 1301 const int stack_depth = static_cast<int>(stack_.size()); | |
| 1302 control_.emplace_back( | 1297 control_.emplace_back( |
| 1303 Control::If(pc_, stack_depth, end_env, false_env, current_catch_)); | 1298 Control::If(pc_, stack_.size(), end_env, false_env, current_catch_)); |
| 1304 } | 1299 } |
| 1305 | 1300 |
| 1306 void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { | 1301 void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { |
| 1307 const int stack_depth = static_cast<int>(stack_.size()); | 1302 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_)); | 1303 catch_env, current_catch_)); |
| 1310 current_catch_ = static_cast<int32_t>(control_.size() - 1); | 1304 current_catch_ = static_cast<int32_t>(control_.size() - 1); |
| 1311 } | 1305 } |
| 1312 | 1306 |
| 1313 void PopControl() { control_.pop_back(); } | 1307 void PopControl() { control_.pop_back(); } |
| 1314 | 1308 |
| 1315 int DecodeLoadMem(ValueType type, MachineType mem_type) { | 1309 int DecodeLoadMem(ValueType type, MachineType mem_type) { |
| 1316 if (!CheckHasMemory()) return 0; | 1310 if (!CheckHasMemory()) return 0; |
| 1317 MemoryAccessOperand operand(this, pc_, | 1311 MemoryAccessOperand operand(this, pc_, |
| 1318 ElementSizeLog2Of(mem_type.representation())); | 1312 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); | 1418 Push(sig->GetReturn(i), rets ? rets[i] : nullptr); |
| 1425 } | 1419 } |
| 1426 } | 1420 } |
| 1427 | 1421 |
| 1428 const char* SafeOpcodeNameAt(const byte* pc) { | 1422 const char* SafeOpcodeNameAt(const byte* pc) { |
| 1429 if (pc >= end_) return "<end>"; | 1423 if (pc >= end_) return "<end>"; |
| 1430 return WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc)); | 1424 return WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc)); |
| 1431 } | 1425 } |
| 1432 | 1426 |
| 1433 Value Pop(int index, ValueType expected) { | 1427 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(); | 1428 Value val = Pop(); |
| 1439 if (val.type != expected) { | 1429 if (val.type != expected) { |
| 1440 if (val.type != kWasmEnd) { | 1430 if (val.type != kWasmEnd) { |
| 1441 error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s", | 1431 error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s", |
| 1442 SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected), | 1432 SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected), |
| 1443 SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type)); | 1433 SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type)); |
| 1444 } | 1434 } |
| 1445 } | 1435 } |
| 1446 return val; | 1436 return val; |
| 1447 } | 1437 } |
| 1448 | 1438 |
| 1449 Value Pop() { | 1439 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; | 1440 size_t limit = control_.empty() ? 0 : control_.back().stack_depth; |
| 1455 if (stack_.size() <= limit) { | 1441 if (stack_.size() <= limit) { |
| 1456 Value val = {pc_, nullptr, kWasmStmt}; | 1442 Value val = {pc_, nullptr, kWasmEnd}; |
| 1457 error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_)); | 1443 if (ssa_env_->go()) { |
| 1444 // Popping past the current control start in reachable code. | |
| 1445 error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_)); | |
| 1446 } | |
| 1458 return val; | 1447 return val; |
| 1459 } | 1448 } |
| 1460 Value val = stack_.back(); | 1449 Value val = stack_.back(); |
| 1461 stack_.pop_back(); | 1450 stack_.pop_back(); |
| 1462 return val; | 1451 return val; |
| 1463 } | 1452 } |
| 1464 | 1453 |
| 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) { | 1454 int baserel(const byte* ptr) { |
| 1482 return base_ ? static_cast<int>(ptr - base_) : 0; | 1455 return base_ ? static_cast<int>(ptr - base_) : 0; |
| 1483 } | 1456 } |
| 1484 | 1457 |
| 1485 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } | 1458 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } |
| 1486 | 1459 |
| 1487 void BreakTo(unsigned depth) { | 1460 void BreakTo(unsigned depth) { |
| 1488 if (!ssa_env_->go()) return; | 1461 if (!ssa_env_->go()) return; |
| 1489 Control* c = &control_[control_.size() - depth - 1]; | 1462 Control* c = &control_[control_.size() - depth - 1]; |
| 1490 if (c->is_loop()) { | 1463 if (c->is_loop()) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1501 return; | 1474 return; |
| 1502 } | 1475 } |
| 1503 MergeValuesInto(c); | 1476 MergeValuesInto(c); |
| 1504 } | 1477 } |
| 1505 } | 1478 } |
| 1506 | 1479 |
| 1507 void FallThruTo(Control* c) { | 1480 void FallThruTo(Control* c) { |
| 1508 if (!ssa_env_->go()) return; | 1481 if (!ssa_env_->go()) return; |
| 1509 // Merge the value(s) into the end of the block. | 1482 // Merge the value(s) into the end of the block. |
| 1510 int arity = static_cast<int>(c->merge.arity); | 1483 int arity = static_cast<int>(c->merge.arity); |
| 1511 if (c->stack_depth + arity != static_cast<int>(stack_.size())) { | 1484 if (c->stack_depth + arity != stack_.size()) { |
| 1512 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", | 1485 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", |
| 1513 arity, startrel(c->pc)); | 1486 arity, startrel(c->pc)); |
| 1514 return; | 1487 return; |
| 1515 } | 1488 } |
| 1516 MergeValuesInto(c); | 1489 MergeValuesInto(c); |
| 1517 } | 1490 } |
| 1518 | 1491 |
| 1519 inline Value& GetMergeValueFromStack(Control* c, int i) { | 1492 inline Value& GetMergeValueFromStack(Control* c, int i) { |
| 1520 return stack_[stack_.size() - c->merge.arity + i]; | 1493 return stack_[stack_.size() - c->merge.arity + i]; |
| 1521 } | 1494 } |
| 1522 | 1495 |
| 1523 void TypeCheckLoopFallThru(Control* c) { | 1496 void TypeCheckLoopFallThru(Control* c) { |
| 1524 if (!ssa_env_->go()) return; | 1497 if (!ssa_env_->go()) return; |
| 1525 // Fallthru must match arity exactly. | 1498 // Fallthru must match arity exactly. |
| 1526 int arity = static_cast<int>(c->merge.arity); | 1499 int arity = static_cast<int>(c->merge.arity); |
| 1527 if (c->stack_depth + arity != static_cast<int>(stack_.size())) { | 1500 if (c->stack_depth + arity != stack_.size()) { |
| 1528 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", | 1501 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d", |
| 1529 arity, startrel(c->pc)); | 1502 arity, startrel(c->pc)); |
| 1530 return; | 1503 return; |
| 1531 } | 1504 } |
| 1532 // Typecheck the values left on the stack. | 1505 // Typecheck the values left on the stack. |
| 1533 for (unsigned i = 0; i < c->merge.arity; i++) { | 1506 for (unsigned i = 0; i < c->merge.arity; i++) { |
| 1534 Value& val = GetMergeValueFromStack(c, i); | 1507 Value& val = GetMergeValueFromStack(c, i); |
| 1535 Value& old = | 1508 Value& old = |
| 1536 c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i]; | 1509 c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i]; |
| 1537 if (val.type != old.type) { | 1510 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, | 2010 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 2038 const byte* start, const byte* end) { | 2011 const byte* start, const byte* end) { |
| 2039 Decoder decoder(start, end); | 2012 Decoder decoder(start, end); |
| 2040 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, | 2013 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, |
| 2041 static_cast<int>(num_locals), zone); | 2014 static_cast<int>(num_locals), zone); |
| 2042 } | 2015 } |
| 2043 | 2016 |
| 2044 } // namespace wasm | 2017 } // namespace wasm |
| 2045 } // namespace internal | 2018 } // namespace internal |
| 2046 } // namespace v8 | 2019 } // namespace v8 |
| OLD | NEW |