| 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 |