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