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 |