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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
73 | 73 |
74 // A helper that handles building graph fragments for trapping. | 74 // A helper that handles building graph fragments for trapping. |
75 // To avoid generating a ton of redundant code that just calls the runtime | 75 // To avoid generating a ton of redundant code that just calls the runtime |
76 // to trap, we generate a per-trap-reason block of code that all trap sites | 76 // to trap, we generate a per-trap-reason block of code that all trap sites |
77 // in this function will branch to. | 77 // in this function will branch to. |
78 class WasmTrapHelper : public ZoneObject { | 78 class WasmTrapHelper : public ZoneObject { |
79 public: | 79 public: |
80 explicit WasmTrapHelper(WasmGraphBuilder* builder) | 80 explicit WasmTrapHelper(WasmGraphBuilder* builder) |
81 : builder_(builder), | 81 : builder_(builder), |
82 jsgraph_(builder->jsgraph()), | 82 jsgraph_(builder->jsgraph()), |
83 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) { | 83 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) {} |
84 for (int i = 0; i < wasm::kTrapCount; i++) traps_[i] = nullptr; | 84 |
85 // Make the current control path trap to unreachable. | |
86 void Unreachable(int position) { | |
87 ConnectTrap(wasm::kTrapUnreachable, position); | |
85 } | 88 } |
86 | 89 |
87 // Make the current control path trap to unreachable. | |
88 void Unreachable() { ConnectTrap(wasm::kTrapUnreachable); } | |
89 | |
90 // Always trap with the given reason. | 90 // Always trap with the given reason. |
91 void TrapAlways(wasm::TrapReason reason) { ConnectTrap(reason); } | 91 void TrapAlways(wasm::TrapReason reason, int position) { |
92 ConnectTrap(reason, position); | |
93 } | |
92 | 94 |
93 // Add a check that traps if {node} is equal to {val}. | 95 // Add a check that traps if {node} is equal to {val}. |
94 Node* TrapIfEq32(wasm::TrapReason reason, Node* node, int32_t val) { | 96 Node* TrapIfEq32(wasm::TrapReason reason, Node* node, int32_t val, |
97 int position) { | |
95 Int32Matcher m(node); | 98 Int32Matcher m(node); |
96 if (m.HasValue() && !m.Is(val)) return graph()->start(); | 99 if (m.HasValue() && !m.Is(val)) return graph()->start(); |
97 if (val == 0) { | 100 if (val == 0) { |
98 AddTrapIfFalse(reason, node); | 101 AddTrapIfFalse(reason, node, position); |
99 } else { | 102 } else { |
100 AddTrapIfTrue(reason, | 103 AddTrapIfTrue(reason, |
101 graph()->NewNode(jsgraph()->machine()->Word32Equal(), node, | 104 graph()->NewNode(jsgraph()->machine()->Word32Equal(), node, |
102 jsgraph()->Int32Constant(val))); | 105 jsgraph()->Int32Constant(val)), |
106 position); | |
103 } | 107 } |
104 return builder_->Control(); | 108 return builder_->Control(); |
105 } | 109 } |
106 | 110 |
107 // Add a check that traps if {node} is zero. | 111 // Add a check that traps if {node} is zero. |
108 Node* ZeroCheck32(wasm::TrapReason reason, Node* node) { | 112 Node* ZeroCheck32(wasm::TrapReason reason, Node* node, int position) { |
109 return TrapIfEq32(reason, node, 0); | 113 return TrapIfEq32(reason, node, 0, position); |
110 } | 114 } |
111 | 115 |
112 // Add a check that traps if {node} is equal to {val}. | 116 // Add a check that traps if {node} is equal to {val}. |
113 Node* TrapIfEq64(wasm::TrapReason reason, Node* node, int64_t val) { | 117 Node* TrapIfEq64(wasm::TrapReason reason, Node* node, int64_t val, |
118 int position) { | |
114 Int64Matcher m(node); | 119 Int64Matcher m(node); |
115 if (m.HasValue() && !m.Is(val)) return graph()->start(); | 120 if (m.HasValue() && !m.Is(val)) return graph()->start(); |
116 AddTrapIfTrue(reason, | 121 AddTrapIfTrue(reason, graph()->NewNode(jsgraph()->machine()->Word64Equal(), |
117 graph()->NewNode(jsgraph()->machine()->Word64Equal(), node, | 122 node, jsgraph()->Int64Constant(val)), |
118 jsgraph()->Int64Constant(val))); | 123 position); |
119 return builder_->Control(); | 124 return builder_->Control(); |
120 } | 125 } |
121 | 126 |
122 // Add a check that traps if {node} is zero. | 127 // Add a check that traps if {node} is zero. |
123 Node* ZeroCheck64(wasm::TrapReason reason, Node* node) { | 128 Node* ZeroCheck64(wasm::TrapReason reason, Node* node, int position) { |
124 return TrapIfEq64(reason, node, 0); | 129 return TrapIfEq64(reason, node, 0, position); |
125 } | 130 } |
126 | 131 |
127 // Add a trap if {cond} is true. | 132 // Add a trap if {cond} is true. |
128 void AddTrapIfTrue(wasm::TrapReason reason, Node* cond) { | 133 void AddTrapIfTrue(wasm::TrapReason reason, Node* cond, int position) { |
129 AddTrapIf(reason, cond, true); | 134 AddTrapIf(reason, cond, true, position); |
130 } | 135 } |
131 | 136 |
132 // Add a trap if {cond} is false. | 137 // Add a trap if {cond} is false. |
133 void AddTrapIfFalse(wasm::TrapReason reason, Node* cond) { | 138 void AddTrapIfFalse(wasm::TrapReason reason, Node* cond, int position) { |
134 AddTrapIf(reason, cond, false); | 139 AddTrapIf(reason, cond, false, position); |
135 } | 140 } |
136 | 141 |
137 // Add a trap if {cond} is true or false according to {iftrue}. | 142 // Add a trap if {cond} is true or false according to {iftrue}. |
138 void AddTrapIf(wasm::TrapReason reason, Node* cond, bool iftrue) { | 143 void AddTrapIf(wasm::TrapReason reason, Node* cond, bool iftrue, |
144 int position) { | |
139 Node** effect_ptr = builder_->effect_; | 145 Node** effect_ptr = builder_->effect_; |
140 Node** control_ptr = builder_->control_; | 146 Node** control_ptr = builder_->control_; |
141 Node* before = *effect_ptr; | 147 Node* before = *effect_ptr; |
142 BranchHint hint = iftrue ? BranchHint::kFalse : BranchHint::kTrue; | 148 BranchHint hint = iftrue ? BranchHint::kFalse : BranchHint::kTrue; |
143 Node* branch = graph()->NewNode(common()->Branch(hint), cond, *control_ptr); | 149 Node* branch = graph()->NewNode(common()->Branch(hint), cond, *control_ptr); |
144 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 150 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
145 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 151 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
146 | 152 |
147 *control_ptr = iftrue ? if_true : if_false; | 153 *control_ptr = iftrue ? if_true : if_false; |
148 ConnectTrap(reason); | 154 ConnectTrap(reason, position); |
149 *control_ptr = iftrue ? if_false : if_true; | 155 *control_ptr = iftrue ? if_false : if_true; |
150 *effect_ptr = before; | 156 *effect_ptr = before; |
151 } | 157 } |
152 | 158 |
153 Node* GetTrapValue(wasm::FunctionSig* sig) { | 159 Node* GetTrapValue(wasm::FunctionSig* sig) { |
154 if (sig->return_count() > 0) { | 160 if (sig->return_count() > 0) { |
155 switch (sig->GetReturn()) { | 161 switch (sig->GetReturn()) { |
156 case wasm::kAstI32: | 162 case wasm::kAstI32: |
157 return jsgraph()->Int32Constant(0xdeadbeef); | 163 return jsgraph()->Int32Constant(0xdeadbeef); |
158 case wasm::kAstI64: | 164 case wasm::kAstI64: |
(...skipping 10 matching lines...) Expand all Loading... | |
169 } | 175 } |
170 } else { | 176 } else { |
171 return jsgraph()->Int32Constant(0xdeadbeef); | 177 return jsgraph()->Int32Constant(0xdeadbeef); |
172 } | 178 } |
173 } | 179 } |
174 | 180 |
175 private: | 181 private: |
176 WasmGraphBuilder* builder_; | 182 WasmGraphBuilder* builder_; |
177 JSGraph* jsgraph_; | 183 JSGraph* jsgraph_; |
178 Graph* graph_; | 184 Graph* graph_; |
179 Node* traps_[wasm::kTrapCount]; | 185 Node* trap_merge_ = nullptr; |
180 Node* effects_[wasm::kTrapCount]; | 186 Node* trap_effect_; |
187 Node* trap_reason_; | |
188 Node* trap_position_; | |
181 | 189 |
182 JSGraph* jsgraph() { return jsgraph_; } | 190 JSGraph* jsgraph() { return jsgraph_; } |
183 Graph* graph() { return jsgraph_->graph(); } | 191 Graph* graph() { return jsgraph_->graph(); } |
184 CommonOperatorBuilder* common() { return jsgraph()->common(); } | 192 CommonOperatorBuilder* common() { return jsgraph()->common(); } |
185 | 193 |
186 void ConnectTrap(wasm::TrapReason reason) { | 194 void ConnectTrap(wasm::TrapReason reason, int position) { |
187 if (traps_[reason] == nullptr) { | 195 DCHECK(position >= 0); |
196 Node* reason_node = builder_->Int32Constant( | |
197 wasm::WasmOpcodes::TrapReasonToMessageId(reason)); | |
198 Node* position_node = builder_->Int32Constant(position); | |
199 if (trap_merge_ == nullptr) { | |
188 // Create trap code for the first time this trap is used. | 200 // Create trap code for the first time this trap is used. |
titzer
2016/04/28 11:27:00
Update comment: s/this trap is used//
Clemens Hammacher
2016/04/28 12:43:28
Done.
| |
189 return BuildTrapCode(reason); | 201 return BuildTrapCode(reason_node, position_node); |
190 } | 202 } |
191 // Connect the current control and effect to the existing trap code. | 203 // Connect the current control and effect to the existing trap code. |
192 builder_->AppendToMerge(traps_[reason], builder_->Control()); | 204 builder_->AppendToMerge(trap_merge_, builder_->Control()); |
193 builder_->AppendToPhi(traps_[reason], effects_[reason], builder_->Effect()); | 205 builder_->AppendToPhi(trap_effect_, builder_->Effect()); |
206 builder_->AppendToPhi(trap_reason_, reason_node); | |
207 builder_->AppendToPhi(trap_position_, position_node); | |
194 } | 208 } |
195 | 209 |
196 void BuildTrapCode(wasm::TrapReason reason) { | 210 void BuildTrapCode(Node* reason_node, Node* position_node) { |
197 Node* message_id = builder_->NumberConstant( | |
198 wasm::WasmOpcodes::TrapReasonToMessageId(reason)); | |
199 Node* end; | 211 Node* end; |
200 Node** control_ptr = builder_->control_; | 212 Node** control_ptr = builder_->control_; |
201 Node** effect_ptr = builder_->effect_; | 213 Node** effect_ptr = builder_->effect_; |
202 wasm::ModuleEnv* module = builder_->module_; | 214 wasm::ModuleEnv* module = builder_->module_; |
203 DCHECK(traps_[reason] == NULL); | 215 DCHECK(trap_merge_ == NULL); |
204 *control_ptr = traps_[reason] = | 216 *control_ptr = trap_merge_ = |
205 graph()->NewNode(common()->Merge(1), *control_ptr); | 217 graph()->NewNode(common()->Merge(1), *control_ptr); |
206 *effect_ptr = effects_[reason] = | 218 *effect_ptr = trap_effect_ = |
207 graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr); | 219 graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr); |
220 trap_reason_ = | |
221 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1), | |
222 reason_node, *control_ptr); | |
223 trap_position_ = | |
224 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1), | |
225 position_node, *control_ptr); | |
226 | |
227 Node* trap_reason_smi = builder_->BuildChangeInt32ToSmi(trap_reason_); | |
228 Node* trap_position_smi = builder_->BuildChangeInt32ToSmi(trap_position_); | |
208 | 229 |
209 if (module && !module->instance->context.is_null()) { | 230 if (module && !module->instance->context.is_null()) { |
210 // Use the module context to call the runtime to throw an exception. | 231 // Use the module context to call the runtime to throw an exception. |
211 Runtime::FunctionId f = Runtime::kThrowWasmError; | 232 Runtime::FunctionId f = Runtime::kThrowWasmError; |
212 const Runtime::Function* fun = Runtime::FunctionForId(f); | 233 const Runtime::Function* fun = Runtime::FunctionForId(f); |
213 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( | 234 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( |
214 jsgraph()->zone(), f, fun->nargs, Operator::kNoProperties, | 235 jsgraph()->zone(), f, fun->nargs, Operator::kNoProperties, |
215 CallDescriptor::kNoFlags); | 236 CallDescriptor::kNoFlags); |
216 Node* inputs[] = { | 237 Node* inputs[] = { |
217 jsgraph()->CEntryStubConstant(fun->result_size), // C entry | 238 jsgraph()->CEntryStubConstant(fun->result_size), // C entry |
218 message_id, // message id | 239 trap_reason_smi, // message id |
240 trap_position_smi, // byte position | |
219 jsgraph()->ExternalConstant( | 241 jsgraph()->ExternalConstant( |
220 ExternalReference(f, jsgraph()->isolate())), // ref | 242 ExternalReference(f, jsgraph()->isolate())), // ref |
221 jsgraph()->Int32Constant(fun->nargs), // arity | 243 jsgraph()->Int32Constant(fun->nargs), // arity |
222 jsgraph()->Constant(module->instance->context), // context | 244 jsgraph()->Constant(module->instance->context), // context |
223 *effect_ptr, | 245 *effect_ptr, |
224 *control_ptr}; | 246 *control_ptr}; |
225 | 247 |
226 Node* node = graph()->NewNode( | 248 Node* node = graph()->NewNode( |
227 common()->Call(desc), static_cast<int>(arraysize(inputs)), inputs); | 249 common()->Call(desc), static_cast<int>(arraysize(inputs)), inputs); |
228 *control_ptr = node; | 250 *control_ptr = node; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
306 | 328 |
307 | 329 |
308 void WasmGraphBuilder::AppendToMerge(Node* merge, Node* from) { | 330 void WasmGraphBuilder::AppendToMerge(Node* merge, Node* from) { |
309 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); | 331 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); |
310 merge->AppendInput(jsgraph()->zone(), from); | 332 merge->AppendInput(jsgraph()->zone(), from); |
311 int new_size = merge->InputCount(); | 333 int new_size = merge->InputCount(); |
312 NodeProperties::ChangeOp( | 334 NodeProperties::ChangeOp( |
313 merge, jsgraph()->common()->ResizeMergeOrPhi(merge->op(), new_size)); | 335 merge, jsgraph()->common()->ResizeMergeOrPhi(merge->op(), new_size)); |
314 } | 336 } |
315 | 337 |
316 | 338 void WasmGraphBuilder::AppendToPhi(Node* phi, Node* from) { |
317 void WasmGraphBuilder::AppendToPhi(Node* merge, Node* phi, Node* from) { | |
318 DCHECK(IrOpcode::IsPhiOpcode(phi->opcode())); | 339 DCHECK(IrOpcode::IsPhiOpcode(phi->opcode())); |
319 DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); | |
320 int new_size = phi->InputCount(); | 340 int new_size = phi->InputCount(); |
321 phi->InsertInput(jsgraph()->zone(), phi->InputCount() - 1, from); | 341 phi->InsertInput(jsgraph()->zone(), phi->InputCount() - 1, from); |
322 NodeProperties::ChangeOp( | 342 NodeProperties::ChangeOp( |
323 phi, jsgraph()->common()->ResizeMergeOrPhi(phi->op(), new_size)); | 343 phi, jsgraph()->common()->ResizeMergeOrPhi(phi->op(), new_size)); |
324 } | 344 } |
325 | 345 |
326 | 346 |
327 Node* WasmGraphBuilder::Merge(unsigned count, Node** controls) { | 347 Node* WasmGraphBuilder::Merge(unsigned count, Node** controls) { |
328 return graph()->NewNode(jsgraph()->common()->Merge(count), count, controls); | 348 return graph()->NewNode(jsgraph()->common()->Merge(count), count, controls); |
329 } | 349 } |
(...skipping 24 matching lines...) Expand all Loading... | |
354 | 374 |
355 Node* WasmGraphBuilder::Int32Constant(int32_t value) { | 375 Node* WasmGraphBuilder::Int32Constant(int32_t value) { |
356 return jsgraph()->Int32Constant(value); | 376 return jsgraph()->Int32Constant(value); |
357 } | 377 } |
358 | 378 |
359 | 379 |
360 Node* WasmGraphBuilder::Int64Constant(int64_t value) { | 380 Node* WasmGraphBuilder::Int64Constant(int64_t value) { |
361 return jsgraph()->Int64Constant(value); | 381 return jsgraph()->Int64Constant(value); |
362 } | 382 } |
363 | 383 |
364 | 384 Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right, |
365 Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, | 385 int position) { |
366 Node* right) { | |
367 const Operator* op; | 386 const Operator* op; |
368 MachineOperatorBuilder* m = jsgraph()->machine(); | 387 MachineOperatorBuilder* m = jsgraph()->machine(); |
369 switch (opcode) { | 388 switch (opcode) { |
370 case wasm::kExprI32Add: | 389 case wasm::kExprI32Add: |
371 op = m->Int32Add(); | 390 op = m->Int32Add(); |
372 break; | 391 break; |
373 case wasm::kExprI32Sub: | 392 case wasm::kExprI32Sub: |
374 op = m->Int32Sub(); | 393 op = m->Int32Sub(); |
375 break; | 394 break; |
376 case wasm::kExprI32Mul: | 395 case wasm::kExprI32Mul: |
377 op = m->Int32Mul(); | 396 op = m->Int32Mul(); |
378 break; | 397 break; |
379 case wasm::kExprI32DivS: | 398 case wasm::kExprI32DivS: |
380 return BuildI32DivS(left, right); | 399 return BuildI32DivS(left, right, position); |
381 case wasm::kExprI32DivU: | 400 case wasm::kExprI32DivU: |
382 return BuildI32DivU(left, right); | 401 return BuildI32DivU(left, right, position); |
383 case wasm::kExprI32RemS: | 402 case wasm::kExprI32RemS: |
384 return BuildI32RemS(left, right); | 403 return BuildI32RemS(left, right, position); |
385 case wasm::kExprI32RemU: | 404 case wasm::kExprI32RemU: |
386 return BuildI32RemU(left, right); | 405 return BuildI32RemU(left, right, position); |
387 case wasm::kExprI32And: | 406 case wasm::kExprI32And: |
388 op = m->Word32And(); | 407 op = m->Word32And(); |
389 break; | 408 break; |
390 case wasm::kExprI32Ior: | 409 case wasm::kExprI32Ior: |
391 op = m->Word32Or(); | 410 op = m->Word32Or(); |
392 break; | 411 break; |
393 case wasm::kExprI32Xor: | 412 case wasm::kExprI32Xor: |
394 op = m->Word32Xor(); | 413 op = m->Word32Xor(); |
395 break; | 414 break; |
396 case wasm::kExprI32Shl: | 415 case wasm::kExprI32Shl: |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
457 // kExprI64Sub: | 476 // kExprI64Sub: |
458 case wasm::kExprI64Sub: | 477 case wasm::kExprI64Sub: |
459 op = m->Int64Sub(); | 478 op = m->Int64Sub(); |
460 break; | 479 break; |
461 // kExprI64Mul: | 480 // kExprI64Mul: |
462 case wasm::kExprI64Mul: | 481 case wasm::kExprI64Mul: |
463 op = m->Int64Mul(); | 482 op = m->Int64Mul(); |
464 break; | 483 break; |
465 // kExprI64DivS: | 484 // kExprI64DivS: |
466 case wasm::kExprI64DivS: | 485 case wasm::kExprI64DivS: |
467 return BuildI64DivS(left, right); | 486 return BuildI64DivS(left, right, position); |
468 // kExprI64DivU: | 487 // kExprI64DivU: |
469 case wasm::kExprI64DivU: | 488 case wasm::kExprI64DivU: |
470 return BuildI64DivU(left, right); | 489 return BuildI64DivU(left, right, position); |
471 // kExprI64RemS: | 490 // kExprI64RemS: |
472 case wasm::kExprI64RemS: | 491 case wasm::kExprI64RemS: |
473 return BuildI64RemS(left, right); | 492 return BuildI64RemS(left, right, position); |
474 // kExprI64RemU: | 493 // kExprI64RemU: |
475 case wasm::kExprI64RemU: | 494 case wasm::kExprI64RemU: |
476 return BuildI64RemU(left, right); | 495 return BuildI64RemU(left, right, position); |
477 case wasm::kExprI64Ior: | 496 case wasm::kExprI64Ior: |
478 op = m->Word64Or(); | 497 op = m->Word64Or(); |
479 break; | 498 break; |
480 // kExprI64Xor: | 499 // kExprI64Xor: |
481 case wasm::kExprI64Xor: | 500 case wasm::kExprI64Xor: |
482 op = m->Word64Xor(); | 501 op = m->Word64Xor(); |
483 break; | 502 break; |
484 // kExprI64Shl: | 503 // kExprI64Shl: |
485 case wasm::kExprI64Shl: | 504 case wasm::kExprI64Shl: |
486 op = m->Word64Shl(); | 505 op = m->Word64Shl(); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
620 } | 639 } |
621 case wasm::kExprF64Mod: { | 640 case wasm::kExprF64Mod: { |
622 return BuildF64Mod(left, right); | 641 return BuildF64Mod(left, right); |
623 } | 642 } |
624 default: | 643 default: |
625 op = UnsupportedOpcode(opcode); | 644 op = UnsupportedOpcode(opcode); |
626 } | 645 } |
627 return graph()->NewNode(op, left, right); | 646 return graph()->NewNode(op, left, right); |
628 } | 647 } |
629 | 648 |
630 | 649 Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input, |
631 Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) { | 650 int position) { |
632 const Operator* op; | 651 const Operator* op; |
633 MachineOperatorBuilder* m = jsgraph()->machine(); | 652 MachineOperatorBuilder* m = jsgraph()->machine(); |
634 switch (opcode) { | 653 switch (opcode) { |
635 case wasm::kExprI32Eqz: | 654 case wasm::kExprI32Eqz: |
636 op = m->Word32Equal(); | 655 op = m->Word32Equal(); |
637 return graph()->NewNode(op, input, jsgraph()->Int32Constant(0)); | 656 return graph()->NewNode(op, input, jsgraph()->Int32Constant(0)); |
638 case wasm::kExprF32Abs: | 657 case wasm::kExprF32Abs: |
639 op = m->Float32Abs(); | 658 op = m->Float32Abs(); |
640 break; | 659 break; |
641 case wasm::kExprF32Neg: | 660 case wasm::kExprF32Neg: |
642 return BuildF32Neg(input); | 661 return BuildF32Neg(input); |
643 case wasm::kExprF32Sqrt: | 662 case wasm::kExprF32Sqrt: |
644 op = m->Float32Sqrt(); | 663 op = m->Float32Sqrt(); |
645 break; | 664 break; |
646 case wasm::kExprF64Abs: | 665 case wasm::kExprF64Abs: |
647 op = m->Float64Abs(); | 666 op = m->Float64Abs(); |
648 break; | 667 break; |
649 case wasm::kExprF64Neg: | 668 case wasm::kExprF64Neg: |
650 return BuildF64Neg(input); | 669 return BuildF64Neg(input); |
651 case wasm::kExprF64Sqrt: | 670 case wasm::kExprF64Sqrt: |
652 op = m->Float64Sqrt(); | 671 op = m->Float64Sqrt(); |
653 break; | 672 break; |
654 case wasm::kExprI32SConvertF64: | 673 case wasm::kExprI32SConvertF64: |
655 return BuildI32SConvertF64(input); | 674 return BuildI32SConvertF64(input, position); |
656 case wasm::kExprI32UConvertF64: | 675 case wasm::kExprI32UConvertF64: |
657 return BuildI32UConvertF64(input); | 676 return BuildI32UConvertF64(input, position); |
658 case wasm::kExprF32ConvertF64: | 677 case wasm::kExprF32ConvertF64: |
659 op = m->TruncateFloat64ToFloat32(); | 678 op = m->TruncateFloat64ToFloat32(); |
660 break; | 679 break; |
661 case wasm::kExprF64SConvertI32: | 680 case wasm::kExprF64SConvertI32: |
662 op = m->ChangeInt32ToFloat64(); | 681 op = m->ChangeInt32ToFloat64(); |
663 break; | 682 break; |
664 case wasm::kExprF64UConvertI32: | 683 case wasm::kExprF64UConvertI32: |
665 op = m->ChangeUint32ToFloat64(); | 684 op = m->ChangeUint32ToFloat64(); |
666 break; | 685 break; |
667 case wasm::kExprF32SConvertI32: | 686 case wasm::kExprF32SConvertI32: |
668 op = m->RoundInt32ToFloat32(); | 687 op = m->RoundInt32ToFloat32(); |
669 break; | 688 break; |
670 case wasm::kExprF32UConvertI32: | 689 case wasm::kExprF32UConvertI32: |
671 op = m->RoundUint32ToFloat32(); | 690 op = m->RoundUint32ToFloat32(); |
672 break; | 691 break; |
673 case wasm::kExprI32SConvertF32: | 692 case wasm::kExprI32SConvertF32: |
674 return BuildI32SConvertF32(input); | 693 return BuildI32SConvertF32(input, position); |
675 case wasm::kExprI32UConvertF32: | 694 case wasm::kExprI32UConvertF32: |
676 return BuildI32UConvertF32(input); | 695 return BuildI32UConvertF32(input, position); |
677 case wasm::kExprF64ConvertF32: | 696 case wasm::kExprF64ConvertF32: |
678 op = m->ChangeFloat32ToFloat64(); | 697 op = m->ChangeFloat32ToFloat64(); |
679 break; | 698 break; |
680 case wasm::kExprF32ReinterpretI32: | 699 case wasm::kExprF32ReinterpretI32: |
681 op = m->BitcastInt32ToFloat32(); | 700 op = m->BitcastInt32ToFloat32(); |
682 break; | 701 break; |
683 case wasm::kExprI32ReinterpretF32: | 702 case wasm::kExprI32ReinterpretF32: |
684 op = m->BitcastFloat32ToInt32(); | 703 op = m->BitcastFloat32ToInt32(); |
685 break; | 704 break; |
686 case wasm::kExprI32Clz: | 705 case wasm::kExprI32Clz: |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
849 break; | 868 break; |
850 // kExprF64UConvertI64: | 869 // kExprF64UConvertI64: |
851 case wasm::kExprF64UConvertI64: | 870 case wasm::kExprF64UConvertI64: |
852 if (m->Is32()) { | 871 if (m->Is32()) { |
853 return BuildF64UConvertI64(input); | 872 return BuildF64UConvertI64(input); |
854 } | 873 } |
855 op = m->RoundUint64ToFloat64(); | 874 op = m->RoundUint64ToFloat64(); |
856 break; | 875 break; |
857 // kExprI64SConvertF32: | 876 // kExprI64SConvertF32: |
858 case wasm::kExprI64SConvertF32: { | 877 case wasm::kExprI64SConvertF32: { |
859 return BuildI64SConvertF32(input); | 878 return BuildI64SConvertF32(input, position); |
860 } | 879 } |
861 // kExprI64SConvertF64: | 880 // kExprI64SConvertF64: |
862 case wasm::kExprI64SConvertF64: { | 881 case wasm::kExprI64SConvertF64: { |
863 return BuildI64SConvertF64(input); | 882 return BuildI64SConvertF64(input, position); |
864 } | 883 } |
865 // kExprI64UConvertF32: | 884 // kExprI64UConvertF32: |
866 case wasm::kExprI64UConvertF32: { | 885 case wasm::kExprI64UConvertF32: { |
867 return BuildI64UConvertF32(input); | 886 return BuildI64UConvertF32(input, position); |
868 } | 887 } |
869 // kExprI64UConvertF64: | 888 // kExprI64UConvertF64: |
870 case wasm::kExprI64UConvertF64: { | 889 case wasm::kExprI64UConvertF64: { |
871 return BuildI64UConvertF64(input); | 890 return BuildI64UConvertF64(input, position); |
872 } | 891 } |
873 default: | 892 default: |
874 op = UnsupportedOpcode(opcode); | 893 op = UnsupportedOpcode(opcode); |
875 } | 894 } |
876 return graph()->NewNode(op, input); | 895 return graph()->NewNode(op, input); |
877 } | 896 } |
878 | 897 |
879 | 898 |
880 Node* WasmGraphBuilder::Float32Constant(float value) { | 899 Node* WasmGraphBuilder::Float32Constant(float value) { |
881 return jsgraph()->Float32Constant(value); | 900 return jsgraph()->Float32Constant(value); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
936 buf[count + 1] = *control_; | 955 buf[count + 1] = *control_; |
937 Node* ret = graph()->NewNode(jsgraph()->common()->Return(), count + 2, vals); | 956 Node* ret = graph()->NewNode(jsgraph()->common()->Return(), count + 2, vals); |
938 | 957 |
939 MergeControlToEnd(jsgraph(), ret); | 958 MergeControlToEnd(jsgraph(), ret); |
940 return ret; | 959 return ret; |
941 } | 960 } |
942 | 961 |
943 | 962 |
944 Node* WasmGraphBuilder::ReturnVoid() { return Return(0, Buffer(0)); } | 963 Node* WasmGraphBuilder::ReturnVoid() { return Return(0, Buffer(0)); } |
945 | 964 |
946 | 965 Node* WasmGraphBuilder::Unreachable(int position) { |
947 Node* WasmGraphBuilder::Unreachable() { | 966 trap_->Unreachable(position); |
948 trap_->Unreachable(); | |
949 return nullptr; | 967 return nullptr; |
950 } | 968 } |
951 | 969 |
952 Node* WasmGraphBuilder::MaskShiftCount32(Node* node) { | 970 Node* WasmGraphBuilder::MaskShiftCount32(Node* node) { |
953 static const int32_t kMask32 = 0x1f; | 971 static const int32_t kMask32 = 0x1f; |
954 if (!jsgraph()->machine()->Word32ShiftIsSafe()) { | 972 if (!jsgraph()->machine()->Word32ShiftIsSafe()) { |
955 // Shifts by constants are so common we pattern-match them here. | 973 // Shifts by constants are so common we pattern-match them here. |
956 Int32Matcher match(node); | 974 Int32Matcher match(node); |
957 if (match.HasValue()) { | 975 if (match.HasValue()) { |
958 int32_t masked = (match.Value() & kMask32); | 976 int32_t masked = (match.Value() & kMask32); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1129 return left_ge_right.Phi( | 1147 return left_ge_right.Phi( |
1130 wasm::kAstF64, left, | 1148 wasm::kAstF64, left, |
1131 right_gt_left.Phi( | 1149 right_gt_left.Phi( |
1132 wasm::kAstF64, right, | 1150 wasm::kAstF64, right, |
1133 left_is_not_nan.Phi( | 1151 left_is_not_nan.Phi( |
1134 wasm::kAstF64, | 1152 wasm::kAstF64, |
1135 Binop(wasm::kExprF64Mul, right, Float64Constant(1.0)), | 1153 Binop(wasm::kExprF64Mul, right, Float64Constant(1.0)), |
1136 Binop(wasm::kExprF64Mul, left, Float64Constant(1.0))))); | 1154 Binop(wasm::kExprF64Mul, left, Float64Constant(1.0))))); |
1137 } | 1155 } |
1138 | 1156 |
1139 | 1157 Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input, int position) { |
1140 Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input) { | |
1141 MachineOperatorBuilder* m = jsgraph()->machine(); | 1158 MachineOperatorBuilder* m = jsgraph()->machine(); |
1142 if (module_ && module_->asm_js()) { | 1159 if (module_ && module_->asm_js()) { |
1143 // asm.js must use the wacky JS semantics. | 1160 // asm.js must use the wacky JS semantics. |
1144 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); | 1161 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); |
1145 return graph()->NewNode(m->TruncateFloat64ToWord32(), input); | 1162 return graph()->NewNode(m->TruncateFloat64ToWord32(), input); |
1146 } | 1163 } |
1147 | 1164 |
1148 // Truncation of the input value is needed for the overflow check later. | 1165 // Truncation of the input value is needed for the overflow check later. |
1149 Node* trunc = Unop(wasm::kExprF32Trunc, input); | 1166 Node* trunc = Unop(wasm::kExprF32Trunc, input); |
1150 Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc); | 1167 Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc); |
1151 | 1168 |
1152 // Convert the result back to f64. If we end up at a different value than the | 1169 // Convert the result back to f64. If we end up at a different value than the |
1153 // truncated input value, then there has been an overflow and we trap. | 1170 // truncated input value, then there has been an overflow and we trap. |
1154 Node* check = Unop(wasm::kExprF32SConvertI32, result); | 1171 Node* check = Unop(wasm::kExprF32SConvertI32, result); |
1155 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); | 1172 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); |
1156 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); | 1173 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position); |
1157 | 1174 |
1158 return result; | 1175 return result; |
1159 } | 1176 } |
1160 | 1177 |
1161 | 1178 Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input, int position) { |
1162 Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) { | |
1163 MachineOperatorBuilder* m = jsgraph()->machine(); | 1179 MachineOperatorBuilder* m = jsgraph()->machine(); |
1164 if (module_ && module_->asm_js()) { | 1180 if (module_ && module_->asm_js()) { |
1165 // asm.js must use the wacky JS semantics. | 1181 // asm.js must use the wacky JS semantics. |
1166 return graph()->NewNode(m->TruncateFloat64ToWord32(), input); | 1182 return graph()->NewNode(m->TruncateFloat64ToWord32(), input); |
1167 } | 1183 } |
1168 // Truncation of the input value is needed for the overflow check later. | 1184 // Truncation of the input value is needed for the overflow check later. |
1169 Node* trunc = Unop(wasm::kExprF64Trunc, input); | 1185 Node* trunc = Unop(wasm::kExprF64Trunc, input); |
1170 Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc); | 1186 Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc); |
1171 | 1187 |
1172 // Convert the result back to f64. If we end up at a different value than the | 1188 // Convert the result back to f64. If we end up at a different value than the |
1173 // truncated input value, then there has been an overflow and we trap. | 1189 // truncated input value, then there has been an overflow and we trap. |
1174 Node* check = Unop(wasm::kExprF64SConvertI32, result); | 1190 Node* check = Unop(wasm::kExprF64SConvertI32, result); |
1175 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); | 1191 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); |
1176 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); | 1192 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position); |
1177 | 1193 |
1178 return result; | 1194 return result; |
1179 } | 1195 } |
1180 | 1196 |
1181 | 1197 Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input, int position) { |
1182 Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input) { | |
1183 MachineOperatorBuilder* m = jsgraph()->machine(); | 1198 MachineOperatorBuilder* m = jsgraph()->machine(); |
1184 if (module_ && module_->asm_js()) { | 1199 if (module_ && module_->asm_js()) { |
1185 // asm.js must use the wacky JS semantics. | 1200 // asm.js must use the wacky JS semantics. |
1186 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); | 1201 input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input); |
1187 return graph()->NewNode(m->TruncateFloat64ToWord32(), input); | 1202 return graph()->NewNode(m->TruncateFloat64ToWord32(), input); |
1188 } | 1203 } |
1189 | 1204 |
1190 // Truncation of the input value is needed for the overflow check later. | 1205 // Truncation of the input value is needed for the overflow check later. |
1191 Node* trunc = Unop(wasm::kExprF32Trunc, input); | 1206 Node* trunc = Unop(wasm::kExprF32Trunc, input); |
1192 Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc); | 1207 Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc); |
1193 | 1208 |
1194 // Convert the result back to f32. If we end up at a different value than the | 1209 // Convert the result back to f32. If we end up at a different value than the |
1195 // truncated input value, then there has been an overflow and we trap. | 1210 // truncated input value, then there has been an overflow and we trap. |
1196 Node* check = Unop(wasm::kExprF32UConvertI32, result); | 1211 Node* check = Unop(wasm::kExprF32UConvertI32, result); |
1197 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); | 1212 Node* overflow = Binop(wasm::kExprF32Ne, trunc, check); |
1198 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); | 1213 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position); |
1199 | 1214 |
1200 return result; | 1215 return result; |
1201 } | 1216 } |
1202 | 1217 |
1203 | 1218 Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input, int position) { |
1204 Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) { | |
1205 MachineOperatorBuilder* m = jsgraph()->machine(); | 1219 MachineOperatorBuilder* m = jsgraph()->machine(); |
1206 if (module_ && module_->asm_js()) { | 1220 if (module_ && module_->asm_js()) { |
1207 // asm.js must use the wacky JS semantics. | 1221 // asm.js must use the wacky JS semantics. |
1208 return graph()->NewNode(m->TruncateFloat64ToWord32(), input); | 1222 return graph()->NewNode(m->TruncateFloat64ToWord32(), input); |
1209 } | 1223 } |
1210 // Truncation of the input value is needed for the overflow check later. | 1224 // Truncation of the input value is needed for the overflow check later. |
1211 Node* trunc = Unop(wasm::kExprF64Trunc, input); | 1225 Node* trunc = Unop(wasm::kExprF64Trunc, input); |
1212 Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc); | 1226 Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc); |
1213 | 1227 |
1214 // Convert the result back to f64. If we end up at a different value than the | 1228 // Convert the result back to f64. If we end up at a different value than the |
1215 // truncated input value, then there has been an overflow and we trap. | 1229 // truncated input value, then there has been an overflow and we trap. |
1216 Node* check = Unop(wasm::kExprF64UConvertI32, result); | 1230 Node* check = Unop(wasm::kExprF64UConvertI32, result); |
1217 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); | 1231 Node* overflow = Binop(wasm::kExprF64Ne, trunc, check); |
1218 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow); | 1232 trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position); |
1219 | 1233 |
1220 return result; | 1234 return result; |
1221 } | 1235 } |
1222 | 1236 |
1223 Node* WasmGraphBuilder::BuildBitCountingCall(Node* input, ExternalReference ref, | 1237 Node* WasmGraphBuilder::BuildBitCountingCall(Node* input, ExternalReference ref, |
1224 MachineRepresentation input_type) { | 1238 MachineRepresentation input_type) { |
1225 Node* stack_slot_param = | 1239 Node* stack_slot_param = |
1226 graph()->NewNode(jsgraph()->machine()->StackSlot(input_type)); | 1240 graph()->NewNode(jsgraph()->machine()->StackSlot(input_type)); |
1227 | 1241 |
1228 const Operator* store_op = jsgraph()->machine()->Store( | 1242 const Operator* store_op = jsgraph()->machine()->Store( |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1499 Node* args[] = {function, stack_slot_param, stack_slot_result}; | 1513 Node* args[] = {function, stack_slot_param, stack_slot_result}; |
1500 BuildCCall(sig_builder.Build(), args); | 1514 BuildCCall(sig_builder.Build(), args); |
1501 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1515 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
1502 Node* load = | 1516 Node* load = |
1503 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), | 1517 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), |
1504 *effect_, *control_); | 1518 *effect_, *control_); |
1505 *effect_ = load; | 1519 *effect_ = load; |
1506 return load; | 1520 return load; |
1507 } | 1521 } |
1508 | 1522 |
1509 Node* WasmGraphBuilder::BuildI64SConvertF32(Node* input) { | 1523 Node* WasmGraphBuilder::BuildI64SConvertF32(Node* input, int position) { |
1510 if (jsgraph()->machine()->Is32()) { | 1524 if (jsgraph()->machine()->Is32()) { |
1511 return BuildFloatToIntConversionInstruction( | 1525 return BuildFloatToIntConversionInstruction( |
1512 input, ExternalReference::wasm_float32_to_int64(jsgraph()->isolate()), | 1526 input, ExternalReference::wasm_float32_to_int64(jsgraph()->isolate()), |
1513 MachineRepresentation::kFloat32, MachineType::Int64()); | 1527 MachineRepresentation::kFloat32, MachineType::Int64(), position); |
1514 } else { | 1528 } else { |
1515 Node* trunc = graph()->NewNode( | 1529 Node* trunc = graph()->NewNode( |
1516 jsgraph()->machine()->TryTruncateFloat32ToInt64(), input); | 1530 jsgraph()->machine()->TryTruncateFloat32ToInt64(), input); |
1517 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1531 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
1518 Node* overflow = | 1532 Node* overflow = |
1519 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1533 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
1520 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); | 1534 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position); |
1521 return result; | 1535 return result; |
1522 } | 1536 } |
1523 } | 1537 } |
1524 | 1538 |
1525 Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input) { | 1539 Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input, int position) { |
1526 if (jsgraph()->machine()->Is32()) { | 1540 if (jsgraph()->machine()->Is32()) { |
1527 return BuildFloatToIntConversionInstruction( | 1541 return BuildFloatToIntConversionInstruction( |
1528 input, ExternalReference::wasm_float32_to_uint64(jsgraph()->isolate()), | 1542 input, ExternalReference::wasm_float32_to_uint64(jsgraph()->isolate()), |
1529 MachineRepresentation::kFloat32, MachineType::Int64()); | 1543 MachineRepresentation::kFloat32, MachineType::Int64(), position); |
1530 } else { | 1544 } else { |
1531 Node* trunc = graph()->NewNode( | 1545 Node* trunc = graph()->NewNode( |
1532 jsgraph()->machine()->TryTruncateFloat32ToUint64(), input); | 1546 jsgraph()->machine()->TryTruncateFloat32ToUint64(), input); |
1533 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1547 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
1534 Node* overflow = | 1548 Node* overflow = |
1535 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1549 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
1536 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); | 1550 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position); |
1537 return result; | 1551 return result; |
1538 } | 1552 } |
1539 } | 1553 } |
1540 | 1554 |
1541 Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input) { | 1555 Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input, int position) { |
1542 if (jsgraph()->machine()->Is32()) { | 1556 if (jsgraph()->machine()->Is32()) { |
1543 return BuildFloatToIntConversionInstruction( | 1557 return BuildFloatToIntConversionInstruction( |
1544 input, ExternalReference::wasm_float64_to_int64(jsgraph()->isolate()), | 1558 input, ExternalReference::wasm_float64_to_int64(jsgraph()->isolate()), |
1545 MachineRepresentation::kFloat64, MachineType::Int64()); | 1559 MachineRepresentation::kFloat64, MachineType::Int64(), position); |
1546 } else { | 1560 } else { |
1547 Node* trunc = graph()->NewNode( | 1561 Node* trunc = graph()->NewNode( |
1548 jsgraph()->machine()->TryTruncateFloat64ToInt64(), input); | 1562 jsgraph()->machine()->TryTruncateFloat64ToInt64(), input); |
1549 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1563 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
1550 Node* overflow = | 1564 Node* overflow = |
1551 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1565 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
1552 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); | 1566 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position); |
1553 return result; | 1567 return result; |
1554 } | 1568 } |
1555 } | 1569 } |
1556 | 1570 |
1557 Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input) { | 1571 Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input, int position) { |
1558 if (jsgraph()->machine()->Is32()) { | 1572 if (jsgraph()->machine()->Is32()) { |
1559 return BuildFloatToIntConversionInstruction( | 1573 return BuildFloatToIntConversionInstruction( |
1560 input, ExternalReference::wasm_float64_to_uint64(jsgraph()->isolate()), | 1574 input, ExternalReference::wasm_float64_to_uint64(jsgraph()->isolate()), |
1561 MachineRepresentation::kFloat64, MachineType::Int64()); | 1575 MachineRepresentation::kFloat64, MachineType::Int64(), position); |
1562 } else { | 1576 } else { |
1563 Node* trunc = graph()->NewNode( | 1577 Node* trunc = graph()->NewNode( |
1564 jsgraph()->machine()->TryTruncateFloat64ToUint64(), input); | 1578 jsgraph()->machine()->TryTruncateFloat64ToUint64(), input); |
1565 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); | 1579 Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); |
1566 Node* overflow = | 1580 Node* overflow = |
1567 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); | 1581 graph()->NewNode(jsgraph()->common()->Projection(1), trunc); |
1568 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow); | 1582 trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position); |
1569 return result; | 1583 return result; |
1570 } | 1584 } |
1571 } | 1585 } |
1572 | 1586 |
1573 Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction( | 1587 Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction( |
1574 Node* input, ExternalReference ref, | 1588 Node* input, ExternalReference ref, |
1575 MachineRepresentation parameter_representation, | 1589 MachineRepresentation parameter_representation, |
1576 const MachineType result_type) { | 1590 const MachineType result_type, int position) { |
1577 Node* stack_slot_param = graph()->NewNode( | 1591 Node* stack_slot_param = graph()->NewNode( |
1578 jsgraph()->machine()->StackSlot(parameter_representation)); | 1592 jsgraph()->machine()->StackSlot(parameter_representation)); |
1579 Node* stack_slot_result = graph()->NewNode( | 1593 Node* stack_slot_result = graph()->NewNode( |
1580 jsgraph()->machine()->StackSlot(result_type.representation())); | 1594 jsgraph()->machine()->StackSlot(result_type.representation())); |
1581 const Operator* store_op = jsgraph()->machine()->Store( | 1595 const Operator* store_op = jsgraph()->machine()->Store( |
1582 StoreRepresentation(parameter_representation, kNoWriteBarrier)); | 1596 StoreRepresentation(parameter_representation, kNoWriteBarrier)); |
1583 *effect_ = | 1597 *effect_ = |
1584 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), | 1598 graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0), |
1585 input, *effect_, *control_); | 1599 input, *effect_, *control_); |
1586 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); | 1600 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); |
1587 sig_builder.AddReturn(MachineType::Int32()); | 1601 sig_builder.AddReturn(MachineType::Int32()); |
1588 sig_builder.AddParam(MachineType::Pointer()); | 1602 sig_builder.AddParam(MachineType::Pointer()); |
1589 sig_builder.AddParam(MachineType::Pointer()); | 1603 sig_builder.AddParam(MachineType::Pointer()); |
1590 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); | 1604 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
1591 Node* args[] = {function, stack_slot_param, stack_slot_result}; | 1605 Node* args[] = {function, stack_slot_param, stack_slot_result}; |
1592 trap_->ZeroCheck32(wasm::kTrapFloatUnrepresentable, | 1606 trap_->ZeroCheck32(wasm::kTrapFloatUnrepresentable, |
1593 BuildCCall(sig_builder.Build(), args)); | 1607 BuildCCall(sig_builder.Build(), args), position); |
1594 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1608 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
1595 Node* load = | 1609 Node* load = |
1596 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), | 1610 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), |
1597 *effect_, *control_); | 1611 *effect_, *control_); |
1598 *effect_ = load; | 1612 *effect_ = load; |
1599 return load; | 1613 return load; |
1600 } | 1614 } |
1601 | 1615 |
1602 Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right) { | 1616 Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right, int position) { |
1603 MachineOperatorBuilder* m = jsgraph()->machine(); | 1617 MachineOperatorBuilder* m = jsgraph()->machine(); |
1604 if (module_ && module_->asm_js()) { | 1618 if (module_ && module_->asm_js()) { |
1605 // asm.js semantics return 0 on divide or mod by zero. | 1619 // asm.js semantics return 0 on divide or mod by zero. |
1606 if (m->Int32DivIsSafe()) { | 1620 if (m->Int32DivIsSafe()) { |
1607 // The hardware instruction does the right thing (e.g. arm). | 1621 // The hardware instruction does the right thing (e.g. arm). |
1608 return graph()->NewNode(m->Int32Div(), left, right, graph()->start()); | 1622 return graph()->NewNode(m->Int32Div(), left, right, graph()->start()); |
1609 } | 1623 } |
1610 | 1624 |
1611 // Check denominator for zero. | 1625 // Check denominator for zero. |
1612 Diamond z( | 1626 Diamond z( |
1613 graph(), jsgraph()->common(), | 1627 graph(), jsgraph()->common(), |
1614 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | 1628 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
1615 BranchHint::kFalse); | 1629 BranchHint::kFalse); |
1616 | 1630 |
1617 // Check numerator for -1. (avoid minint / -1 case). | 1631 // Check numerator for -1. (avoid minint / -1 case). |
1618 Diamond n( | 1632 Diamond n( |
1619 graph(), jsgraph()->common(), | 1633 graph(), jsgraph()->common(), |
1620 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1634 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
1621 BranchHint::kFalse); | 1635 BranchHint::kFalse); |
1622 | 1636 |
1623 Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false); | 1637 Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false); |
1624 Node* neg = | 1638 Node* neg = |
1625 graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left); | 1639 graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left); |
1626 | 1640 |
1627 return n.Phi(MachineRepresentation::kWord32, neg, | 1641 return n.Phi(MachineRepresentation::kWord32, neg, |
1628 z.Phi(MachineRepresentation::kWord32, | 1642 z.Phi(MachineRepresentation::kWord32, |
1629 jsgraph()->Int32Constant(0), div)); | 1643 jsgraph()->Int32Constant(0), div)); |
1630 } | 1644 } |
1631 | 1645 |
1632 trap_->ZeroCheck32(wasm::kTrapDivByZero, right); | 1646 trap_->ZeroCheck32(wasm::kTrapDivByZero, right, position); |
1633 Node* before = *control_; | 1647 Node* before = *control_; |
1634 Node* denom_is_m1; | 1648 Node* denom_is_m1; |
1635 Node* denom_is_not_m1; | 1649 Node* denom_is_not_m1; |
1636 Branch( | 1650 Branch( |
1637 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1651 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
1638 &denom_is_m1, &denom_is_not_m1); | 1652 &denom_is_m1, &denom_is_not_m1); |
1639 *control_ = denom_is_m1; | 1653 *control_ = denom_is_m1; |
1640 trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt); | 1654 trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt, position); |
1641 if (*control_ != denom_is_m1) { | 1655 if (*control_ != denom_is_m1) { |
1642 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, | 1656 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, |
1643 *control_); | 1657 *control_); |
1644 } else { | 1658 } else { |
1645 *control_ = before; | 1659 *control_ = before; |
1646 } | 1660 } |
1647 return graph()->NewNode(m->Int32Div(), left, right, *control_); | 1661 return graph()->NewNode(m->Int32Div(), left, right, *control_); |
1648 } | 1662 } |
1649 | 1663 |
1650 Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right) { | 1664 Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right, int position) { |
1651 MachineOperatorBuilder* m = jsgraph()->machine(); | 1665 MachineOperatorBuilder* m = jsgraph()->machine(); |
1652 if (module_ && module_->asm_js()) { | 1666 if (module_ && module_->asm_js()) { |
1653 // asm.js semantics return 0 on divide or mod by zero. | 1667 // asm.js semantics return 0 on divide or mod by zero. |
1654 // Explicit check for x % 0. | 1668 // Explicit check for x % 0. |
1655 Diamond z( | 1669 Diamond z( |
1656 graph(), jsgraph()->common(), | 1670 graph(), jsgraph()->common(), |
1657 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | 1671 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
1658 BranchHint::kFalse); | 1672 BranchHint::kFalse); |
1659 | 1673 |
1660 // Explicit check for x % -1. | 1674 // Explicit check for x % -1. |
1661 Diamond d( | 1675 Diamond d( |
1662 graph(), jsgraph()->common(), | 1676 graph(), jsgraph()->common(), |
1663 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1677 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
1664 BranchHint::kFalse); | 1678 BranchHint::kFalse); |
1665 d.Chain(z.if_false); | 1679 d.Chain(z.if_false); |
1666 | 1680 |
1667 return z.Phi( | 1681 return z.Phi( |
1668 MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1682 MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1669 d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1683 d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1670 graph()->NewNode(m->Int32Mod(), left, right, d.if_false))); | 1684 graph()->NewNode(m->Int32Mod(), left, right, d.if_false))); |
1671 } | 1685 } |
1672 | 1686 |
1673 trap_->ZeroCheck32(wasm::kTrapRemByZero, right); | 1687 trap_->ZeroCheck32(wasm::kTrapRemByZero, right, position); |
1674 | 1688 |
1675 Diamond d( | 1689 Diamond d( |
1676 graph(), jsgraph()->common(), | 1690 graph(), jsgraph()->common(), |
1677 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | 1691 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
1678 BranchHint::kFalse); | 1692 BranchHint::kFalse); |
1679 d.Chain(*control_); | 1693 d.Chain(*control_); |
1680 | 1694 |
1681 return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1695 return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1682 graph()->NewNode(m->Int32Mod(), left, right, d.if_false)); | 1696 graph()->NewNode(m->Int32Mod(), left, right, d.if_false)); |
1683 } | 1697 } |
1684 | 1698 |
1685 Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right) { | 1699 Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right, int position) { |
1686 MachineOperatorBuilder* m = jsgraph()->machine(); | 1700 MachineOperatorBuilder* m = jsgraph()->machine(); |
1687 if (module_ && module_->asm_js()) { | 1701 if (module_ && module_->asm_js()) { |
1688 // asm.js semantics return 0 on divide or mod by zero. | 1702 // asm.js semantics return 0 on divide or mod by zero. |
1689 if (m->Uint32DivIsSafe()) { | 1703 if (m->Uint32DivIsSafe()) { |
1690 // The hardware instruction does the right thing (e.g. arm). | 1704 // The hardware instruction does the right thing (e.g. arm). |
1691 return graph()->NewNode(m->Uint32Div(), left, right, graph()->start()); | 1705 return graph()->NewNode(m->Uint32Div(), left, right, graph()->start()); |
1692 } | 1706 } |
1693 | 1707 |
1694 // Explicit check for x % 0. | 1708 // Explicit check for x % 0. |
1695 Diamond z( | 1709 Diamond z( |
1696 graph(), jsgraph()->common(), | 1710 graph(), jsgraph()->common(), |
1697 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | 1711 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
1698 BranchHint::kFalse); | 1712 BranchHint::kFalse); |
1699 | 1713 |
1700 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1714 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1701 graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, | 1715 graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, |
1702 right, z.if_false)); | 1716 right, z.if_false)); |
1703 } | 1717 } |
1704 return graph()->NewNode(m->Uint32Div(), left, right, | 1718 return graph()->NewNode( |
1705 trap_->ZeroCheck32(wasm::kTrapDivByZero, right)); | 1719 m->Uint32Div(), left, right, |
1720 trap_->ZeroCheck32(wasm::kTrapDivByZero, right, position)); | |
1706 } | 1721 } |
1707 | 1722 |
1708 Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right) { | 1723 Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right, int position) { |
1709 MachineOperatorBuilder* m = jsgraph()->machine(); | 1724 MachineOperatorBuilder* m = jsgraph()->machine(); |
1710 if (module_ && module_->asm_js()) { | 1725 if (module_ && module_->asm_js()) { |
1711 // asm.js semantics return 0 on divide or mod by zero. | 1726 // asm.js semantics return 0 on divide or mod by zero. |
1712 // Explicit check for x % 0. | 1727 // Explicit check for x % 0. |
1713 Diamond z( | 1728 Diamond z( |
1714 graph(), jsgraph()->common(), | 1729 graph(), jsgraph()->common(), |
1715 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | 1730 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
1716 BranchHint::kFalse); | 1731 BranchHint::kFalse); |
1717 | 1732 |
1718 Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right, | 1733 Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right, |
1719 z.if_false); | 1734 z.if_false); |
1720 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | 1735 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
1721 rem); | 1736 rem); |
1722 } | 1737 } |
1723 | 1738 |
1724 return graph()->NewNode(m->Uint32Mod(), left, right, | 1739 return graph()->NewNode( |
1725 trap_->ZeroCheck32(wasm::kTrapRemByZero, right)); | 1740 m->Uint32Mod(), left, right, |
1741 trap_->ZeroCheck32(wasm::kTrapRemByZero, right, position)); | |
1726 } | 1742 } |
1727 | 1743 |
1728 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { | 1744 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right, int position) { |
1729 if (jsgraph()->machine()->Is32()) { | 1745 if (jsgraph()->machine()->Is32()) { |
1730 return BuildDiv64Call( | 1746 return BuildDiv64Call( |
1731 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), | 1747 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), |
1732 MachineType::Int64(), wasm::kTrapDivByZero); | 1748 MachineType::Int64(), wasm::kTrapDivByZero, position); |
1733 } | 1749 } |
1734 trap_->ZeroCheck64(wasm::kTrapDivByZero, right); | 1750 trap_->ZeroCheck64(wasm::kTrapDivByZero, right, position); |
1735 Node* before = *control_; | 1751 Node* before = *control_; |
1736 Node* denom_is_m1; | 1752 Node* denom_is_m1; |
1737 Node* denom_is_not_m1; | 1753 Node* denom_is_not_m1; |
1738 Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | 1754 Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
1739 jsgraph()->Int64Constant(-1)), | 1755 jsgraph()->Int64Constant(-1)), |
1740 &denom_is_m1, &denom_is_not_m1); | 1756 &denom_is_m1, &denom_is_not_m1); |
1741 *control_ = denom_is_m1; | 1757 *control_ = denom_is_m1; |
1742 trap_->TrapIfEq64(wasm::kTrapDivUnrepresentable, left, | 1758 trap_->TrapIfEq64(wasm::kTrapDivUnrepresentable, left, |
1743 std::numeric_limits<int64_t>::min()); | 1759 std::numeric_limits<int64_t>::min(), position); |
1744 if (*control_ != denom_is_m1) { | 1760 if (*control_ != denom_is_m1) { |
1745 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, | 1761 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, |
1746 *control_); | 1762 *control_); |
1747 } else { | 1763 } else { |
1748 *control_ = before; | 1764 *control_ = before; |
1749 } | 1765 } |
1750 return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right, | 1766 return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right, |
1751 *control_); | 1767 *control_); |
1752 } | 1768 } |
1753 | 1769 |
1754 Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right) { | 1770 Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right, int position) { |
1755 if (jsgraph()->machine()->Is32()) { | 1771 if (jsgraph()->machine()->Is32()) { |
1756 return BuildDiv64Call( | 1772 return BuildDiv64Call( |
1757 left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()), | 1773 left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()), |
1758 MachineType::Int64(), wasm::kTrapRemByZero); | 1774 MachineType::Int64(), wasm::kTrapRemByZero, position); |
1759 } | 1775 } |
1760 trap_->ZeroCheck64(wasm::kTrapRemByZero, right); | 1776 trap_->ZeroCheck64(wasm::kTrapRemByZero, right, position); |
1761 Diamond d(jsgraph()->graph(), jsgraph()->common(), | 1777 Diamond d(jsgraph()->graph(), jsgraph()->common(), |
1762 graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | 1778 graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
1763 jsgraph()->Int64Constant(-1))); | 1779 jsgraph()->Int64Constant(-1))); |
1764 | 1780 |
1765 Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right, | 1781 Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right, |
1766 d.if_false); | 1782 d.if_false); |
1767 | 1783 |
1768 return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), | 1784 return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), |
1769 rem); | 1785 rem); |
1770 } | 1786 } |
1771 | 1787 |
1772 Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right) { | 1788 Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right, int position) { |
1773 if (jsgraph()->machine()->Is32()) { | 1789 if (jsgraph()->machine()->Is32()) { |
1774 return BuildDiv64Call( | 1790 return BuildDiv64Call( |
1775 left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()), | 1791 left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()), |
1776 MachineType::Int64(), wasm::kTrapDivByZero); | 1792 MachineType::Int64(), wasm::kTrapDivByZero, position); |
1777 } | 1793 } |
1778 return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right, | 1794 return graph()->NewNode( |
1779 trap_->ZeroCheck64(wasm::kTrapDivByZero, right)); | 1795 jsgraph()->machine()->Uint64Div(), left, right, |
1796 trap_->ZeroCheck64(wasm::kTrapDivByZero, right, position)); | |
1780 } | 1797 } |
1781 Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right) { | 1798 Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right, int position) { |
1782 if (jsgraph()->machine()->Is32()) { | 1799 if (jsgraph()->machine()->Is32()) { |
1783 return BuildDiv64Call( | 1800 return BuildDiv64Call( |
1784 left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()), | 1801 left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()), |
1785 MachineType::Int64(), wasm::kTrapRemByZero); | 1802 MachineType::Int64(), wasm::kTrapRemByZero, position); |
1786 } | 1803 } |
1787 return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right, | 1804 return graph()->NewNode( |
1788 trap_->ZeroCheck64(wasm::kTrapRemByZero, right)); | 1805 jsgraph()->machine()->Uint64Mod(), left, right, |
1806 trap_->ZeroCheck64(wasm::kTrapRemByZero, right, position)); | |
1789 } | 1807 } |
1790 | 1808 |
1791 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right, | 1809 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right, |
1792 ExternalReference ref, | 1810 ExternalReference ref, |
1793 MachineType result_type, int trap_zero) { | 1811 MachineType result_type, int trap_zero, |
1812 int position) { | |
1794 Node* stack_slot_dst = graph()->NewNode( | 1813 Node* stack_slot_dst = graph()->NewNode( |
1795 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); | 1814 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
1796 Node* stack_slot_src = graph()->NewNode( | 1815 Node* stack_slot_src = graph()->NewNode( |
1797 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); | 1816 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
1798 | 1817 |
1799 const Operator* store_op = jsgraph()->machine()->Store( | 1818 const Operator* store_op = jsgraph()->machine()->Store( |
1800 StoreRepresentation(MachineRepresentation::kWord64, kNoWriteBarrier)); | 1819 StoreRepresentation(MachineRepresentation::kWord64, kNoWriteBarrier)); |
1801 *effect_ = | 1820 *effect_ = |
1802 graph()->NewNode(store_op, stack_slot_dst, jsgraph()->Int32Constant(0), | 1821 graph()->NewNode(store_op, stack_slot_dst, jsgraph()->Int32Constant(0), |
1803 left, *effect_, *control_); | 1822 left, *effect_, *control_); |
1804 *effect_ = | 1823 *effect_ = |
1805 graph()->NewNode(store_op, stack_slot_src, jsgraph()->Int32Constant(0), | 1824 graph()->NewNode(store_op, stack_slot_src, jsgraph()->Int32Constant(0), |
1806 right, *effect_, *control_); | 1825 right, *effect_, *control_); |
1807 | 1826 |
1808 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); | 1827 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); |
1809 sig_builder.AddReturn(MachineType::Int32()); | 1828 sig_builder.AddReturn(MachineType::Int32()); |
1810 sig_builder.AddParam(MachineType::Pointer()); | 1829 sig_builder.AddParam(MachineType::Pointer()); |
1811 sig_builder.AddParam(MachineType::Pointer()); | 1830 sig_builder.AddParam(MachineType::Pointer()); |
1812 | 1831 |
1813 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); | 1832 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
1814 Node* args[] = {function, stack_slot_dst, stack_slot_src}; | 1833 Node* args[] = {function, stack_slot_dst, stack_slot_src}; |
1815 | 1834 |
1816 Node* call = BuildCCall(sig_builder.Build(), args); | 1835 Node* call = BuildCCall(sig_builder.Build(), args); |
1817 | 1836 |
1818 // TODO(wasm): This can get simpler if we have a specialized runtime call to | 1837 // TODO(wasm): This can get simpler if we have a specialized runtime call to |
1819 // throw WASM exceptions by trap code instead of by string. | 1838 // throw WASM exceptions by trap code instead of by string. |
1820 trap_->ZeroCheck32(static_cast<wasm::TrapReason>(trap_zero), call); | 1839 trap_->ZeroCheck32(static_cast<wasm::TrapReason>(trap_zero), call, position); |
1821 trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1); | 1840 trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1, position); |
1822 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1841 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
1823 Node* load = | 1842 Node* load = |
1824 graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0), | 1843 graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0), |
1825 *effect_, *control_); | 1844 *effect_, *control_); |
1826 *effect_ = load; | 1845 *effect_ = load; |
1827 return load; | 1846 return load; |
1828 } | 1847 } |
1829 | 1848 |
1830 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { | 1849 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
1831 const size_t params = sig->parameter_count(); | 1850 const size_t params = sig->parameter_count(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1882 Node* WasmGraphBuilder::CallImport(uint32_t index, Node** args) { | 1901 Node* WasmGraphBuilder::CallImport(uint32_t index, Node** args) { |
1883 DCHECK_NULL(args[0]); | 1902 DCHECK_NULL(args[0]); |
1884 | 1903 |
1885 // Add code object as constant. | 1904 // Add code object as constant. |
1886 args[0] = Constant(module_->GetImportCode(index)); | 1905 args[0] = Constant(module_->GetImportCode(index)); |
1887 wasm::FunctionSig* sig = module_->GetImportSignature(index); | 1906 wasm::FunctionSig* sig = module_->GetImportSignature(index); |
1888 | 1907 |
1889 return BuildWasmCall(sig, args); | 1908 return BuildWasmCall(sig, args); |
1890 } | 1909 } |
1891 | 1910 |
1892 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args) { | 1911 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args, |
1912 int position) { | |
1893 DCHECK_NOT_NULL(args[0]); | 1913 DCHECK_NOT_NULL(args[0]); |
1894 DCHECK(module_ && module_->instance); | 1914 DCHECK(module_ && module_->instance); |
1895 | 1915 |
1896 MachineOperatorBuilder* machine = jsgraph()->machine(); | 1916 MachineOperatorBuilder* machine = jsgraph()->machine(); |
1897 | 1917 |
1898 // Compute the code object by loading it from the function table. | 1918 // Compute the code object by loading it from the function table. |
1899 Node* key = args[0]; | 1919 Node* key = args[0]; |
1900 | 1920 |
1901 // Bounds check the index. | 1921 // Bounds check the index. |
1902 int table_size = static_cast<int>(module_->FunctionTableSize()); | 1922 int table_size = static_cast<int>(module_->FunctionTableSize()); |
1903 if (table_size > 0) { | 1923 if (table_size > 0) { |
1904 // Bounds check against the table size. | 1924 // Bounds check against the table size. |
1905 Node* size = Int32Constant(static_cast<int>(table_size)); | 1925 Node* size = Int32Constant(static_cast<int>(table_size)); |
1906 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); | 1926 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); |
1907 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds); | 1927 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); |
1908 } else { | 1928 } else { |
1909 // No function table. Generate a trap and return a constant. | 1929 // No function table. Generate a trap and return a constant. |
1910 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0)); | 1930 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); |
1911 return trap_->GetTrapValue(module_->GetSignature(index)); | 1931 return trap_->GetTrapValue(module_->GetSignature(index)); |
1912 } | 1932 } |
1913 Node* table = FunctionTable(); | 1933 Node* table = FunctionTable(); |
1914 | 1934 |
1915 // Load signature from the table and check. | 1935 // Load signature from the table and check. |
1916 // The table is a FixedArray; signatures are encoded as SMIs. | 1936 // The table is a FixedArray; signatures are encoded as SMIs. |
1917 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] | 1937 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] |
1918 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 1938 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
1919 const int fixed_offset = access.header_size - access.tag(); | 1939 const int fixed_offset = access.header_size - access.tag(); |
1920 { | 1940 { |
1921 Node* load_sig = graph()->NewNode( | 1941 Node* load_sig = graph()->NewNode( |
1922 machine->Load(MachineType::AnyTagged()), table, | 1942 machine->Load(MachineType::AnyTagged()), table, |
1923 graph()->NewNode(machine->Int32Add(), | 1943 graph()->NewNode(machine->Int32Add(), |
1924 graph()->NewNode(machine->Word32Shl(), key, | 1944 graph()->NewNode(machine->Word32Shl(), key, |
1925 Int32Constant(kPointerSizeLog2)), | 1945 Int32Constant(kPointerSizeLog2)), |
1926 Int32Constant(fixed_offset)), | 1946 Int32Constant(fixed_offset)), |
1927 *effect_, *control_); | 1947 *effect_, *control_); |
1928 Node* sig_match = graph()->NewNode(machine->WordEqual(), load_sig, | 1948 Node* sig_match = graph()->NewNode(machine->WordEqual(), load_sig, |
1929 jsgraph()->SmiConstant(index)); | 1949 jsgraph()->SmiConstant(index)); |
1930 trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match); | 1950 trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position); |
1931 } | 1951 } |
1932 | 1952 |
1933 // Load code object from the table. | 1953 // Load code object from the table. |
1934 int offset = fixed_offset + kPointerSize * table_size; | 1954 int offset = fixed_offset + kPointerSize * table_size; |
1935 Node* load_code = graph()->NewNode( | 1955 Node* load_code = graph()->NewNode( |
1936 machine->Load(MachineType::AnyTagged()), table, | 1956 machine->Load(MachineType::AnyTagged()), table, |
1937 graph()->NewNode(machine->Int32Add(), | 1957 graph()->NewNode(machine->Int32Add(), |
1938 graph()->NewNode(machine->Word32Shl(), key, | 1958 graph()->NewNode(machine->Word32Shl(), key, |
1939 Int32Constant(kPointerSizeLog2)), | 1959 Int32Constant(kPointerSizeLog2)), |
1940 Int32Constant(offset)), | 1960 Int32Constant(offset)), |
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2554 reinterpret_cast<uintptr_t>(module_->instance->globals_start + | 2574 reinterpret_cast<uintptr_t>(module_->instance->globals_start + |
2555 module_->module->globals[index].offset)); | 2575 module_->module->globals[index].offset)); |
2556 const Operator* op = jsgraph()->machine()->Store( | 2576 const Operator* op = jsgraph()->machine()->Store( |
2557 StoreRepresentation(mem_type.representation(), kNoWriteBarrier)); | 2577 StoreRepresentation(mem_type.representation(), kNoWriteBarrier)); |
2558 Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val, | 2578 Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val, |
2559 *effect_, *control_); | 2579 *effect_, *control_); |
2560 *effect_ = node; | 2580 *effect_ = node; |
2561 return node; | 2581 return node; |
2562 } | 2582 } |
2563 | 2583 |
2564 | |
2565 void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index, | 2584 void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index, |
2566 uint32_t offset) { | 2585 uint32_t offset, int position) { |
2567 // TODO(turbofan): fold bounds checks for constant indexes. | 2586 // TODO(turbofan): fold bounds checks for constant indexes. |
2568 DCHECK(module_ && module_->instance); | 2587 DCHECK(module_ && module_->instance); |
2569 size_t size = module_->instance->mem_size; | 2588 size_t size = module_->instance->mem_size; |
2570 byte memsize = wasm::WasmOpcodes::MemSize(memtype); | 2589 byte memsize = wasm::WasmOpcodes::MemSize(memtype); |
2571 Node* cond; | 2590 Node* cond; |
2572 if (offset >= size || (static_cast<uint64_t>(offset) + memsize) > size) { | 2591 if (offset >= size || (static_cast<uint64_t>(offset) + memsize) > size) { |
2573 // The access will always throw. | 2592 // The access will always throw. |
2574 cond = jsgraph()->Int32Constant(0); | 2593 cond = jsgraph()->Int32Constant(0); |
2575 } else { | 2594 } else { |
2576 // Check against the limit. | 2595 // Check against the limit. |
2577 size_t limit = size - offset - memsize; | 2596 size_t limit = size - offset - memsize; |
2578 CHECK(limit <= kMaxUInt32); | 2597 CHECK(limit <= kMaxUInt32); |
2579 cond = graph()->NewNode( | 2598 cond = graph()->NewNode( |
2580 jsgraph()->machine()->Uint32LessThanOrEqual(), index, | 2599 jsgraph()->machine()->Uint32LessThanOrEqual(), index, |
2581 jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); | 2600 jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); |
2582 } | 2601 } |
2583 | 2602 |
2584 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond); | 2603 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position); |
2585 } | 2604 } |
2586 | 2605 |
2587 | |
2588 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, | 2606 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |
2589 Node* index, uint32_t offset) { | 2607 Node* index, uint32_t offset, int position) { |
2590 Node* load; | 2608 Node* load; |
2591 | 2609 |
2592 if (module_ && module_->asm_js()) { | 2610 if (module_ && module_->asm_js()) { |
2593 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). | 2611 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). |
2594 DCHECK_EQ(0, offset); | 2612 DCHECK_EQ(0, offset); |
2595 const Operator* op = jsgraph()->machine()->CheckedLoad(memtype); | 2613 const Operator* op = jsgraph()->machine()->CheckedLoad(memtype); |
2596 load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_, | 2614 load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_, |
2597 *control_); | 2615 *control_); |
2598 } else { | 2616 } else { |
2599 // WASM semantics throw on OOB. Introduce explicit bounds check. | 2617 // WASM semantics throw on OOB. Introduce explicit bounds check. |
2600 BoundsCheckMem(memtype, index, offset); | 2618 BoundsCheckMem(memtype, index, offset, position); |
2601 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), | 2619 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
2602 MemBuffer(offset), index, *effect_, *control_); | 2620 MemBuffer(offset), index, *effect_, *control_); |
2603 } | 2621 } |
2604 | 2622 |
2605 *effect_ = load; | 2623 *effect_ = load; |
2606 | 2624 |
2607 if (type == wasm::kAstI64 && | 2625 if (type == wasm::kAstI64 && |
2608 ElementSizeLog2Of(memtype.representation()) < 3) { | 2626 ElementSizeLog2Of(memtype.representation()) < 3) { |
2609 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. | 2627 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. |
2610 if (memtype.IsSigned()) { | 2628 if (memtype.IsSigned()) { |
2611 // sign extend | 2629 // sign extend |
2612 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); | 2630 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); |
2613 } else { | 2631 } else { |
2614 // zero extend | 2632 // zero extend |
2615 load = | 2633 load = |
2616 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load); | 2634 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load); |
2617 } | 2635 } |
2618 } | 2636 } |
2619 | 2637 |
2620 return load; | 2638 return load; |
2621 } | 2639 } |
2622 | 2640 |
2623 | |
2624 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, | 2641 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
2625 uint32_t offset, Node* val) { | 2642 uint32_t offset, Node* val, int position) { |
2626 Node* store; | 2643 Node* store; |
2627 if (module_ && module_->asm_js()) { | 2644 if (module_ && module_->asm_js()) { |
2628 // asm.js semantics use CheckedStore (i.e. ignore OOB writes). | 2645 // asm.js semantics use CheckedStore (i.e. ignore OOB writes). |
2629 DCHECK_EQ(0, offset); | 2646 DCHECK_EQ(0, offset); |
2630 const Operator* op = | 2647 const Operator* op = |
2631 jsgraph()->machine()->CheckedStore(memtype.representation()); | 2648 jsgraph()->machine()->CheckedStore(memtype.representation()); |
2632 store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val, *effect_, | 2649 store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val, *effect_, |
2633 *control_); | 2650 *control_); |
2634 } else { | 2651 } else { |
2635 // WASM semantics throw on OOB. Introduce explicit bounds check. | 2652 // WASM semantics throw on OOB. Introduce explicit bounds check. |
2636 BoundsCheckMem(memtype, index, offset); | 2653 BoundsCheckMem(memtype, index, offset, position); |
2637 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 2654 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
2638 store = | 2655 store = |
2639 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), | 2656 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |
2640 index, val, *effect_, *control_); | 2657 index, val, *effect_, *control_); |
2641 } | 2658 } |
2642 *effect_ = store; | 2659 *effect_ = store; |
2643 return store; | 2660 return store; |
2644 } | 2661 } |
2645 | 2662 |
2646 | 2663 |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2996 isolate->counters()->wasm_compile_function_peak_memory_bytes()->AddSample( | 3013 isolate->counters()->wasm_compile_function_peak_memory_bytes()->AddSample( |
2997 static_cast<int>(jsgraph->graph()->zone()->allocation_size())); | 3014 static_cast<int>(jsgraph->graph()->zone()->allocation_size())); |
2998 graph_zone_scope.Destroy(); | 3015 graph_zone_scope.Destroy(); |
2999 return code; | 3016 return code; |
3000 } | 3017 } |
3001 | 3018 |
3002 | 3019 |
3003 } // namespace compiler | 3020 } // namespace compiler |
3004 } // namespace internal | 3021 } // namespace internal |
3005 } // namespace v8 | 3022 } // namespace v8 |
OLD | NEW |