Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(653)

Side by Side Diff: src/compiler/wasm-compiler.cc

Issue 1915123006: [wasm] Pass byte position for trapping instructions (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698