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/flags.h" | 8 #include "src/flags.h" |
9 #include "src/handles.h" | 9 #include "src/handles.h" |
10 #include "src/zone-containers.h" | 10 #include "src/zone-containers.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 }; | 41 }; |
42 | 42 |
43 | 43 |
44 // A production represents an incomplete decoded tree in the LR decoder. | 44 // A production represents an incomplete decoded tree in the LR decoder. |
45 struct Production { | 45 struct Production { |
46 Tree* tree; // the root of the syntax tree. | 46 Tree* tree; // the root of the syntax tree. |
47 int index; // the current index into the children of the tree. | 47 int index; // the current index into the children of the tree. |
48 | 48 |
49 WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc()); } | 49 WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc()); } |
50 const byte* pc() const { return tree->pc; } | 50 const byte* pc() const { return tree->pc; } |
51 bool done() const { return index >= tree->count; } | 51 bool done() const { return index >= static_cast<int>(tree->count); } |
52 Tree* last() const { return index > 0 ? tree->children[index - 1] : nullptr; } | 52 Tree* last() const { return index > 0 ? tree->children[index - 1] : nullptr; } |
53 }; | 53 }; |
54 | 54 |
55 | 55 |
56 // An SsaEnv environment carries the current local variable renaming | 56 // An SsaEnv environment carries the current local variable renaming |
57 // as well as the current effect and control dependency in the TF graph. | 57 // as well as the current effect and control dependency in the TF graph. |
58 // It maintains a control state that tracks whether the environment | 58 // It maintains a control state that tracks whether the environment |
59 // is reachable, has reached a control end, or has been merged. | 59 // is reachable, has reached a control end, or has been merged. |
60 struct SsaEnv { | 60 struct SsaEnv { |
61 enum State { kControlEnd, kUnreachable, kReached, kMerged }; | 61 enum State { kControlEnd, kUnreachable, kReached, kMerged }; |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 return length; | 604 return length; |
605 } | 605 } |
606 | 606 |
607 void AddImplicitReturnAtEnd() { | 607 void AddImplicitReturnAtEnd() { |
608 int retcount = static_cast<int>(function_env_->sig->return_count()); | 608 int retcount = static_cast<int>(function_env_->sig->return_count()); |
609 if (retcount == 0) { | 609 if (retcount == 0) { |
610 BUILD0(ReturnVoid); | 610 BUILD0(ReturnVoid); |
611 return; | 611 return; |
612 } | 612 } |
613 | 613 |
614 if (trees_.size() < retcount) { | 614 if (static_cast<int>(trees_.size()) < retcount) { |
615 error(limit_, nullptr, | 615 error(limit_, nullptr, |
616 "ImplicitReturn expects %d arguments, only %d remain", retcount, | 616 "ImplicitReturn expects %d arguments, only %d remain", retcount, |
617 static_cast<int>(trees_.size())); | 617 static_cast<int>(trees_.size())); |
618 return; | 618 return; |
619 } | 619 } |
620 | 620 |
621 TRACE("wasm-decode implicit return of %d args\n", retcount); | 621 TRACE("wasm-decode implicit return of %d args\n", retcount); |
622 | 622 |
623 TFNode** buffer = BUILD(Buffer, retcount); | 623 TFNode** buffer = BUILD(Buffer, retcount); |
624 for (int index = 0; index < retcount; index++) { | 624 for (int index = 0; index < retcount; index++) { |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 if (!sig) break; | 991 if (!sig) break; |
992 if (p->index > 0) { | 992 if (p->index > 0) { |
993 TypeCheckLast(p, sig->GetParam(p->index - 1)); | 993 TypeCheckLast(p, sig->GetParam(p->index - 1)); |
994 } | 994 } |
995 if (p->done() && build()) { | 995 if (p->done() && build()) { |
996 uint32_t count = p->tree->count + 1; | 996 uint32_t count = p->tree->count + 1; |
997 TFNode** buffer = builder_->Buffer(count); | 997 TFNode** buffer = builder_->Buffer(count); |
998 FunctionSig* sig = FunctionSigOperand(p->pc(), &index, &len); | 998 FunctionSig* sig = FunctionSigOperand(p->pc(), &index, &len); |
999 USE(sig); | 999 USE(sig); |
1000 buffer[0] = nullptr; // reserved for code object. | 1000 buffer[0] = nullptr; // reserved for code object. |
1001 for (int i = 1; i < count; i++) { | 1001 for (uint32_t i = 1; i < count; i++) { |
1002 buffer[i] = p->tree->children[i - 1]->node; | 1002 buffer[i] = p->tree->children[i - 1]->node; |
1003 } | 1003 } |
1004 p->tree->node = builder_->CallDirect(index, buffer); | 1004 p->tree->node = builder_->CallDirect(index, buffer); |
1005 } | 1005 } |
1006 break; | 1006 break; |
1007 } | 1007 } |
1008 case kExprCallIndirect: { | 1008 case kExprCallIndirect: { |
1009 int len; | 1009 int len; |
1010 uint32_t index; | 1010 uint32_t index; |
1011 FunctionSig* sig = SigOperand(p->pc(), &index, &len); | 1011 FunctionSig* sig = SigOperand(p->pc(), &index, &len); |
1012 if (p->index == 1) { | 1012 if (p->index == 1) { |
1013 TypeCheckLast(p, kAstI32); | 1013 TypeCheckLast(p, kAstI32); |
1014 } else { | 1014 } else { |
1015 TypeCheckLast(p, sig->GetParam(p->index - 2)); | 1015 TypeCheckLast(p, sig->GetParam(p->index - 2)); |
1016 } | 1016 } |
1017 if (p->done() && build()) { | 1017 if (p->done() && build()) { |
1018 uint32_t count = p->tree->count; | 1018 uint32_t count = p->tree->count; |
1019 TFNode** buffer = builder_->Buffer(count); | 1019 TFNode** buffer = builder_->Buffer(count); |
1020 for (int i = 0; i < count; i++) { | 1020 for (uint32_t i = 0; i < count; i++) { |
1021 buffer[i] = p->tree->children[i]->node; | 1021 buffer[i] = p->tree->children[i]->node; |
1022 } | 1022 } |
1023 p->tree->node = builder_->CallIndirect(index, buffer); | 1023 p->tree->node = builder_->CallIndirect(index, buffer); |
1024 } | 1024 } |
1025 break; | 1025 break; |
1026 } | 1026 } |
1027 default: | 1027 default: |
1028 break; | 1028 break; |
1029 } | 1029 } |
1030 } | 1030 } |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 if (!builder_) break; | 1162 if (!builder_) break; |
1163 TFNode* merge = to->control; | 1163 TFNode* merge = to->control; |
1164 // Extend the existing merge. | 1164 // Extend the existing merge. |
1165 builder_->AppendToMerge(merge, from->control); | 1165 builder_->AppendToMerge(merge, from->control); |
1166 // Merge effects. | 1166 // Merge effects. |
1167 if (builder_->IsPhiWithMerge(to->effect, merge)) { | 1167 if (builder_->IsPhiWithMerge(to->effect, merge)) { |
1168 builder_->AppendToPhi(merge, to->effect, from->effect); | 1168 builder_->AppendToPhi(merge, to->effect, from->effect); |
1169 } else if (to->effect != from->effect) { | 1169 } else if (to->effect != from->effect) { |
1170 uint32_t count = builder_->InputCount(merge); | 1170 uint32_t count = builder_->InputCount(merge); |
1171 TFNode** effects = builder_->Buffer(count); | 1171 TFNode** effects = builder_->Buffer(count); |
1172 for (int j = 0; j < count - 1; j++) effects[j] = to->effect; | 1172 for (uint32_t j = 0; j < count - 1; j++) { |
| 1173 effects[j] = to->effect; |
| 1174 } |
1173 effects[count - 1] = from->effect; | 1175 effects[count - 1] = from->effect; |
1174 to->effect = builder_->EffectPhi(count, effects, merge); | 1176 to->effect = builder_->EffectPhi(count, effects, merge); |
1175 } | 1177 } |
1176 // Merge locals. | 1178 // Merge locals. |
1177 for (int i = EnvironmentCount() - 1; i >= 0; i--) { | 1179 for (int i = EnvironmentCount() - 1; i >= 0; i--) { |
1178 TFNode* tnode = to->locals[i]; | 1180 TFNode* tnode = to->locals[i]; |
1179 TFNode* fnode = from->locals[i]; | 1181 TFNode* fnode = from->locals[i]; |
1180 if (builder_->IsPhiWithMerge(tnode, merge)) { | 1182 if (builder_->IsPhiWithMerge(tnode, merge)) { |
1181 builder_->AppendToPhi(merge, tnode, fnode); | 1183 builder_->AppendToPhi(merge, tnode, fnode); |
1182 } else if (tnode != fnode) { | 1184 } else if (tnode != fnode) { |
1183 uint32_t count = builder_->InputCount(merge); | 1185 uint32_t count = builder_->InputCount(merge); |
1184 TFNode** vals = builder_->Buffer(count); | 1186 TFNode** vals = builder_->Buffer(count); |
1185 for (int j = 0; j < count - 1; j++) vals[j] = tnode; | 1187 for (uint32_t j = 0; j < count - 1; j++) { |
| 1188 vals[j] = tnode; |
| 1189 } |
1186 vals[count - 1] = fnode; | 1190 vals[count - 1] = fnode; |
1187 to->locals[i] = builder_->Phi(function_env_->GetLocalType(i), count, | 1191 to->locals[i] = builder_->Phi(function_env_->GetLocalType(i), count, |
1188 vals, merge); | 1192 vals, merge); |
1189 } | 1193 } |
1190 } | 1194 } |
1191 break; | 1195 break; |
1192 } | 1196 } |
1193 default: | 1197 default: |
1194 UNREACHABLE(); | 1198 UNREACHABLE(); |
1195 } | 1199 } |
1196 return from->Kill(); | 1200 return from->Kill(); |
1197 } | 1201 } |
1198 | 1202 |
1199 TFNode* CreateOrMergeIntoPhi(LocalType type, TFNode* merge, TFNode* tnode, | 1203 TFNode* CreateOrMergeIntoPhi(LocalType type, TFNode* merge, TFNode* tnode, |
1200 TFNode* fnode) { | 1204 TFNode* fnode) { |
1201 if (builder_->IsPhiWithMerge(tnode, merge)) { | 1205 if (builder_->IsPhiWithMerge(tnode, merge)) { |
1202 builder_->AppendToPhi(merge, tnode, fnode); | 1206 builder_->AppendToPhi(merge, tnode, fnode); |
1203 } else if (tnode != fnode) { | 1207 } else if (tnode != fnode) { |
1204 uint32_t count = builder_->InputCount(merge); | 1208 uint32_t count = builder_->InputCount(merge); |
1205 TFNode** vals = builder_->Buffer(count); | 1209 TFNode** vals = builder_->Buffer(count); |
1206 for (int j = 0; j < count - 1; j++) vals[j] = tnode; | 1210 for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode; |
1207 vals[count - 1] = fnode; | 1211 vals[count - 1] = fnode; |
1208 return builder_->Phi(type, count, vals, merge); | 1212 return builder_->Phi(type, count, vals, merge); |
1209 } | 1213 } |
1210 return tnode; | 1214 return tnode; |
1211 } | 1215 } |
1212 | 1216 |
1213 void BuildInfiniteLoop() { | 1217 void BuildInfiniteLoop() { |
1214 if (ssa_env_->go()) { | 1218 if (ssa_env_->go()) { |
1215 PrepareForLoop(ssa_env_); | 1219 PrepareForLoop(ssa_env_); |
1216 SsaEnv* cont_env = ssa_env_; | 1220 SsaEnv* cont_env = ssa_env_; |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1423 } | 1427 } |
1424 | 1428 |
1425 | 1429 |
1426 std::ostream& operator<<(std::ostream& os, const Tree& tree) { | 1430 std::ostream& operator<<(std::ostream& os, const Tree& tree) { |
1427 if (tree.pc == nullptr) { | 1431 if (tree.pc == nullptr) { |
1428 os << "null"; | 1432 os << "null"; |
1429 return os; | 1433 return os; |
1430 } | 1434 } |
1431 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode())); | 1435 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode())); |
1432 if (tree.count > 0) os << "("; | 1436 if (tree.count > 0) os << "("; |
1433 for (int i = 0; i < tree.count; i++) { | 1437 for (uint32_t i = 0; i < tree.count; i++) { |
1434 if (i > 0) os << ", "; | 1438 if (i > 0) os << ", "; |
1435 os << *tree.children[i]; | 1439 os << *tree.children[i]; |
1436 } | 1440 } |
1437 if (tree.count > 0) os << ")"; | 1441 if (tree.count > 0) os << ")"; |
1438 return os; | 1442 return os; |
1439 } | 1443 } |
1440 | 1444 |
1441 | 1445 |
1442 ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte* pc, | 1446 ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte* pc, |
1443 const byte* limit, | 1447 const byte* limit, |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1564 #define DECLARE_OPCODE_CASE(name, opcode, sig) \ | 1568 #define DECLARE_OPCODE_CASE(name, opcode, sig) \ |
1565 case kExpr##name: \ | 1569 case kExpr##name: \ |
1566 return kArity_##sig; | 1570 return kArity_##sig; |
1567 | 1571 |
1568 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) | 1572 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) |
1569 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) | 1573 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) |
1570 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE) | 1574 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE) |
1571 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE) | 1575 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE) |
1572 #undef DECLARE_OPCODE_CASE | 1576 #undef DECLARE_OPCODE_CASE |
1573 } | 1577 } |
| 1578 UNREACHABLE(); |
| 1579 return 0; |
1574 } | 1580 } |
1575 } // namespace wasm | 1581 } // namespace wasm |
1576 } // namespace internal | 1582 } // namespace internal |
1577 } // namespace v8 | 1583 } // namespace v8 |
OLD | NEW |