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