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