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/compiler/wasm-compiler.h" | 5 #include "src/compiler/wasm-compiler.h" |
6 | 6 |
7 #include "src/isolate-inl.h" | 7 #include "src/isolate-inl.h" |
8 | 8 |
9 #include "src/base/platform/elapsed-timer.h" | 9 #include "src/base/platform/elapsed-timer.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 | 65 |
66 void MergeControlToEnd(JSGraph* jsgraph, Node* node) { | 66 void MergeControlToEnd(JSGraph* jsgraph, Node* node) { |
67 Graph* g = jsgraph->graph(); | 67 Graph* g = jsgraph->graph(); |
68 if (g->end()) { | 68 if (g->end()) { |
69 NodeProperties::MergeControlToEnd(g, jsgraph->common(), node); | 69 NodeProperties::MergeControlToEnd(g, jsgraph->common(), node); |
70 } else { | 70 } else { |
71 g->SetEnd(g->NewNode(jsgraph->common()->End(1), node)); | 71 g->SetEnd(g->NewNode(jsgraph->common()->End(1), node)); |
72 } | 72 } |
73 } | 73 } |
74 | 74 |
75 | |
76 enum TrapReason { | |
77 kTrapUnreachable, | |
78 kTrapMemOutOfBounds, | |
79 kTrapDivByZero, | |
80 kTrapDivUnrepresentable, | |
81 kTrapRemByZero, | |
82 kTrapFloatUnrepresentable, | |
83 kTrapFuncInvalid, | |
84 kTrapFuncSigMismatch, | |
85 kTrapCount | |
86 }; | |
87 | |
88 | |
89 static const char* kTrapMessages[] = { | |
90 "unreachable", "memory access out of bounds", | |
91 "divide by zero", "divide result unrepresentable", | |
92 "remainder by zero", "integer result unrepresentable", | |
93 "invalid function", "function signature mismatch"}; | |
94 } // namespace | 75 } // namespace |
95 | 76 |
96 | |
97 // A helper that handles building graph fragments for trapping. | 77 // A helper that handles building graph fragments for trapping. |
98 // To avoid generating a ton of redundant code that just calls the runtime | 78 // To avoid generating a ton of redundant code that just calls the runtime |
99 // to trap, we generate a per-trap-reason block of code that all trap sites | 79 // to trap, we generate a per-trap-reason block of code that all trap sites |
100 // in this function will branch to. | 80 // in this function will branch to. |
101 class WasmTrapHelper : public ZoneObject { | 81 class WasmTrapHelper : public ZoneObject { |
102 public: | 82 public: |
103 explicit WasmTrapHelper(WasmGraphBuilder* builder) | 83 explicit WasmTrapHelper(WasmGraphBuilder* builder) |
104 : builder_(builder), | 84 : builder_(builder), |
105 jsgraph_(builder->jsgraph()), | 85 jsgraph_(builder->jsgraph()), |
106 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) { | 86 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) { |
107 for (int i = 0; i < kTrapCount; i++) traps_[i] = nullptr; | 87 for (int i = 0; i < wasm::kTrapCount; i++) traps_[i] = nullptr; |
108 } | 88 } |
109 | 89 |
110 // Make the current control path trap to unreachable. | 90 // Make the current control path trap to unreachable. |
111 void Unreachable() { ConnectTrap(kTrapUnreachable); } | 91 void Unreachable() { ConnectTrap(wasm::kTrapUnreachable); } |
112 | 92 |
113 // Always trap with the given reason. | 93 // Always trap with the given reason. |
114 void TrapAlways(TrapReason reason) { ConnectTrap(reason); } | 94 void TrapAlways(wasm::TrapReason reason) { ConnectTrap(reason); } |
115 | 95 |
116 // Add a check that traps if {node} is equal to {val}. | 96 // Add a check that traps if {node} is equal to {val}. |
117 Node* TrapIfEq32(TrapReason reason, Node* node, int32_t val) { | 97 Node* TrapIfEq32(wasm::TrapReason reason, Node* node, int32_t val) { |
118 Int32Matcher m(node); | 98 Int32Matcher m(node); |
119 if (m.HasValue() && !m.Is(val)) return graph()->start(); | 99 if (m.HasValue() && !m.Is(val)) return graph()->start(); |
120 if (val == 0) { | 100 if (val == 0) { |
121 AddTrapIfFalse(reason, node); | 101 AddTrapIfFalse(reason, node); |
122 } else { | 102 } else { |
123 AddTrapIfTrue(reason, | 103 AddTrapIfTrue(reason, |
124 graph()->NewNode(jsgraph()->machine()->Word32Equal(), node, | 104 graph()->NewNode(jsgraph()->machine()->Word32Equal(), node, |
125 jsgraph()->Int32Constant(val))); | 105 jsgraph()->Int32Constant(val))); |
126 } | 106 } |
127 return builder_->Control(); | 107 return builder_->Control(); |
128 } | 108 } |
129 | 109 |
130 // Add a check that traps if {node} is zero. | 110 // Add a check that traps if {node} is zero. |
131 Node* ZeroCheck32(TrapReason reason, Node* node) { | 111 Node* ZeroCheck32(wasm::TrapReason reason, Node* node) { |
132 return TrapIfEq32(reason, node, 0); | 112 return TrapIfEq32(reason, node, 0); |
133 } | 113 } |
134 | 114 |
135 // Add a check that traps if {node} is equal to {val}. | 115 // Add a check that traps if {node} is equal to {val}. |
136 Node* TrapIfEq64(TrapReason reason, Node* node, int64_t val) { | 116 Node* TrapIfEq64(wasm::TrapReason reason, Node* node, int64_t val) { |
137 Int64Matcher m(node); | 117 Int64Matcher m(node); |
138 if (m.HasValue() && !m.Is(val)) return graph()->start(); | 118 if (m.HasValue() && !m.Is(val)) return graph()->start(); |
139 AddTrapIfTrue(reason, | 119 AddTrapIfTrue(reason, |
140 graph()->NewNode(jsgraph()->machine()->Word64Equal(), node, | 120 graph()->NewNode(jsgraph()->machine()->Word64Equal(), node, |
141 jsgraph()->Int64Constant(val))); | 121 jsgraph()->Int64Constant(val))); |
142 return builder_->Control(); | 122 return builder_->Control(); |
143 } | 123 } |
144 | 124 |
145 // Add a check that traps if {node} is zero. | 125 // Add a check that traps if {node} is zero. |
146 Node* ZeroCheck64(TrapReason reason, Node* node) { | 126 Node* ZeroCheck64(wasm::TrapReason reason, Node* node) { |
147 return TrapIfEq64(reason, node, 0); | 127 return TrapIfEq64(reason, node, 0); |
148 } | 128 } |
149 | 129 |
150 // Add a trap if {cond} is true. | 130 // Add a trap if {cond} is true. |
151 void AddTrapIfTrue(TrapReason reason, Node* cond) { | 131 void AddTrapIfTrue(wasm::TrapReason reason, Node* cond) { |
152 AddTrapIf(reason, cond, true); | 132 AddTrapIf(reason, cond, true); |
153 } | 133 } |
154 | 134 |
155 // Add a trap if {cond} is false. | 135 // Add a trap if {cond} is false. |
156 void AddTrapIfFalse(TrapReason reason, Node* cond) { | 136 void AddTrapIfFalse(wasm::TrapReason reason, Node* cond) { |
157 AddTrapIf(reason, cond, false); | 137 AddTrapIf(reason, cond, false); |
158 } | 138 } |
159 | 139 |
160 // Add a trap if {cond} is true or false according to {iftrue}. | 140 // Add a trap if {cond} is true or false according to {iftrue}. |
161 void AddTrapIf(TrapReason reason, Node* cond, bool iftrue) { | 141 void AddTrapIf(wasm::TrapReason reason, Node* cond, bool iftrue) { |
162 Node** effect_ptr = builder_->effect_; | 142 Node** effect_ptr = builder_->effect_; |
163 Node** control_ptr = builder_->control_; | 143 Node** control_ptr = builder_->control_; |
164 Node* before = *effect_ptr; | 144 Node* before = *effect_ptr; |
165 BranchHint hint = iftrue ? BranchHint::kFalse : BranchHint::kTrue; | 145 BranchHint hint = iftrue ? BranchHint::kFalse : BranchHint::kTrue; |
166 Node* branch = graph()->NewNode(common()->Branch(hint), cond, *control_ptr); | 146 Node* branch = graph()->NewNode(common()->Branch(hint), cond, *control_ptr); |
167 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 147 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
168 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 148 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
169 | 149 |
170 *control_ptr = iftrue ? if_true : if_false; | 150 *control_ptr = iftrue ? if_true : if_false; |
171 ConnectTrap(reason); | 151 ConnectTrap(reason); |
(...skipping 20 matching lines...) Expand all Loading... |
192 } | 172 } |
193 } else { | 173 } else { |
194 return jsgraph()->Int32Constant(0xdeadbeef); | 174 return jsgraph()->Int32Constant(0xdeadbeef); |
195 } | 175 } |
196 } | 176 } |
197 | 177 |
198 private: | 178 private: |
199 WasmGraphBuilder* builder_; | 179 WasmGraphBuilder* builder_; |
200 JSGraph* jsgraph_; | 180 JSGraph* jsgraph_; |
201 Graph* graph_; | 181 Graph* graph_; |
202 Node* traps_[kTrapCount]; | 182 Node* traps_[wasm::kTrapCount]; |
203 Node* effects_[kTrapCount]; | 183 Node* effects_[wasm::kTrapCount]; |
204 | 184 |
205 JSGraph* jsgraph() { return jsgraph_; } | 185 JSGraph* jsgraph() { return jsgraph_; } |
206 Graph* graph() { return jsgraph_->graph(); } | 186 Graph* graph() { return jsgraph_->graph(); } |
207 CommonOperatorBuilder* common() { return jsgraph()->common(); } | 187 CommonOperatorBuilder* common() { return jsgraph()->common(); } |
208 | 188 |
209 void ConnectTrap(TrapReason reason) { | 189 void ConnectTrap(wasm::TrapReason reason) { |
210 if (traps_[reason] == nullptr) { | 190 if (traps_[reason] == nullptr) { |
211 // Create trap code for the first time this trap is used. | 191 // Create trap code for the first time this trap is used. |
212 return BuildTrapCode(reason); | 192 return BuildTrapCode(reason); |
213 } | 193 } |
214 // Connect the current control and effect to the existing trap code. | 194 // Connect the current control and effect to the existing trap code. |
215 builder_->AppendToMerge(traps_[reason], builder_->Control()); | 195 builder_->AppendToMerge(traps_[reason], builder_->Control()); |
216 builder_->AppendToPhi(traps_[reason], effects_[reason], builder_->Effect()); | 196 builder_->AppendToPhi(traps_[reason], effects_[reason], builder_->Effect()); |
217 } | 197 } |
218 | 198 |
219 void BuildTrapCode(TrapReason reason) { | 199 void BuildTrapCode(wasm::TrapReason reason) { |
220 Node* exception = builder_->String(kTrapMessages[reason]); | 200 Node* exception = |
| 201 builder_->String(wasm::WasmOpcodes::TrapReasonName(reason)); |
221 Node* end; | 202 Node* end; |
222 Node** control_ptr = builder_->control_; | 203 Node** control_ptr = builder_->control_; |
223 Node** effect_ptr = builder_->effect_; | 204 Node** effect_ptr = builder_->effect_; |
224 wasm::ModuleEnv* module = builder_->module_; | 205 wasm::ModuleEnv* module = builder_->module_; |
225 *control_ptr = traps_[reason] = | 206 *control_ptr = traps_[reason] = |
226 graph()->NewNode(common()->Merge(1), *control_ptr); | 207 graph()->NewNode(common()->Merge(1), *control_ptr); |
227 *effect_ptr = effects_[reason] = | 208 *effect_ptr = effects_[reason] = |
228 graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr); | 209 graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr); |
229 | 210 |
230 if (module && !module->instance->context.is_null()) { | 211 if (module && !module->instance->context.is_null()) { |
(...skipping 28 matching lines...) Expand all Loading... |
259 // End the control flow with returning 0xdeadbeef | 240 // End the control flow with returning 0xdeadbeef |
260 Node* ret_value = GetTrapValue(builder_->GetFunctionSignature()); | 241 Node* ret_value = GetTrapValue(builder_->GetFunctionSignature()); |
261 end = graph()->NewNode(jsgraph()->common()->Return(), ret_value, | 242 end = graph()->NewNode(jsgraph()->common()->Return(), ret_value, |
262 *effect_ptr, *control_ptr); | 243 *effect_ptr, *control_ptr); |
263 } | 244 } |
264 | 245 |
265 MergeControlToEnd(jsgraph(), end); | 246 MergeControlToEnd(jsgraph(), end); |
266 } | 247 } |
267 }; | 248 }; |
268 | 249 |
269 | |
270 WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph, | 250 WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph, |
271 wasm::FunctionSig* function_signature) | 251 wasm::FunctionSig* function_signature) |
272 : zone_(zone), | 252 : zone_(zone), |
273 jsgraph_(jsgraph), | 253 jsgraph_(jsgraph), |
274 module_(nullptr), | 254 module_(nullptr), |
275 mem_buffer_(nullptr), | 255 mem_buffer_(nullptr), |
276 mem_size_(nullptr), | 256 mem_size_(nullptr), |
277 function_table_(nullptr), | 257 function_table_(nullptr), |
278 control_(nullptr), | 258 control_(nullptr), |
279 effect_(nullptr), | 259 effect_(nullptr), |
(...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 } | 1144 } |
1165 | 1145 |
1166 // Truncation of the input value is needed for the overflow check later. | 1146 // Truncation of the input value is needed for the overflow check later. |
1167 Node* trunc = Unop(wasm::kExprF32Trunc, input); | 1147 Node* trunc = Unop(wasm::kExprF32Trunc, input); |
1168 Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc); | 1148 Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc); |
1169 | 1149 |
1170 // Convert the result back to f64. If we end up at a different value than the | 1150 // Convert the result back to f64. If we end up at a different value than the |
1171 // truncated input value, then there has been an overflow and we trap. | 1151 // truncated input value, then there has been an overflow and we trap. |
1172 Node* check = Unop(wasm::kExprF32SConvertI32, result); | 1152 Node* check = Unop(wasm::kExprF32SConvertI32, result); |
1173 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); | 1153 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); |
1174 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1154 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); |
1175 | 1155 |
1176 return result; | 1156 return result; |
1177 } | 1157 } |
1178 | 1158 |
1179 | 1159 |
1180 Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) { | 1160 Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) { |
1181 MachineOperatorBuilder* m = jsgraph()->machine(); | 1161 MachineOperatorBuilder* m = jsgraph()->machine(); |
1182 if (module_ && module_->asm_js()) { | 1162 if (module_ && module_->asm_js()) { |
1183 // asm.js must use the wacky JS semantics. | 1163 // asm.js must use the wacky JS semantics. |
1184 return graph()->NewNode( | 1164 return graph()->NewNode( |
1185 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); | 1165 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
1186 } | 1166 } |
1187 // Truncation of the input value is needed for the overflow check later. | 1167 // Truncation of the input value is needed for the overflow check later. |
1188 Node* trunc = Unop(wasm::kExprF64Trunc, input); | 1168 Node* trunc = Unop(wasm::kExprF64Trunc, input); |
1189 Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc); | 1169 Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc); |
1190 | 1170 |
1191 // Convert the result back to f64. If we end up at a different value than the | 1171 // Convert the result back to f64. If we end up at a different value than the |
1192 // truncated input value, then there has been an overflow and we trap. | 1172 // truncated input value, then there has been an overflow and we trap. |
1193 Node* check = Unop(wasm::kExprF64SConvertI32, result); | 1173 Node* check = Unop(wasm::kExprF64SConvertI32, result); |
1194 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); | 1174 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); |
1195 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1175 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); |
1196 | 1176 |
1197 return result; | 1177 return result; |
1198 } | 1178 } |
1199 | 1179 |
1200 | 1180 |
1201 Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input) { | 1181 Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input) { |
1202 MachineOperatorBuilder* m = jsgraph()->machine(); | 1182 MachineOperatorBuilder* m = jsgraph()->machine(); |
1203 if (module_ && module_->asm_js()) { | 1183 if (module_ && module_->asm_js()) { |
1204 // asm.js must use the wacky JS semantics. | 1184 // asm.js must use the wacky JS semantics. |
1205 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); | 1185 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); |
1206 return graph()->NewNode( | 1186 return graph()->NewNode( |
1207 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); | 1187 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
1208 } | 1188 } |
1209 | 1189 |
1210 // Truncation of the input value is needed for the overflow check later. | 1190 // Truncation of the input value is needed for the overflow check later. |
1211 Node* trunc = Unop(wasm::kExprF32Trunc, input); | 1191 Node* trunc = Unop(wasm::kExprF32Trunc, input); |
1212 Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc); | 1192 Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc); |
1213 | 1193 |
1214 // Convert the result back to f32. If we end up at a different value than the | 1194 // Convert the result back to f32. If we end up at a different value than the |
1215 // truncated input value, then there has been an overflow and we trap. | 1195 // truncated input value, then there has been an overflow and we trap. |
1216 Node* check = Unop(wasm::kExprF32UConvertI32, result); | 1196 Node* check = Unop(wasm::kExprF32UConvertI32, result); |
1217 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); | 1197 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); |
1218 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1198 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); |
1219 | 1199 |
1220 return result; | 1200 return result; |
1221 } | 1201 } |
1222 | 1202 |
1223 | 1203 |
1224 Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) { | 1204 Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) { |
1225 MachineOperatorBuilder* m = jsgraph()->machine(); | 1205 MachineOperatorBuilder* m = jsgraph()->machine(); |
1226 if (module_ && module_->asm_js()) { | 1206 if (module_ && module_->asm_js()) { |
1227 // asm.js must use the wacky JS semantics. | 1207 // asm.js must use the wacky JS semantics. |
1228 return graph()->NewNode( | 1208 return graph()->NewNode( |
1229 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); | 1209 m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input); |
1230 } | 1210 } |
1231 // Truncation of the input value is needed for the overflow check later. | 1211 // Truncation of the input value is needed for the overflow check later. |
1232 Node* trunc = Unop(wasm::kExprF64Trunc, input); | 1212 Node* trunc = Unop(wasm::kExprF64Trunc, input); |
1233 Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc); | 1213 Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc); |
1234 | 1214 |
1235 // Convert the result back to f64. If we end up at a different value than the | 1215 // Convert the result back to f64. If we end up at a different value than the |
1236 // truncated input value, then there has been an overflow and we trap. | 1216 // truncated input value, then there has been an overflow and we trap. |
1237 Node* check = Unop(wasm::kExprF64UConvertI32, result); | 1217 Node* check = Unop(wasm::kExprF64UConvertI32, result); |
1238 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); | 1218 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); |
1239 trap_->AddTrapIfTrue(kTrapFloatUnrepresentable, overflow); | 1219 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); |
1240 | 1220 |
1241 return result; | 1221 return result; |
1242 } | 1222 } |
1243 | 1223 |
1244 | 1224 |
1245 Node* WasmGraphBuilder::BuildI32Ctz(Node* input) { | 1225 Node* WasmGraphBuilder::BuildI32Ctz(Node* input) { |
1246 //// Implement the following code as TF graph. | 1226 //// Implement the following code as TF graph. |
1247 // value = value | (value << 1); | 1227 // value = value | (value << 1); |
1248 // value = value | (value << 2); | 1228 // value = value | (value << 2); |
1249 // value = value | (value << 4); | 1229 // value = value | (value << 4); |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1659 if (jsgraph()->machine()->Is32()) { | 1639 if (jsgraph()->machine()->Is32()) { |
1660 return BuildFloatToIntConversionInstruction( | 1640 return BuildFloatToIntConversionInstruction( |
1661 input, ExternalReference::wasm_float32_to_int64(jsgraph()->isolate()), | 1641 input, ExternalReference::wasm_float32_to_int64(jsgraph()->isolate()), |
1662 MachineRepresentation::kFloat32, MachineType::Int64()); | 1642 MachineRepresentation::kFloat32, MachineType::Int64()); |
1663 } else { | 1643 } else { |
1664 Node* trunc = graph()->NewNode( | 1644 Node* trunc = graph()->NewNode( |
1665 jsgraph()->machine()->TryTruncateFloat32ToInt64(), input); | 1645 jsgraph()->machine()->TryTruncateFloat32ToInt64(), input); |
1666 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1646 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
1667 Node* overflow = | 1647 Node* overflow = |
1668 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1648 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
1669 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); | 1649 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); |
1670 return result; | 1650 return result; |
1671 } | 1651 } |
1672 } | 1652 } |
1673 | 1653 |
1674 Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input) { | 1654 Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input) { |
1675 if (jsgraph()->machine()->Is32()) { | 1655 if (jsgraph()->machine()->Is32()) { |
1676 return BuildFloatToIntConversionInstruction( | 1656 return BuildFloatToIntConversionInstruction( |
1677 input, ExternalReference::wasm_float32_to_uint64(jsgraph()->isolate()), | 1657 input, ExternalReference::wasm_float32_to_uint64(jsgraph()->isolate()), |
1678 MachineRepresentation::kFloat32, MachineType::Int64()); | 1658 MachineRepresentation::kFloat32, MachineType::Int64()); |
1679 } else { | 1659 } else { |
1680 Node* trunc = graph()->NewNode( | 1660 Node* trunc = graph()->NewNode( |
1681 jsgraph()->machine()->TryTruncateFloat32ToUint64(), input); | 1661 jsgraph()->machine()->TryTruncateFloat32ToUint64(), input); |
1682 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1662 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
1683 Node* overflow = | 1663 Node* overflow = |
1684 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1664 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
1685 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); | 1665 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); |
1686 return result; | 1666 return result; |
1687 } | 1667 } |
1688 } | 1668 } |
1689 | 1669 |
1690 Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input) { | 1670 Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input) { |
1691 if (jsgraph()->machine()->Is32()) { | 1671 if (jsgraph()->machine()->Is32()) { |
1692 return BuildFloatToIntConversionInstruction( | 1672 return BuildFloatToIntConversionInstruction( |
1693 input, ExternalReference::wasm_float64_to_int64(jsgraph()->isolate()), | 1673 input, ExternalReference::wasm_float64_to_int64(jsgraph()->isolate()), |
1694 MachineRepresentation::kFloat64, MachineType::Int64()); | 1674 MachineRepresentation::kFloat64, MachineType::Int64()); |
1695 } else { | 1675 } else { |
1696 Node* trunc = graph()->NewNode( | 1676 Node* trunc = graph()->NewNode( |
1697 jsgraph()->machine()->TryTruncateFloat64ToInt64(), input); | 1677 jsgraph()->machine()->TryTruncateFloat64ToInt64(), input); |
1698 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1678 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
1699 Node* overflow = | 1679 Node* overflow = |
1700 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1680 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
1701 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); | 1681 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); |
1702 return result; | 1682 return result; |
1703 } | 1683 } |
1704 } | 1684 } |
1705 | 1685 |
1706 Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input) { | 1686 Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input) { |
1707 if (jsgraph()->machine()->Is32()) { | 1687 if (jsgraph()->machine()->Is32()) { |
1708 return BuildFloatToIntConversionInstruction( | 1688 return BuildFloatToIntConversionInstruction( |
1709 input, ExternalReference::wasm_float64_to_uint64(jsgraph()->isolate()), | 1689 input, ExternalReference::wasm_float64_to_uint64(jsgraph()->isolate()), |
1710 MachineRepresentation::kFloat64, MachineType::Int64()); | 1690 MachineRepresentation::kFloat64, MachineType::Int64()); |
1711 } else { | 1691 } else { |
1712 Node* trunc = graph()->NewNode( | 1692 Node* trunc = graph()->NewNode( |
1713 jsgraph()->machine()->TryTruncateFloat64ToUint64(), input); | 1693 jsgraph()->machine()->TryTruncateFloat64ToUint64(), input); |
1714 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1694 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
1715 Node* overflow = | 1695 Node* overflow = |
1716 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1696 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
1717 trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow); | 1697 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); |
1718 return result; | 1698 return result; |
1719 } | 1699 } |
1720 } | 1700 } |
1721 | 1701 |
1722 Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction( | 1702 Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction( |
1723 Node* input, ExternalReference ref, | 1703 Node* input, ExternalReference ref, |
1724 MachineRepresentation parameter_representation, | 1704 MachineRepresentation parameter_representation, |
1725 const MachineType result_type) { | 1705 const MachineType result_type) { |
1726 Node* stack_slot_param = graph()->NewNode( | 1706 Node* stack_slot_param = graph()->NewNode( |
1727 jsgraph()->machine()->StackSlot(parameter_representation)); | 1707 jsgraph()->machine()->StackSlot(parameter_representation)); |
1728 Node* stack_slot_result = graph()->NewNode( | 1708 Node* stack_slot_result = graph()->NewNode( |
1729 jsgraph()->machine()->StackSlot(result_type.representation())); | 1709 jsgraph()->machine()->StackSlot(result_type.representation())); |
1730 const Operator* store_op = jsgraph()->machine()->Store( | 1710 const Operator* store_op = jsgraph()->machine()->Store( |
1731 StoreRepresentation(parameter_representation, kNoWriteBarrier)); | 1711 StoreRepresentation(parameter_representation, kNoWriteBarrier)); |
1732 *effect_ = | 1712 *effect_ = |
1733 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), | 1713 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), |
1734 input, *effect_, *control_); | 1714 input, *effect_, *control_); |
1735 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); | 1715 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); |
1736 sig_builder.AddReturn(MachineType::Int32()); | 1716 sig_builder.AddReturn(MachineType::Int32()); |
1737 sig_builder.AddParam(MachineType::Pointer()); | 1717 sig_builder.AddParam(MachineType::Pointer()); |
1738 sig_builder.AddParam(MachineType::Pointer()); | 1718 sig_builder.AddParam(MachineType::Pointer()); |
1739 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); | 1719 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
1740 Node* args[] = {function, stack_slot_param, stack_slot_result}; | 1720 Node* args[] = {function, stack_slot_param, stack_slot_result}; |
1741 trap_->ZeroCheck32(kTrapFloatUnrepresentable, | 1721 trap_->ZeroCheck32(wasm::kTrapFloatUnrepresentable, |
1742 BuildCCall(sig_builder.Build(), args)); | 1722 BuildCCall(sig_builder.Build(), args)); |
1743 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1723 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
1744 Node* load = | 1724 Node* load = |
1745 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), | 1725 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), |
1746 *effect_, *control_); | 1726 *effect_, *control_); |
1747 *effect_ = load; | 1727 *effect_ = load; |
1748 return load; | 1728 return load; |
1749 } | 1729 } |
1750 | 1730 |
1751 Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right) { | 1731 Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right) { |
(...skipping 19 matching lines...) Expand all Loading... |
1771 | 1751 |
1772 Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false); | 1752 Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false); |
1773 Node* neg = | 1753 Node* neg = |
1774 graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left); | 1754 graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left); |
1775 | 1755 |
1776 return n.Phi(MachineRepresentation::kWord32, neg, | 1756 return n.Phi(MachineRepresentation::kWord32, neg, |
1777 z.Phi(MachineRepresentation::kWord32, | 1757 z.Phi(MachineRepresentation::kWord32, |
1778 jsgraph()->Int32Constant(0), div)); | 1758 jsgraph()->Int32Constant(0), div)); |
1779 } | 1759 } |
1780 | 1760 |
1781 trap_->ZeroCheck32(kTrapDivByZero, right); | 1761 trap_->ZeroCheck32(wasm::kTrapDivByZero, right); |
1782 Node* before = *control_; | 1762 Node* before = *control_; |
1783 Node* denom_is_m1; | 1763 Node* denom_is_m1; |
1784 Node* denom_is_not_m1; | 1764 Node* denom_is_not_m1; |
1785 Branch( | 1765 Branch( |
1786 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1766 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
1787 &denom_is_m1, &denom_is_not_m1); | 1767 &denom_is_m1, &denom_is_not_m1); |
1788 *control_ = denom_is_m1; | 1768 *control_ = denom_is_m1; |
1789 trap_->TrapIfEq32(kTrapDivUnrepresentable, left, kMinInt); | 1769 trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt); |
1790 if (*control_ != denom_is_m1) { | 1770 if (*control_ != denom_is_m1) { |
1791 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, | 1771 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, |
1792 *control_); | 1772 *control_); |
1793 } else { | 1773 } else { |
1794 *control_ = before; | 1774 *control_ = before; |
1795 } | 1775 } |
1796 return graph()->NewNode(m->Int32Div(), left, right, *control_); | 1776 return graph()->NewNode(m->Int32Div(), left, right, *control_); |
1797 } | 1777 } |
1798 | 1778 |
1799 Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right) { | 1779 Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right) { |
(...skipping 12 matching lines...) Expand all Loading... |
1812 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1792 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
1813 BranchHint::kFalse); | 1793 BranchHint::kFalse); |
1814 d.Chain(z.if_false); | 1794 d.Chain(z.if_false); |
1815 | 1795 |
1816 return z.Phi( | 1796 return z.Phi( |
1817 MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1797 MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1818 d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1798 d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1819 graph()->NewNode(m->Int32Mod(), left, right, d.if_false))); | 1799 graph()->NewNode(m->Int32Mod(), left, right, d.if_false))); |
1820 } | 1800 } |
1821 | 1801 |
1822 trap_->ZeroCheck32(kTrapRemByZero, right); | 1802 trap_->ZeroCheck32(wasm::kTrapRemByZero, right); |
1823 | 1803 |
1824 Diamond d( | 1804 Diamond d( |
1825 graph(), jsgraph()->common(), | 1805 graph(), jsgraph()->common(), |
1826 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1806 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
1827 BranchHint::kFalse); | 1807 BranchHint::kFalse); |
1828 d.Chain(*control_); | 1808 d.Chain(*control_); |
1829 | 1809 |
1830 return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1810 return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1831 graph()->NewNode(m->Int32Mod(), left, right, d.if_false)); | 1811 graph()->NewNode(m->Int32Mod(), left, right, d.if_false)); |
1832 } | 1812 } |
(...skipping 11 matching lines...) Expand all Loading... |
1844 Diamond z( | 1824 Diamond z( |
1845 graph(), jsgraph()->common(), | 1825 graph(), jsgraph()->common(), |
1846 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | 1826 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
1847 BranchHint::kFalse); | 1827 BranchHint::kFalse); |
1848 | 1828 |
1849 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1829 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1850 graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, | 1830 graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, |
1851 right, z.if_false)); | 1831 right, z.if_false)); |
1852 } | 1832 } |
1853 return graph()->NewNode(m->Uint32Div(), left, right, | 1833 return graph()->NewNode(m->Uint32Div(), left, right, |
1854 trap_->ZeroCheck32(kTrapDivByZero, right)); | 1834 trap_->ZeroCheck32(wasm::kTrapDivByZero, right)); |
1855 } | 1835 } |
1856 | 1836 |
1857 Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right) { | 1837 Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right) { |
1858 MachineOperatorBuilder* m = jsgraph()->machine(); | 1838 MachineOperatorBuilder* m = jsgraph()->machine(); |
1859 if (module_ && module_->asm_js()) { | 1839 if (module_ && module_->asm_js()) { |
1860 // asm.js semantics return 0 on divide or mod by zero. | 1840 // asm.js semantics return 0 on divide or mod by zero. |
1861 // Explicit check for x % 0. | 1841 // Explicit check for x % 0. |
1862 Diamond z( | 1842 Diamond z( |
1863 graph(), jsgraph()->common(), | 1843 graph(), jsgraph()->common(), |
1864 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | 1844 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
1865 BranchHint::kFalse); | 1845 BranchHint::kFalse); |
1866 | 1846 |
1867 Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right, | 1847 Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right, |
1868 z.if_false); | 1848 z.if_false); |
1869 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1849 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1870 rem); | 1850 rem); |
1871 } | 1851 } |
1872 | 1852 |
1873 return graph()->NewNode(m->Uint32Mod(), left, right, | 1853 return graph()->NewNode(m->Uint32Mod(), left, right, |
1874 trap_->ZeroCheck32(kTrapRemByZero, right)); | 1854 trap_->ZeroCheck32(wasm::kTrapRemByZero, right)); |
1875 } | 1855 } |
1876 | 1856 |
1877 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { | 1857 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { |
1878 if (jsgraph()->machine()->Is32()) { | 1858 if (jsgraph()->machine()->Is32()) { |
1879 return BuildDiv64Call( | 1859 return BuildDiv64Call( |
1880 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), | 1860 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), |
1881 MachineType::Int64(), kTrapDivByZero); | 1861 MachineType::Int64(), wasm::kTrapDivByZero); |
1882 } | 1862 } |
1883 trap_->ZeroCheck64(kTrapDivByZero, right); | 1863 trap_->ZeroCheck64(wasm::kTrapDivByZero, right); |
1884 Node* before = *control_; | 1864 Node* before = *control_; |
1885 Node* denom_is_m1; | 1865 Node* denom_is_m1; |
1886 Node* denom_is_not_m1; | 1866 Node* denom_is_not_m1; |
1887 Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | 1867 Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
1888 jsgraph()->Int64Constant(-1)), | 1868 jsgraph()->Int64Constant(-1)), |
1889 &denom_is_m1, &denom_is_not_m1); | 1869 &denom_is_m1, &denom_is_not_m1); |
1890 *control_ = denom_is_m1; | 1870 *control_ = denom_is_m1; |
1891 trap_->TrapIfEq64(kTrapDivUnrepresentable, left, | 1871 trap_->TrapIfEq64(wasm::kTrapDivUnrepresentable, left, |
1892 std::numeric_limits<int64_t>::min()); | 1872 std::numeric_limits<int64_t>::min()); |
1893 if (*control_ != denom_is_m1) { | 1873 if (*control_ != denom_is_m1) { |
1894 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, | 1874 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, |
1895 *control_); | 1875 *control_); |
1896 } else { | 1876 } else { |
1897 *control_ = before; | 1877 *control_ = before; |
1898 } | 1878 } |
1899 return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right, | 1879 return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right, |
1900 *control_); | 1880 *control_); |
1901 } | 1881 } |
1902 | 1882 |
1903 Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right) { | 1883 Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right) { |
1904 if (jsgraph()->machine()->Is32()) { | 1884 if (jsgraph()->machine()->Is32()) { |
1905 return BuildDiv64Call( | 1885 return BuildDiv64Call( |
1906 left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()), | 1886 left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()), |
1907 MachineType::Int64(), kTrapRemByZero); | 1887 MachineType::Int64(), wasm::kTrapRemByZero); |
1908 } | 1888 } |
1909 trap_->ZeroCheck64(kTrapRemByZero, right); | 1889 trap_->ZeroCheck64(wasm::kTrapRemByZero, right); |
1910 Diamond d(jsgraph()->graph(), jsgraph()->common(), | 1890 Diamond d(jsgraph()->graph(), jsgraph()->common(), |
1911 graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | 1891 graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
1912 jsgraph()->Int64Constant(-1))); | 1892 jsgraph()->Int64Constant(-1))); |
1913 | 1893 |
1914 Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right, | 1894 Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right, |
1915 d.if_false); | 1895 d.if_false); |
1916 | 1896 |
1917 return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), | 1897 return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), |
1918 rem); | 1898 rem); |
1919 } | 1899 } |
1920 | 1900 |
1921 Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right) { | 1901 Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right) { |
1922 if (jsgraph()->machine()->Is32()) { | 1902 if (jsgraph()->machine()->Is32()) { |
1923 return BuildDiv64Call( | 1903 return BuildDiv64Call( |
1924 left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()), | 1904 left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()), |
1925 MachineType::Int64(), kTrapDivByZero); | 1905 MachineType::Int64(), wasm::kTrapDivByZero); |
1926 } | 1906 } |
1927 return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right, | 1907 return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right, |
1928 trap_->ZeroCheck64(kTrapDivByZero, right)); | 1908 trap_->ZeroCheck64(wasm::kTrapDivByZero, right)); |
1929 } | 1909 } |
1930 Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right) { | 1910 Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right) { |
1931 if (jsgraph()->machine()->Is32()) { | 1911 if (jsgraph()->machine()->Is32()) { |
1932 return BuildDiv64Call( | 1912 return BuildDiv64Call( |
1933 left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()), | 1913 left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()), |
1934 MachineType::Int64(), kTrapRemByZero); | 1914 MachineType::Int64(), wasm::kTrapRemByZero); |
1935 } | 1915 } |
1936 return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right, | 1916 return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right, |
1937 trap_->ZeroCheck64(kTrapRemByZero, right)); | 1917 trap_->ZeroCheck64(wasm::kTrapRemByZero, right)); |
1938 } | 1918 } |
1939 | 1919 |
1940 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right, | 1920 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right, |
1941 ExternalReference ref, | 1921 ExternalReference ref, |
1942 MachineType result_type, int trap_zero) { | 1922 MachineType result_type, int trap_zero) { |
1943 Node* stack_slot_dst = graph()->NewNode( | 1923 Node* stack_slot_dst = graph()->NewNode( |
1944 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); | 1924 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
1945 Node* stack_slot_src = graph()->NewNode( | 1925 Node* stack_slot_src = graph()->NewNode( |
1946 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); | 1926 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
1947 | 1927 |
(...skipping 11 matching lines...) Expand all Loading... |
1959 sig_builder.AddParam(MachineType::Pointer()); | 1939 sig_builder.AddParam(MachineType::Pointer()); |
1960 sig_builder.AddParam(MachineType::Pointer()); | 1940 sig_builder.AddParam(MachineType::Pointer()); |
1961 | 1941 |
1962 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); | 1942 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
1963 Node* args[] = {function, stack_slot_dst, stack_slot_src}; | 1943 Node* args[] = {function, stack_slot_dst, stack_slot_src}; |
1964 | 1944 |
1965 Node* call = BuildCCall(sig_builder.Build(), args); | 1945 Node* call = BuildCCall(sig_builder.Build(), args); |
1966 | 1946 |
1967 // TODO(wasm): This can get simpler if we have a specialized runtime call to | 1947 // TODO(wasm): This can get simpler if we have a specialized runtime call to |
1968 // throw WASM exceptions by trap code instead of by string. | 1948 // throw WASM exceptions by trap code instead of by string. |
1969 trap_->ZeroCheck32(static_cast<TrapReason>(trap_zero), call); | 1949 trap_->ZeroCheck32(static_cast<wasm::TrapReason>(trap_zero), call); |
1970 trap_->TrapIfEq32(kTrapDivUnrepresentable, call, -1); | 1950 trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1); |
1971 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1951 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
1972 Node* load = | 1952 Node* load = |
1973 graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0), | 1953 graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0), |
1974 *effect_, *control_); | 1954 *effect_, *control_); |
1975 *effect_ = load; | 1955 *effect_ = load; |
1976 return load; | 1956 return load; |
1977 } | 1957 } |
1978 | 1958 |
1979 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { | 1959 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
1980 const size_t params = sig->parameter_count(); | 1960 const size_t params = sig->parameter_count(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2046 | 2026 |
2047 // Compute the code object by loading it from the function table. | 2027 // Compute the code object by loading it from the function table. |
2048 Node* key = args[0]; | 2028 Node* key = args[0]; |
2049 | 2029 |
2050 // Bounds check the index. | 2030 // Bounds check the index. |
2051 int table_size = static_cast<int>(module_->FunctionTableSize()); | 2031 int table_size = static_cast<int>(module_->FunctionTableSize()); |
2052 if (table_size > 0) { | 2032 if (table_size > 0) { |
2053 // Bounds check against the table size. | 2033 // Bounds check against the table size. |
2054 Node* size = Int32Constant(static_cast<int>(table_size)); | 2034 Node* size = Int32Constant(static_cast<int>(table_size)); |
2055 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); | 2035 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); |
2056 trap_->AddTrapIfFalse(kTrapFuncInvalid, in_bounds); | 2036 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds); |
2057 } else { | 2037 } else { |
2058 // No function table. Generate a trap and return a constant. | 2038 // No function table. Generate a trap and return a constant. |
2059 trap_->AddTrapIfFalse(kTrapFuncInvalid, Int32Constant(0)); | 2039 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0)); |
2060 return trap_->GetTrapValue(module_->GetSignature(index)); | 2040 return trap_->GetTrapValue(module_->GetSignature(index)); |
2061 } | 2041 } |
2062 Node* table = FunctionTable(); | 2042 Node* table = FunctionTable(); |
2063 | 2043 |
2064 // Load signature from the table and check. | 2044 // Load signature from the table and check. |
2065 // The table is a FixedArray; signatures are encoded as SMIs. | 2045 // The table is a FixedArray; signatures are encoded as SMIs. |
2066 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] | 2046 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] |
2067 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 2047 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
2068 const int fixed_offset = access.header_size - access.tag(); | 2048 const int fixed_offset = access.header_size - access.tag(); |
2069 { | 2049 { |
2070 Node* load_sig = graph()->NewNode( | 2050 Node* load_sig = graph()->NewNode( |
2071 machine->Load(MachineType::AnyTagged()), table, | 2051 machine->Load(MachineType::AnyTagged()), table, |
2072 graph()->NewNode(machine->Int32Add(), | 2052 graph()->NewNode(machine->Int32Add(), |
2073 graph()->NewNode(machine->Word32Shl(), key, | 2053 graph()->NewNode(machine->Word32Shl(), key, |
2074 Int32Constant(kPointerSizeLog2)), | 2054 Int32Constant(kPointerSizeLog2)), |
2075 Int32Constant(fixed_offset)), | 2055 Int32Constant(fixed_offset)), |
2076 *effect_, *control_); | 2056 *effect_, *control_); |
2077 Node* sig_match = graph()->NewNode(machine->WordEqual(), load_sig, | 2057 Node* sig_match = graph()->NewNode(machine->WordEqual(), load_sig, |
2078 jsgraph()->SmiConstant(index)); | 2058 jsgraph()->SmiConstant(index)); |
2079 trap_->AddTrapIfFalse(kTrapFuncSigMismatch, sig_match); | 2059 trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match); |
2080 } | 2060 } |
2081 | 2061 |
2082 // Load code object from the table. | 2062 // Load code object from the table. |
2083 int offset = fixed_offset + kPointerSize * table_size; | 2063 int offset = fixed_offset + kPointerSize * table_size; |
2084 Node* load_code = graph()->NewNode( | 2064 Node* load_code = graph()->NewNode( |
2085 machine->Load(MachineType::AnyTagged()), table, | 2065 machine->Load(MachineType::AnyTagged()), table, |
2086 graph()->NewNode(machine->Int32Add(), | 2066 graph()->NewNode(machine->Int32Add(), |
2087 graph()->NewNode(machine->Word32Shl(), key, | 2067 graph()->NewNode(machine->Word32Shl(), key, |
2088 Int32Constant(kPointerSizeLog2)), | 2068 Int32Constant(kPointerSizeLog2)), |
2089 Int32Constant(offset)), | 2069 Int32Constant(offset)), |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2388 cond = jsgraph()->Int32Constant(0); | 2368 cond = jsgraph()->Int32Constant(0); |
2389 } else { | 2369 } else { |
2390 // Check against the limit. | 2370 // Check against the limit. |
2391 size_t limit = size - offset - memsize; | 2371 size_t limit = size - offset - memsize; |
2392 CHECK(limit <= kMaxUInt32); | 2372 CHECK(limit <= kMaxUInt32); |
2393 cond = graph()->NewNode( | 2373 cond = graph()->NewNode( |
2394 jsgraph()->machine()->Uint32LessThanOrEqual(), index, | 2374 jsgraph()->machine()->Uint32LessThanOrEqual(), index, |
2395 jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); | 2375 jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); |
2396 } | 2376 } |
2397 | 2377 |
2398 trap_->AddTrapIfFalse(kTrapMemOutOfBounds, cond); | 2378 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond); |
2399 } | 2379 } |
2400 | 2380 |
2401 | 2381 |
2402 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, | 2382 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |
2403 Node* index, uint32_t offset) { | 2383 Node* index, uint32_t offset) { |
2404 Node* load; | 2384 Node* load; |
2405 | 2385 |
2406 if (module_ && module_->asm_js()) { | 2386 if (module_ && module_->asm_js()) { |
2407 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). | 2387 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). |
2408 DCHECK_EQ(0, offset); | 2388 DCHECK_EQ(0, offset); |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2798 static_cast<int>(function.code_end_offset - function.code_start_offset), | 2778 static_cast<int>(function.code_end_offset - function.code_start_offset), |
2799 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); | 2779 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); |
2800 } | 2780 } |
2801 return code; | 2781 return code; |
2802 } | 2782 } |
2803 | 2783 |
2804 | 2784 |
2805 } // namespace compiler | 2785 } // namespace compiler |
2806 } // namespace internal | 2786 } // namespace internal |
2807 } // namespace v8 | 2787 } // namespace v8 |
OLD | NEW |