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