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