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/base/platform/elapsed-timer.h" | 5 #include "src/base/platform/elapsed-timer.h" |
6 #include "src/signature.h" | 6 #include "src/signature.h" |
7 | 7 |
8 #include "src/bit-vector.h" | 8 #include "src/bit-vector.h" |
9 #include "src/flags.h" | 9 #include "src/flags.h" |
10 #include "src/handles.h" | 10 #include "src/handles.h" |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 inline bool Validate(const byte* pc, BreakDepthOperand& operand, | 188 inline bool Validate(const byte* pc, BreakDepthOperand& operand, |
189 ZoneVector<Block>& blocks) { | 189 ZoneVector<Block>& blocks) { |
190 if (operand.depth < blocks.size()) { | 190 if (operand.depth < blocks.size()) { |
191 operand.target = &blocks[blocks.size() - operand.depth - 1]; | 191 operand.target = &blocks[blocks.size() - operand.depth - 1]; |
192 return true; | 192 return true; |
193 } | 193 } |
194 error(pc, pc + 1, "invalid break depth"); | 194 error(pc, pc + 1, "invalid break depth"); |
195 return false; | 195 return false; |
196 } | 196 } |
197 | 197 |
198 bool Validate(const byte* pc, TableSwitchOperand& operand, | 198 bool Validate(const byte* pc, BranchTableOperand& operand, |
199 size_t block_depth) { | 199 size_t block_depth) { |
200 if (operand.table_count == 0) { | |
201 error(pc, "tableswitch with 0 entries"); | |
202 return false; | |
203 } | |
204 // Verify table. | 200 // Verify table. |
205 for (uint32_t i = 0; i < operand.table_count; i++) { | 201 for (uint32_t i = 0; i < operand.table_count + 1; i++) { |
206 uint16_t target = operand.read_entry(this, i); | 202 uint16_t target = operand.read_entry(this, i); |
207 if (target >= 0x8000) { | 203 if (target >= block_depth) { |
208 size_t depth = target - 0x8000; | 204 error(operand.table + i * 2, "improper branch in br_table"); |
209 if (depth > block_depth) { | 205 return false; |
210 error(operand.table + i * 2, "improper branch in tableswitch"); | |
211 return false; | |
212 } | |
213 } else { | |
214 if (target >= operand.case_count) { | |
215 error(operand.table + i * 2, "invalid case target in tableswitch"); | |
216 return false; | |
217 } | |
218 } | 206 } |
219 } | 207 } |
220 return true; | 208 return true; |
221 } | 209 } |
222 | 210 |
223 int OpcodeArity(const byte* pc) { | 211 int OpcodeArity(const byte* pc) { |
224 #define DECLARE_ARITY(name, ...) \ | 212 #define DECLARE_ARITY(name, ...) \ |
225 static const LocalType kTypes_##name[] = {__VA_ARGS__}; \ | 213 static const LocalType kTypes_##name[] = {__VA_ARGS__}; \ |
226 static const int kArity_##name = \ | 214 static const int kArity_##name = \ |
227 static_cast<int>(arraysize(kTypes_##name) - 1); | 215 static_cast<int>(arraysize(kTypes_##name) - 1); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 } | 261 } |
274 case kExprCallImport: { | 262 case kExprCallImport: { |
275 ImportIndexOperand operand(this, pc); | 263 ImportIndexOperand operand(this, pc); |
276 return static_cast<int>( | 264 return static_cast<int>( |
277 function_env_->module->GetImportSignature(operand.index) | 265 function_env_->module->GetImportSignature(operand.index) |
278 ->parameter_count()); | 266 ->parameter_count()); |
279 } | 267 } |
280 case kExprReturn: { | 268 case kExprReturn: { |
281 return static_cast<int>(function_env_->sig->return_count()); | 269 return static_cast<int>(function_env_->sig->return_count()); |
282 } | 270 } |
283 case kExprTableSwitch: { | 271 case kExprBrTable: { |
284 TableSwitchOperand operand(this, pc); | 272 return 1; |
285 return 1 + operand.case_count; | |
286 } | 273 } |
287 | 274 |
288 #define DECLARE_OPCODE_CASE(name, opcode, sig) \ | 275 #define DECLARE_OPCODE_CASE(name, opcode, sig) \ |
289 case kExpr##name: \ | 276 case kExpr##name: \ |
290 return kArity_##sig; | 277 return kArity_##sig; |
291 | 278 |
292 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) | 279 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) |
293 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) | 280 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) |
294 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE) | 281 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE) |
295 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE) | 282 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 case kExprCallImport: { | 324 case kExprCallImport: { |
338 ImportIndexOperand operand(this, pc); | 325 ImportIndexOperand operand(this, pc); |
339 return 1 + operand.length; | 326 return 1 + operand.length; |
340 } | 327 } |
341 | 328 |
342 case kExprSetLocal: | 329 case kExprSetLocal: |
343 case kExprGetLocal: { | 330 case kExprGetLocal: { |
344 LocalIndexOperand operand(this, pc); | 331 LocalIndexOperand operand(this, pc); |
345 return 1 + operand.length; | 332 return 1 + operand.length; |
346 } | 333 } |
347 case kExprTableSwitch: { | 334 case kExprBrTable: { |
348 TableSwitchOperand operand(this, pc); | 335 BranchTableOperand operand(this, pc); |
349 return 1 + operand.length; | 336 return 1 + operand.length; |
350 } | 337 } |
351 case kExprI8Const: | 338 case kExprI8Const: |
352 return 2; | 339 return 2; |
353 case kExprI32Const: | 340 case kExprI32Const: |
354 case kExprF32Const: | 341 case kExprF32Const: |
355 return 5; | 342 return 5; |
356 case kExprI64Const: | 343 case kExprI64Const: |
357 case kExprF64Const: | 344 case kExprF64Const: |
358 return 9; | 345 return 9; |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 break; | 636 break; |
650 } | 637 } |
651 case kExprBrIf: { | 638 case kExprBrIf: { |
652 BreakDepthOperand operand(this, pc_); | 639 BreakDepthOperand operand(this, pc_); |
653 if (Validate(pc_, operand, blocks_)) { | 640 if (Validate(pc_, operand, blocks_)) { |
654 Shift(kAstStmt, 2); | 641 Shift(kAstStmt, 2); |
655 } | 642 } |
656 len = 1 + operand.length; | 643 len = 1 + operand.length; |
657 break; | 644 break; |
658 } | 645 } |
659 case kExprTableSwitch: { | 646 case kExprBrTable: { |
660 TableSwitchOperand operand(this, pc_); | 647 BranchTableOperand operand(this, pc_); |
661 if (Validate(pc_, operand, blocks_.size())) { | 648 if (Validate(pc_, operand, blocks_.size())) { |
662 Shift(kAstEnd, 1 + operand.case_count); | 649 Shift(kAstEnd, 1); |
663 } | 650 } |
664 len = 1 + operand.length; | 651 len = 1 + operand.length; |
665 break; | 652 break; |
666 } | 653 } |
667 case kExprReturn: { | 654 case kExprReturn: { |
668 int count = static_cast<int>(function_env_->sig->return_count()); | 655 int count = static_cast<int>(function_env_->sig->return_count()); |
669 if (count == 0) { | 656 if (count == 0) { |
670 BUILD(Return, 0, builder_->Buffer(0)); | 657 BUILD(Return, 0, builder_->Buffer(0)); |
671 ssa_env_->Kill(); | 658 ssa_env_->Kill(); |
672 Leaf(kAstEnd); | 659 Leaf(kAstEnd); |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1037 SsaEnv* fenv = ssa_env_; | 1024 SsaEnv* fenv = ssa_env_; |
1038 SsaEnv* tenv = Split(fenv); | 1025 SsaEnv* tenv = Split(fenv); |
1039 BUILD(Branch, p->tree->children[1]->node, &tenv->control, | 1026 BUILD(Branch, p->tree->children[1]->node, &tenv->control, |
1040 &fenv->control); | 1027 &fenv->control); |
1041 ssa_env_ = tenv; | 1028 ssa_env_ = tenv; |
1042 ReduceBreakToExprBlock(p, operand.target, p->tree->children[0]); | 1029 ReduceBreakToExprBlock(p, operand.target, p->tree->children[0]); |
1043 ssa_env_ = fenv; | 1030 ssa_env_ = fenv; |
1044 } | 1031 } |
1045 break; | 1032 break; |
1046 } | 1033 } |
1047 case kExprTableSwitch: { | 1034 case kExprBrTable: { |
1048 if (p->index == 1) { | 1035 if (p->index == 1) { |
1049 // Switch key finished. | 1036 // Switch key finished. |
1050 TypeCheckLast(p, kAstI32); | 1037 TypeCheckLast(p, kAstI32); |
1051 if (failed()) break; | 1038 if (failed()) break; |
1052 | 1039 |
1053 TableSwitchOperand operand(this, p->pc()); | 1040 BranchTableOperand operand(this, p->pc()); |
1054 DCHECK(Validate(p->pc(), operand, blocks_.size())); | 1041 DCHECK(Validate(p->pc(), operand, blocks_.size())); |
1055 | 1042 |
1056 // Build the switch only if it has more than just a default target. | 1043 // Build a switch only if it has more than just a default target. |
1057 bool build_switch = operand.table_count > 1; | 1044 bool build_switch = operand.table_count > 0; |
1058 TFNode* sw = nullptr; | 1045 TFNode* sw = nullptr; |
1059 if (build_switch) | 1046 if (build_switch) { |
1060 sw = BUILD(Switch, operand.table_count, p->last()->node); | 1047 sw = BUILD(Switch, operand.table_count + 1, p->last()->node); |
1061 | |
1062 // Allocate environments for each case. | |
1063 SsaEnv** case_envs = zone_->NewArray<SsaEnv*>(operand.case_count); | |
1064 for (uint32_t i = 0; i < operand.case_count; i++) { | |
1065 case_envs[i] = UnreachableEnv(); | |
1066 } | 1048 } |
1067 | 1049 |
1068 ifs_.push_back({nullptr, nullptr, case_envs}); | 1050 // Process the targets of the break table. |
1069 SsaEnv* break_env = ssa_env_; | 1051 SsaEnv* prev = ssa_env_; |
1070 PushBlock(break_env); | 1052 SsaEnv* copy = Steal(prev); |
1071 SsaEnv* copy = Steal(break_env); | 1053 for (uint32_t i = 0; i < operand.table_count + 1; i++) { |
1072 ssa_env_ = copy; | |
1073 | |
1074 // Build the environments for each case based on the table. | |
1075 for (uint32_t i = 0; i < operand.table_count; i++) { | |
1076 uint16_t target = operand.read_entry(this, i); | 1054 uint16_t target = operand.read_entry(this, i); |
1077 SsaEnv* env = copy; | 1055 SsaEnv* env = copy; |
1078 if (build_switch) { | 1056 if (build_switch) { |
1079 env = Split(env); | 1057 ssa_env_ = env = Split(env); |
1080 env->control = (i == operand.table_count - 1) | 1058 env->control = i == operand.table_count ? BUILD(IfDefault, sw) |
1081 ? BUILD(IfDefault, sw) | 1059 : BUILD(IfValue, i, sw); |
1082 : BUILD(IfValue, i, sw); | |
1083 } | 1060 } |
1084 if (target >= 0x8000) { | 1061 SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env; |
1085 // Targets an outer block. | 1062 Goto(env, tenv); |
1086 int depth = target - 0x8000; | |
1087 SsaEnv* tenv = blocks_[blocks_.size() - depth - 1].ssa_env; | |
1088 Goto(env, tenv); | |
1089 } else { | |
1090 // Targets a case. | |
1091 Goto(env, case_envs[target]); | |
1092 } | |
1093 } | 1063 } |
1094 } | 1064 ssa_env_ = prev; |
1095 | |
1096 if (p->done()) { | |
1097 // Last case. Fall through to the end. | |
1098 Block* block = &blocks_.back(); | |
1099 if (p->index > 1) ReduceBreakToExprBlock(p, block); | |
1100 SsaEnv* next = block->ssa_env; | |
1101 blocks_.pop_back(); | |
1102 ifs_.pop_back(); | |
1103 SetEnv("switch:end", next); | |
1104 } else { | |
1105 // Interior case. Maybe fall through to the next case. | |
1106 SsaEnv* next = ifs_.back().case_envs[p->index - 1]; | |
1107 if (p->index > 1 && ssa_env_->go()) Goto(ssa_env_, next); | |
1108 SetEnv("switch:case", next); | |
1109 } | 1065 } |
1110 break; | 1066 break; |
1111 } | 1067 } |
1112 case kExprReturn: { | 1068 case kExprReturn: { |
1113 TypeCheckLast(p, function_env_->sig->GetReturn(p->index - 1)); | 1069 TypeCheckLast(p, function_env_->sig->GetReturn(p->index - 1)); |
1114 if (p->done()) { | 1070 if (p->done()) { |
1115 if (build()) { | 1071 if (build()) { |
1116 int count = p->tree->count; | 1072 int count = p->tree->count; |
1117 TFNode** buffer = builder_->Buffer(count); | 1073 TFNode** buffer = builder_->Buffer(count); |
1118 for (int i = 0; i < count; i++) { | 1074 for (int i = 0; i < count; i++) { |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1706 | 1662 |
1707 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, FunctionEnv* env, | 1663 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, FunctionEnv* env, |
1708 const byte* start, const byte* end) { | 1664 const byte* start, const byte* end) { |
1709 LoopAssignmentAnalyzer analyzer(zone, env); | 1665 LoopAssignmentAnalyzer analyzer(zone, env); |
1710 return analyzer.Analyze(start, end); | 1666 return analyzer.Analyze(start, end); |
1711 } | 1667 } |
1712 | 1668 |
1713 } // namespace wasm | 1669 } // namespace wasm |
1714 } // namespace internal | 1670 } // namespace internal |
1715 } // namespace v8 | 1671 } // namespace v8 |
OLD | NEW |